Skip to main content

Java相关日志

Flink的工作原理分析

Submitted by taotao on Thu, 10/22/2020 - 20:13

这篇文章主要总结下最近学习的Flink工作原理。

首先要问一个问题,Flink在内存里都干了哪些事情?

  1. 对记录进行排序、聚合、哈希;
  2. 对接受到的数据进行序列化和反序列化;
  3. 在Java里,高效的序列化工具有Avro或者Kyro, 但是Flink为了追求高效而自己开发了一套序列化工具,数据在内存磁盘之间传输或者网络之间传输之后,不再需要反序列化,接受方可以直接操作序列化后的数据;

 

在Java世界里,处理处理比较大的数据量必然会导致GC,而GC必然会导致计算效率的下降,如何解决这个问题?

Envoy代理Jetty9出现的503问题的分析

Submitted by taotao on Sat, 02/15/2020 - 19:36

概述

最近公司在进行压力测试摸底每个服务的最大并发能力,在压力测试的过程中发现出现了大量的503现象,大概每次压测中会有3%-8%的503错误,经过调查分析,发现这是由于后端的Java服务主动关闭了connection,导致前端的代理Envoy拿着一个已经被关闭的connection发送请求,从而导致产生了503的现象。要解决这个问题的需要将服务端的idle timeout值设置的要大于前段代理服务器的idle timeout的值。下面是这个问题的解决的详细过程的描述。

详细过程

测试部门的同事在压力测试的时候发现返回了大量的503错误,服务的架构是:后端的服务是Java的,采用的是Jetty 9,前端的服务器是Envoy,当我接手这个问题的时候,压测的同事说,这个Java服务只有被Envoy代理才会返回503,如果直接压测Java服务,不会出现503,因此我把重点放在了Envoy代理上面。

GC算法之CMS总结

Submitted by taotao on Sun, 08/25/2019 - 08:37

概述

在之前的一篇文章,解决JVM内存泄漏的问题中,涉及到了GC的问题,为了把GC切底弄清楚,花了不到2个星期的业余时间,把这一块的知识复习了一下,所以现在开始对GC中的CMS算法做下总结,原来计划是上个周周末写这篇文章的,但是因为有其他事情,总是不断打断这个计划,于是一直拖到了8月份的下旬了。

JVM的垃圾回收算法有很类别,比如:并行垃圾回收、stop-the-world、并发垃圾回收,垃圾回收器可以是这个类别中的的一种或者多种的组合,因为我经常使用的是CMS垃圾回收器,因此我这里详细介绍CSM垃圾回收算法。阅读完本文你会了解如下的内容:

  1. 什么是CMS,它是为了解决什么问题而出现的?
  2. CMS是如何工作的?
  3. CMS使用过程中会经常遇到什么问题,我们需要如何避免这种问题?

 

关于JVM内存泄漏之GC优化问题提出

Submitted by taotao on Fri, 06/28/2019 - 12:14

概述

根据上一篇文章,将JVM升级到212版本,并追加设置了-Xmx和-Xms参数之后,生产环境的JVM内存一直维持在300-800M之间,高负载和低负载的实例,内存开销都在这个范围之内。所以从这两天的线上验证的现象来看是符合预期的,证实了之前的猜测是正确的(之前的结论参考:JVM的内存泄漏调查)。

详细分析

下面我将结合听云监控上的数据进行分析和论证。

下图是内存开销,可以看出内存开销在500M范围以下。

tingyun_memory_size

下面是Eden区域的内存开销,可以看出eden区大小在250M之内。

JVM的内存泄漏调查

Submitted by taotao on Wed, 06/26/2019 - 19:18

