|
|
51CTO旗下网站
|
|
移步端
创造专栏

惊魂48小时,阿里工程师如何紧急定位线上内存泄露?

必发娱乐登入场景下的广大分布式系统中,网络异常、光盘IO独特、时钟跳变、操作系统异常乃至软件本身可能生存bugs等,平均给分布式系统正确运行带来了挑战。

笔者:朱云锋| 2019-12-20 09:12

必发娱乐登入场景下的广大分布式系统中,网络异常、光盘IO独特、时钟跳变、操作系统异常乃至软件本身可能生存bugs等,平均给分布式系统正确运行带来了挑战。接轨的监察报警完善是打造稳定高可用分布式系统过程中特有关键的上班,其一也就要求我们研发同学从细节处入手,本文将介绍的面貌是针对线上报警的一针异常,抽丝剥茧找到内存泄露的root cause,全程48小时,紧跟修复了潜在风险隐患,并进一步增长完美监控报警体系的经过。

1、题材初现

该风险隐患在必发娱乐手机版10月上旬某天开始浮现,不到24小时之年华里,值班同学陆续接受多个线上电话报警,表现某业务集群中分布式协调服务进程异常:

  • 14:04:28,报警显示一台Follower意外退出当前Quorum,穿过选举重新进入Quorum;
  • 16:06:35,报警显示一台Follower发生意外重启,守护进程拉起后,重新进入Quorum;
  • 02:56:42,报警显示一台Follower发生意外重启,守护进程拉起后,重新进入Quorum;
  • 12:21:04,报警显示一台Follower意外退出当前Quorum,穿过选举重新进入Quorum;
  • ……
  • 下图展示了该分布式协调服务的体系架构,此后端是基于Paxos贯彻的边缘维护功能模块,前者代理客户端与竞争性服务单元的通信,支持服务能力水平扩展性。出于后端分布式一致性服务单元由5台Master机械组成,可以容忍同时2台机械挂掉,故此上述报警均没有意识对劳动可用性产生影响。但是,在短时间之内频繁发生单个Master劳务进程异常,其一对于服务稳定性是个极大隐患,特别是对于作业调度强依赖分布式协调服务的某业务。由此,咱们开始集中人力重点调查这个题目。

    咱们第一排除了网络问题,穿过tsar命令查看机器上网络各项指标正常,穿过内部的网络平台查看机器上联网络设备以及网络链路也均是正常状态。返回日志来分析,咱们从Leader日志中找到了线索,上述报警时间点,平均有“Leader再接再厉关闭了与Follower的通信通道”这么一个事件。

    很自然地,咱们想知道为什么会频繁发生Leader关闭与Follower打电话通道的风波,答案同样在日记中:Follower长时间没有发送请求给Leader,包括Leader发给过来的心跳包的回答,因此被Leader确认为异常Follower,进而关闭与之通信通道,名将他踢出当前Quorum。

    好了,如今得以直观地说明触发报警原因了:Follower长时间与Leader失联,触发了脱离Quorum逻辑(如果退出Quorum经过比较慢的话,进一步会触发直接退出进程逻辑,很快恢复)。

    这就是说新的问题来了,该署Followers为什么不回答轻量的心跳请求呢?当下没有直接的日记来解答我们的疑惑,还好,有间接信息:出题目前Follower的日记输出发生了长时间的间歇(超过了触发退出Quorum的阈值),其一在对分布式协调服务有着频繁请求访问的某业务集群中几乎是不可想象的!咱们更愿相信下端进程hang住了,而不是压根没有用户请求打过来。

    在没有其他更多调查思路的情况下,基于后端分布式一致性服务单元是基于java贯彻的实情,咱们查看了Follower发生问题时间段的gc日志,结果找到了原因:java gc相关的ParNew耗资太久(同一天日志已经把查处,下图是该机器上的类似日志),咱们掌握java gc经过是有个STW(Stop-The-World)公有制的,除了垃圾收集器,其他线程全部挂起,其一就能够解释为什么后端Follower点程会临时hang住。

    虽然我们的java先后申请的初步内存较大,但是实际分配的是虚拟内存,ParNew耗资太久一个很大可能性是机械上实际物理内存不足了。

    按照这个思路,咱们进一步在Follower机械上采取top命令查看进程内存占用情况,结果发现机器上混合部署之前端Proxy经过使用的内存已经达到整机66%+(此刻后端一致性进程实际占用的物理内存也已经达到30%控制)。

    进一步查看系统日志,意识有的机器上前端Proxy经过已经发生过因为内存不足的OOM错误而把系统KILL的风波,至此问题开始定位,咱们开始转向调查前端Proxy内存泄露的题材。

    2、工作风险

    该工作对分布式协调服务的劳务意识功能是重度依赖的。以本次调查的工作集群为例,另一方面集群注册的劳务地址数达到240K,剖析地址的外向会话数总量达到450W,故此,分布式协调服务的祥和直接影响着集群内业务作业的正常化运行。

    在明显了分布式协调服务Proxy经过存在内存泄露风险之后,咱们紧急巡检了点上其他集群,意识该问题并非个例。大促在即,其一风险隐患不能够留到双十一的年华点,在gcore了前者Proxy现场后,咱们做了燃眉之急变更,逐台重启了上述风险集群的前端Proxy经过,暂且先缓解了点上风险。

    3、深入调查

    继承回来调查问题,咱们在重启Proxy经过之前,gcore保留了现场(此地要强调一下,点上gcore永恒要当心,特别是内存占用如此大的经过,很容易造成请求处理hang住,咱们基于的设想是该分布式协调服务的客户端是有超时重试机制的,故此可以承受一定时长之gcore借鉴)。

    因为前端Proxy重大的内存开销是基于订阅实现的迅猛地址缓存,故此,咱们第一通过gdb翻开了保障了缓存的unordered_map大大小小,结果这个大小是符合预期的(正如监控指标显示的,估计下来这个空间占用不会超过1GB),天南海北达不到能够撑起如此内存泄漏的程度。这点我们进一步通过strings core文件也得到了证实,string目标空间占据并不多,刹那间,咱们的检察陷入了困境。

    这会儿我们想到了兄弟团队某大神的名著,介绍了在线上环境调查C/C++使用程序内存泄露问题(可能会有同学提到valgrind其一工具干嘛不用?第一这个神器在测试环境是不可或缺之,但是终究是可能生存一些漏掉的面貌发布上点了导致线上内存泄露。此外,大型项目中会暴露valgrind运作太慢的题材,甚至导致程序不能正常工作),此地提供了另一番摄氏度来考察内存泄露:虚表。每个有虚函数的类都有个虚表,同一个类的一切对象都会指针指向同一个虚表(普通是每个对象的明天8个字节),故此统计每个虚表指针出现的亮度就足以了解这样的目标被分配了有好多,多少异常的话那么就存在内存泄露的可能性。

    大神提供了一番内存泄露排查工具(表明一下,其一工具基于规整的tcmalloc的内存管理措施来分析的),穿过符号表找到每个vtable,故此可以了解虚表地址,即每个虚函数类的目标前8字节的情节,其一工具厉害的中央在于摆脱了gdb依托,直接根据应用程序申请的一切内存块分析,找到所有泄露内存块地址,进一步统计出每个虚表对应类的目标数目。现实这个工具实现细节不再赘述,末了我们统计出来的一切出现频率超过10W的虚表信息,找到了罪魁祸首:其一common::closure的目标泄露了高达16京+。

    根据closure的底数类型信息,咱们很快定位到了切实的类CheckCall:

          
    1. $grep Closure -r proxy | grep Env  
    2. proxy/io_handler.h: typedef common::Closure CheckCall; 

    有关这个目标的宽广泄露,固定到最后原因其实是跟我们对Proxy日志分析有关,咱们在日记中发现了大量非法访问请求:客户端尝试解析某个角色注册的劳务地址,但是却采取不当的集群名参数。在单个Proxy机械上1s时光里最多刷出4000+这样的错误日志,这就是说会不会是因为持续走到这样错误路线导致的目标内存泄露呢?

    对比这块的编码,咱们精心研究了一下,果然,CheckCall目标正常是会走到执行逻辑的(common::closure在推行之后自动会析构掉,自由内存),但是在特殊路径下,譬如上面的不法集群名,这就是说这个函数会直接return少,应当的CheckCall目标不会把析构,随着业务持续访问,也就继续产生内存泄露。

    4、风险修复

    其一题目的rootcause固定之后,摆在我们面前的修补方法有两个:

    1)工作方停止错误访问行为,避免分布式协调服务前端Proxy接轨走到错误路线,触发内存泄露;

    2)过去末Proxy代码层面彻底修复掉这个bug,下一场对点上分布式协调服务Proxy做一轮升级;

    提案二之状况比较大,大促之前已经没有足够的升级换代、灰度窗口,末了我们挑选了方案一,根据日志中连续出现的这个非法访问路径,咱们联系了工作方,援助调查确认业务哪些客户端进程在采取不当集群名访问分布式协调服务,进一步找到了原因。末了业务方通过紧急上点hotfix,消除了错误集群名的走访行为,该工作线分布式协调服务前端Proxy经过内存泄露趋势因此可以控制,风险解除。

    当然,重点之修补方式还是要下前端Proxy针对CheckCall的突出路径下的拍卖,咱们的修补方式是遵守函数实现单一出口原则,在特殊路径下也同样执行该closure,在推行逻辑里面判断错误码直接return,即不履行实际的CheckCall逻辑,只触发自我析构的所作所为。该修复在双十一之后将颁布上点。

    5、题材小结

    稳定工作要求从细节处入手,要求我们针对线上劳动的每一枝报警或者是劳动指标的一针异常,能够追根溯源,找到root cause,并继续跟进风险修复,这样一定可以锤炼出更加安定的分布式系统。“路漫漫其修远兮,吾将上下而求索”,与诸君共勉。

    【本文为51CTO专栏作者“阿里巴巴官方技术”原创稿件,转载请联系原作者】

    戳这里,瞧该作者更多好文

    【编纂推荐】

    1. 高考工程师不懂AI,还有未来吗?
    2. 瞧美国国防部如何增强网络空间安全
    3. 网络攻击成本仅一顿饭钱
    4. 为什么网络风险是高管必需关心的题材
    5. 网络安全市场急缺的六种非技术专业人才
    【义务编辑: 武晓燕 TEL:(010)68476606】

    点赞 0
  • 内存  工程师  网络
  • 分享:
    大家都在看
    猜你喜欢
  • 
       
       
       
       
    
       


    1. <object id="8326c160"></object>