关于java:记录一次使用多线程调用kafka发送消息产生的内存泄漏问题

10次阅读

共计 1389 个字符,预计需要花费 4 分钟才能阅读完成。

在布控预警的需要实现里,我须要把长久化在数据库中的布控对象(身份证、姓名、手机号、imsi、faceId 等等都可别离作为布控对象)始终往 kafka 里发送,而后由 flink 进行生产,把以后的布控对象和存储的用户轨迹记录(有旅客、航班、车辆卡口、人脸等等数据)同时蕴含身份证、姓名等等信息进行比对,如果比对胜利则触发布控预警
最开始我是通过单线程发送,发现发送速度有点慢,这外面我须要把布控对象做一些解决(比方 split,flat,fitler)后才发送到 kafka,大略 30w+ 的布控对象须要十多分钟那边能力预警到,于是开始进行性能优化,应用并行流进行解决,扭转之后同样 30w 的数据这次只须要 8 秒左右就能发送实现,然而跑了一阵之后程序开始呈现报错

Received invalid metadata error in produce request on partition xxxTopic due to org.apache.kafka.common.errors.NetworkException: The server disconnected before a response was received.. Going to request metadata update now

第一眼看到这个错,我认为是 kafka 或者网络出问题了,也去看了 broker 的日志,发现是有一些对于以后 topic 被删除的谬误,然而日志级别只是一个 info,我认为是 topic 呈现谬误,又尝试了应用 kakfa 的生产命令,发现是可能失常生产的,阐明这个 topic 和 metadata 应该是没有问题的。
我也在网上搜寻着,发现很少有这个问题的阐明,然而我发现了一些特色,通过我重启后程序又是能够持续发送的,而且速度还是很快,然而跑了一会儿,开始又有这个报错了,开始是一个报错,其余的都胜利,起初是缓缓的,报错越来越多,胜利的越来越少。接着过了很久居然还产生了 nacos 的心跳超时导致服务不可用的状况。
我这时想到了之前看过的一些文章,说频繁 fullgc 可能会导致心跳申请失败的问题,最开始的时候看了 cpu 使用率,发现十分高,600% 左右,我认为是因为我的程序外面因为是有定时工作去循环发送音讯所有有点占用是失常的,没有当回事,起初我用起了 arthas 和 gc 命令,先应用 dashboard,看了下 cpu 线程,发现 gc 线程占用以及那个并行流 forkjoinpool 的线程占用十分大的 cpu 利用率,而后 full gc 次数十分多,又应用

jstat -gcutil $pid 1000

命令进行确认,开始我就发现了 old 区的占用比十分高,且 fullgc 的频率十分高,简直是几秒钟就有一次,最重要的是,最开始是能回收一些内存,随着工夫的推移,old 区占用比基线始终在增长,最初到了 100,在这个过程中我也发现了,呈现报错的频率和 old 区占用比之间是存在关系的,报错越来越多的时候,old 区被占用的越多,fullgc 越频繁。
这里我才意识到这是呈现 内存透露 的问题了吧,可能是我写的代码有点问题,于是我持续开始排查,通过

jmap dump:format=b,file=xx.hprof $pid

而后导出文件到本地,用 java visualvm 关上(也能够用 mat,我这里解析类实例的还报了堆内存不足,要改一下 /lib/visualvm/etc/visualvm.conf,把 -xms 改大点)

正文完
 0