概述

        最近这半个月生产环境的服务出现了一个比较奇怪的现象,相同的一个服务,有两个实例,其中一个实例的负载比较高,RPM有500-1000左右,另一个实例的RPM在20-50之间,其中低负载的实例吃的内存比较多,能吃到8G左右的内存,另一个高负载的实例,内存稳定维持在2-3个G,吃内存比较高的那个服务,运维在日常巡检的时候发现会手动重启一次服务,避免服务出现OOM的问题。因为这个问题比较频繁,所以反馈到研发这边。这个问题的经过分析定位,排除日志堆积的问题、排除是听云探针的问题之后,把原因定位在了JVM内存自动增长导致的问题,因为根据监控平台上可以看到GC的回收频次很低,因为一旦JVM可用的内存不够,如果没有设置最大可用内存,那么JVM就会自动增长,而自动增长内存后,就不会达到GC触发的条件,这样就导致内存一直增长,而没有垃圾回收的问题。

详细的分析过程

         首先让运维通过利用jmap的方式将JVM的内存信息dump出来,

jmap -dump:format=b,file=文件名.dump 进程id 

经过分析发现了听云的对象占用了大概20%左右的内存空间:

微服务中的API编织问题

Submitted by taotao on Thu, 05/16/2019 - 21:43

问题概述

在最近的工作中,碰到了一个同事反馈的问题,就是说我们目前在使用微服务的概念设计系统的架构,那么每个服务都是一个业务边界比较垂直服务,打个比方我们商城中有订单服务、商品服务、促销服务、评论服务,那么问题来了,比如我们在商品的详情页面需要聚合来自商品、评论、促销等服务的数据之后,才能返回商品详情页所需要的数据,这么多的微服务,我们需要在商品详情服务中每次有新的请求过来时,每次都调用一遍吗?如果每次都调用一遍,那么这些服务的网络通信开销会很大,而且每次都要对数据做大量的集合遍历计算,对性能会产生很严重的影响,所以我们需要找到一种方式,在微服务的架构设计下,能够高效的提供数据给商品详情服务。

如何解决

API网关模式

如果聚合这些数据?有两个方式,其中之一就是通过利用API网关聚合多个服务之间的数据,然后再给商城的商品详情服务使用。API网关可以将数据缓存起来,提升效率。 具体的做法可以参考下图:

Java应用升级使用MySQL8后遇到的时区问题的解决过程

Submitted by taotao on Tue, 01/08/2019 - 12:57

问题的场景描述

Java应用的数据库服务从MySQL Server 5.7升级到MySQL Server 8后, 同时升级了对应的mysql的驱动, 之后就出现了Java应用写入数据库的时间比当前的时间少了13个小时,这个问题是由于mysql server没有指定时区, 而导致mysql使用了system的默认时区,默认时区:CST,即美国中部时间。最后是通过在mysql 的配置文件my.cnf中加入了时区的配置后,问题得到解决。下面是问题的解决分析过程描述。

Druid的存活检测问题

Submitted by taotao on Sun, 12/30/2018 - 10:52

概述

在Druid数据库连接池中有两个参数,分别为: testWhileIdle,timeBetweenEvictionRunsMillis 根据字面意思理解是连接池会定时的对处于idle状态的连接进行一次存活检测, 目的是为了防止返回一个已经关闭的JDBC的连接给应用使用。 但是在本地验证该参数的行为的时后,发现并不是如上的期望。 如果配置了该参数,Druid会在每一次应用获取连接的时后,进行一次存活检测, 如果发现连接不可用,那么就从connection pool中重新获取一个connection返回给应用。 如下是本地的验证的一个过程。

验证过程

在本地启动Java应用,应用直连数据库,配置Druid每间隔30秒进行一次链接检测, 配置数据库的max_timeout为60秒,validationQuery为SELECT 1,如下:

kingshard的连接问题调查(二)

Submitted by taotao on Wed, 12/26/2018 - 12:35

继续之前的分析 kingshard的连接问题调查(一) 中的推测,是由于JDBC的connection pool中的链接失效导致发生如下错误

communications link failure the last packet sent successfully to the server was 0 milliseconds ago

为了验证这个推测,在本地模拟了一个测试场景,具体如下:

  • 将Mysql Server的超时时间调整为30秒
  • 将应用中JDBC连接池(Druid)连接最大闲置检查时间间隔设置为60秒
  • 应用启动后,等待30秒之后再去访问一个有数据库查询的Http接口

当过了30秒之后,Mysql服务端就有如下的日志信息: