zoukankan      html  css  js  c++  java
  • 一个flink作业的调优

    最近接手了一个flink作业,另外一个同事断断续续有的没的写了半年的,不着急,也一直没上线,最近突然要上线,扔给我,要调通上线。

    现状是:

    1.代码跑不动,资源给的不少,但是就是频繁反压。

    2.checkpoint经常失败。

    3.也是最严重的,跑着跑着,作业就挂了。

    接手之后,秉承着代码的业务逻辑是对的原则,开始了调优之旅,后来发现,还是要从最基本的做起,不然都是白扯。总结了如下几条意见,供自己以后反省。

    1.遵循一般的编程原则

    代码到手之后,业务逻辑部分简直不忍卒读,整个业务逻辑在一个大函数中,多达几百行,而且里面很多的if语句,一个if语句就超过一屏,而且if语句大量嵌套,其他比如大量的string的累加操作等等,其实都是编程风格中的忌讳,因此,一边是对同事的信任,一边是没勇气看这个代码,刚开始从flink的机制开始调优,没有重构代码,导致浪费了不少时间。后来还是鼓足勇气重构代码,该拆分拆分,该合并合并,才发现中间有一个HashMap一直在Put但是没有clear操作,MD,作业不崩溃才怪。

    教训:作业调优,先理解清楚业务,再者好好看懂代码,不管多乱,不然有明显的bug都不知道,至于重构,如果时间可以,尽量吧。

    2.确定最耗时的部分

    因为作业的DAG图包含6个level,首先需要确定哪个层级最耗时。因为在parse的部分频繁反压,也就是后面的一个level会处理跟不上。但当时说的是写redis,以之前的理解,redis

    应该很easy就能支持10W的并发写吧,所以虽然flink提示redis sink有问题,但还是将关注点放在了parse上,也是导致了浪费时间。后来才了解到,虽然同事告诉我是写redis,而且

    确实也用的jedis来操作,但其实后台是公司自研的一个类redis的库,而且不保存在内存中,磁盘的写入速度哪里能支持那么大的并发,网卡在瞬间往往都打满,而且写操作还是同步阻塞的,这个也同时解释了前两个问题,由于写入的并发太大,导致反压,所以速度跟不上,速度跟不上,所以在每个level都开启了64个并发,加上写的同步阻塞,checkpoint coordinator需要收到将近300个task的ck 确认才能结束,往往任何一个task的缓慢,都导致了ck的timeout而失败。

    教训:真正了解你的持久化储存,了解他能支持的最大的并发和合适的并发及其他因素。

    3.了解flink的机制

    由于checkpoint总是失败,而flink的checkpoint其实是基于RocksDB去做的,并且是异步和增量的,无论如何都觉得不应该那么容易timeout,后来开启了flink日志的debug级别才发现,ck虽然是异步的,但是需要等到上游所有的barrier都到来才会触发自己的流程,往往这个等的过程就达到分钟级,然后每一个level往后传递,就会导致最后level的task在没有

    收到barrier的时候,ck以及timeout。当然,根本的原因还是反压,导致处理的一些task处理的很慢,拖累了整个作业,毕竟barrier是和真正的数据是在一个channel中发送的,如果

    数据都积压了,barrier当然也发不下去了。

    另一个问题就是chain和slotshareing了,默认flink是开启了chain的,整个是没问题的,这样其实多个operator会在一个task里面,减少了数据传输的开销,但是在调优的时候,也就

    不太容易看出哪里是性能瓶颈,slotsharing机制是进行资源分配的策略,默认都是default,所有的task会共享一个slot,也不太好找那个task是瓶颈,将不同的task的slotshareing

    设置的不一样,就可以在每个slot中是单独的task,更容易分析是哪里出问题了。

    教训:flink默认的机制,一般都是OK的,在找问题的时候可以改,但一般不会是问题点。

    4.善用性能检测工具

    flink作业本身还是java作业,刚开始觉得跑不动的时候,将java的那些自带工具也基本都用了一遍。

    jstack,打印出线程栈,到底是哪里操作在耗时。

    jmap,打印出对象信息以及dump文件,看看具体是哪个对象在搞事。

    jstat,查看各种gc的信息,各个内存区域的使用是否正常等等。

    现在流行的框架,越来越多的使用堆外内存,而这部分内存的回收又不容易,发生泄漏很难查找。

    教训:其实保持良好的编码规范,内存出问题的可能不是那么大,更多的还是使用stack看看具体是哪里在耗时。

    5.监控

    flink有自己的metric,但是往往不够,需要在作业中添加自己的metric,看起来就会很直观。flink的debug日志,虽然会有大量的日志,但有些事情还是必须通过日志来观察。

    但这次问题的解决,关键点还在于运维同学的报警,警示数据库的tps太高,一番探讨之后,才发现用的不是真正的redis,才找到的问题的真正所在,性能立马提示,也没有了反压。

    教训:如果持久化层有监控,包括IO层,这里往往才真正是出问题的地方,至于CPU和内存,反正是在yarn上,资源不够随时添加即可,反而是IO瓶颈,前面再使劲儿,这里

    堵住了,一切都是白扯。

    这次调优,虽然最终问题解决了,但还是挺灰头土脸的,希望以后有类似的事情,能够有步骤有重点的推进。

  • 相关阅读:
    LeetCode "Palindrome Partition II"
    LeetCode "Longest Substring Without Repeating Characters"
    LeetCode "Wildcard Matching"
    LeetCode "Best Time to Buy and Sell Stock II"
    LeetCodeEPI "Best Time to Buy and Sell Stock"
    LeetCode "Substring with Concatenation of All Words"
    LeetCode "Word Break II"
    LeetCode "Word Break"
    Some thoughts..
    LeetCode "Longest Valid Parentheses"
  • 原文地址:https://www.cnblogs.com/029zz010buct/p/9774295.html
Copyright © 2011-2022 走看看