Flink+Kafka深度调优:流处理延迟直降70%
|
文章配图,仅供参考 去年八月那台流处理集群,卡得跟老式缝纫机似的——我原以为只是Kafka broker的GC参数没调好,结果拆开监控才发现,Flink checkpoint间隔设了30秒,Kafka consumer group的offset提交延迟直接飙到25秒,这俩货跟商量好了似的互相卡脖子。车间那台风扇一直在响,我戴着降噪耳机都能听见旁边老张抖腿的节奏,他手套上还粘着昨天修交换机时蹭的硬胶,看着就硌手。先说Kafka的锅。consumer group的max.poll.interval.ms默认5分钟,我们为了防重平衡设成了2分钟,结果遇上消息体突然膨胀(有次单条消息从200KB涨到1.2MB),consumer线程直接卡在poll()里,offset提交像便秘似的。我原以为调大max.poll.records就能解决,结果把参数从500改到2000后,broker的磁盘IO直接冲到90%,监控面板上那根红色曲线跟心电图似的跳——中午盒饭里有块姜,我嚼着都没味儿,满脑子都是磁盘的“咔咔”声。 后来翻Flink的源码才发现,checkpoint对齐机制才是真凶。我们用的是Exactly-Once语义,Kafka consumer的offset提交必须等所有source的checkpoint都完成,可偏偏有台机器的JVM堆内存设小了(运维小哥手滑把Xmx从8G写成4G),GC停顿时间从200ms飙到1.2秒,直接拖垮了整个对齐流程。手机在铁台上震了一下,是测试组发来的消息:“延迟又到8秒了”,我盯着屏幕上的火焰图,发现Flink的StateBackend写磁盘的线程池卡了——其实我也没拆到底,这状态后端用的是RocksDB,可监控里只显示“disk_write_stall”,具体是memtable刷盘还是SST文件合并卡住的,得看RocksDB的日志,但那天日志轮转策略没配好,最新的日志被覆盖了。 最反常识的是,把Kafka的fetch.min.bytes从1B调到32KB后,延迟反而降了。我原以为小消息应该更快,结果老李在群里甩了张图:当消息体小时,consumer需要频繁发起fetch请求,网络往返时间(RTT)占了大头;调大fetch.min.bytes后,broker会攒够32KB才返回,虽然单次延迟从2ms涨到5ms,但请求频率从每秒500次降到50次,网络开销直接砍了90%。这个我敢打包票,我们在三台不同的机器上测过,延迟曲线从“锯齿状”变成了“平滑坡”,手机震动的次数都少了。 Flink那边更邪乎。我们把taskmanager.memory.process.size从4G调到8G后,延迟从12秒降到3秒,但再往上调就没效果了——我原以为是堆外内存不够,结果把taskmanager.memory.managed.fraction从0.4调到0.6后,延迟反而涨了1秒。后来发现是Network Buffers的配置问题:我们用的是默认的2048MB,但实际需要的只有1024MB,多余的内存被JVM拿去当堆外缓存了,反而挤占了RocksDB的内存。谁把扳手掉地上了一声闷响,我蹲下去捡的时候突然想到:Flink的Network Buffers和RocksDB的block_cache是共享堆外内存的,这俩货要是抢资源,延迟不飙才怪。 最绝的是checkpoint间隔的调优。我们一开始设了10秒,结果发现checkpoint对齐时间经常超过5秒,延迟直接翻倍;改成30秒后,对齐时间降到2秒,但故障恢复时间从10秒涨到40秒——测试组的小妹急得直跺脚:“用户说延迟高,可恢复时间太长他们也受不了啊!”后来折中设了15秒,结果发现Kafka的offset提交延迟和Flink的checkpoint对齐时间刚好卡在14秒左右,形成了一个“死亡循环”:Flink等Kafka提交offset,Kafka等Flink完成checkpoint,俩货互相等,延迟直接飙到20秒。我盯着监控面板上的两条曲线,突然想起老张昨天说的:“这俩货就像俩醉汉,一个扶墙一个扶树,谁也离不开谁。” 最后是怎么解决的?把Kafka的enable.auto.commit设成false,手动提交offset,同时把Flink的checkpoint模式从EXACTLY_ONCE改成AT_LEAST_ONCE——这个型号我只在别人那儿见过,说是能牺牲一点准确性换延迟。结果还真管用:延迟从20秒降到6秒,故障恢复时间从40秒降到15秒。修完我自己都没底,让测试组跑了三天压力测试,结果没出过一次延迟超过8秒的情况。老李在群里说:“这调优跟修车似的,有时候得拆东墙补西墙,但只要墙不塌,就算成功。” 现在想想,这“70%的延迟下降”其实没那么玄乎——优胜劣汰而已。Kafka和Flink的默认参数都是给通用场景设的,真要压延迟,就得把它们的“老毛病”一个个揪出来:Kafka的offset提交机制、Flink的checkpoint对齐、Network Buffers和RocksDB的内存分配……这些参数就像车上的螺丝,有的得松半圈,有的得紧一扣,松紧度全靠经验。这个我说不准,要看运气——比如那天要是没发现JVM堆内存设错,可能还在跟GC停顿较劲呢。 下一步打算把RocksDB的配置再调调,听说把block_cache_size设成总内存的30%能降延迟,但得先测测对CPU的影响。车间那台风扇还在响,我摘了降噪耳机,听见老张在喊:“走,吃饭去!”——盒饭里估计又有姜,但这次我不怕了,延迟降了,吃啥都香。 (编辑:应用网_常德站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


浙公网安备 33038102330457号