记录一次生产Flink反压解决过程

问题表现

提交flink作业后,程序开始运行,照常打开web界面进行查看,运行了一会,开始彪红,出现很繁忙的工作状态,上游开始变灰,反压开始出现。。。

解决思路

正常情况下,通过分析自己的代码,就大概能够知道是哪里出的问题,比如有没有耗时很严重的操作,有无和外部系统交互的操作等。

还有一种情况就是,倾斜导致的反压,这个可以观察subtask处理的数据量来直观的判断,比如下面这种情况

能够很明显的看到5号子任务处理的量和其他的都相差比较大,那就说明在这个算子的上游,数据分布不均匀,或者你keyby采用的策略不太好,需要重新均衡设计一下。不过截图中的还好,因为大部分都是很均匀的,如果是只有一两个子任务处理的数量很多,其他的都很少,那就需要改变一下了。

如果都不是上面的问题,一时之间难以看出是哪里出的问题,那可以按照下面的步骤来

解开算子链

正常情况下,flink会自动合并算子链,除非遇到hash,或者并行度不一致,才会拆开。这里为了更加方便的定位到具体是哪一个算子在处理时遇到了问题,需要在代码中增加如下代码来解开算子链

env.disableOperatorChaining();

打开火焰图

火焰图可以帮助我们分析,哪些操作占用cpu的时间片资源比较多,导致处理缓慢。可以通过在flink的作业提交命令中,添加参数来开启。如下

添加参数 rest.flamegraph.enabled=true 即可。

然后我们重新打包提交作业,再次打开web界面。

此时也可以借助火焰图观察我们代码中到底哪里耗时比较多,比较严重

选中红色的算子,然后在右侧的具体面板中选择火焰图

可以看到,是MongoDB的连接耗时比较多。

火焰图中,如果是淡黄色,意味着执行效率还可以,如果是橘红,或者大红色,就意味着有些耗时的内容在里面。可以通过颜色的深浅来判断是哪里出的问题。

知道问题出在MongoDB,就去代码中具体定位,我代码中使用到MongoDB的地方如下

// 查询mongo获取解密后的vin
long start = System.currentTimeMillis();
String vin = MongoUtil.getVinByCarid(mongoClient, yRcanbus.getVin());
long end = System.currentTimeMillis();
LOGGER.info("@@@@@@@@@@ mongo耗时:" + (end - start));

程序会去查询MongoDB获取想要的信息,MongoDB的连接是在open方法中一次性初始化完成的。那现在看来就是每来一条数据都要去查询MongoDB,猜测是这个操作拖慢了flink处理的速度。我在代码中添加了前后耗时的打印,重新运行后,看日志如下

虽然看着MongoDB没什么,才几十毫秒,但是上游kafka的数据来的很快,这里取一个平均时长30毫秒,一秒钟也不过才处理33条数据,这点并发的情况下,是非常缓慢的。

这里有人要问为啥要每来一条数据都要查询MongoDB,为什么不能缓存起来。这和业务有关系,MongoDB中的数据量不是一直不变的,而是动态增加的。

所以,综上,有了如下的解决方案。

解决方案

查询MongoDB后,将数据缓存到状态中,再来数据时,优先从状态中查询,查询不到,再去MongoDB中查询,查询后一样缓存到状态中。

目前看来MongoDB中的数据不算很多,所以就算完全缓存,问题也不大。后面随着数据的增长,可以考虑使用支持增量状态存储的rocksdb,或者使用别的技术方案。

总结

本篇文章旨在记录flink反压的发现,以及基本的解决思路等,问题是每个人都不一样的。

祝各位工作顺利,代码无bug~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值