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

阿里妹导读:云计算场景下的大规模分布式系统中,网络异常、磁盘IO异常、时钟跳变、操作系统异常乃至软件本身可能存在bugs等,均给分布式系统正确运行带来了挑战。持续的监控报警完善是打造稳定高可用分布式系统过程中非常重要的工作,这个也就要求我们研发同学从细节处入手,本文将介绍的场景是针对线上报警的一丝异常,抽丝剥茧找到内存泄露的root cause,全程48小时,跟进修复了潜在风险隐患,并进一步丰富完善监控报警体系的过程。

1、问题初现

该风险隐患在2019年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:

$grep Closure -r  proxy | grep Env
proxy/io_handler.h:    typedef common::Closure<void, Env*>  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,并持续跟进风险修复,这样一定可以锤炼出更加稳定的分布式系统。“路漫漫其修远兮,吾将上下而求索”,与诸君共勉。


原文链接
本文为阿里云原创内容,未经允许不得转载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/517140.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我的程序跑了 60 多小时,就是为了让你看一眼 JDK 的 BUG 导致的内存泄漏

来源 | why技术荒腔走板大家好&#xff0c;我是 why&#xff0c;老规矩&#xff0c;先来一个简短的荒腔走板&#xff0c;给冰冷的技术文注入一丝色彩。上面图片中这个正在奔跑的少年&#xff0c;是正在参加校运会的我&#xff0c;那一年我 18 岁&#xff0c;高三。参加的项目是…

Flutter+Serverless端到端研发架构实践

Serverless&#xff08;无服务架构&#xff09;被誉为下一代云计算&#xff0c;自概念推出以来&#xff0c;因为能带来研发交付速度提升与成本的降低在业内异常火爆。闲鱼客户端基于Flutter进行架构演进与创新&#xff0c;通过Flutter统一Android和iOS双端提升研发效能之后&…

Go 开发关键技术指南 | 为什么你要选择 GO?(内含超全知识大图)

导读&#xff1a;从问题本身出发&#xff0c;不局限于 Go 语言&#xff0c;探讨服务器中常常遇到的问题&#xff0c;最后回到 Go 如何解决这些问题&#xff0c;为大家提供 Go 开发的关键技术指南。我们将以系列文章的形式推出《Go 开发的关键技术指南》&#xff0c;共有 4 篇文…

小程序开发(10)-之热力图解决方案、手绘图

原本是用别人用canvas画的热力图的https://github.com/rover95/wxapp-heatmap&#xff0c;但是问题有点多&#xff0c;热力图的颜色&#xff0c;卡顿、叠加、渲染失败等&#xff0c;所以就弃用了&#xff0c;也找了好久&#xff0c;好像大家都没有更好的提议&#xff0c;自己也…

windows下mysql8.x配置远程连接

文章目录1. 现象2. 登录mysql3.先查看下当前的用户&#xff0c;具有什么权限4.创建新的用户之后再查权限5. 赋予权限6.刷新权限&#xff0c;然后就可远程访问了1. 现象 Host ‘192.168.0.103’ is not allowed to connect to this MySQL server mysql8.x配置远程连接 2. 登…

Spark整合Ray思路漫谈

什么是Ray 之前花了大概两到三天把Ray相关的论文&#xff0c;官网文档看了一遍&#xff0c;同时特意去找了一些中文资料看Ray当前在国内的发展情况&#xff08;以及目前国内大部分人对Ray的认知程度&#xff09;。 先来简单介绍下我对Ray的认知。 首先基因很重要&#xff0c…

建设数据中台之前,建议先看这份企业数据能力测评 | 大咖说中台

作者 | 耿立超来源 | 《大数据平台架构与原型实现&#xff1a;数据中台建设实战》“我的企业目前在数据应用上处于什么水平&#xff1f;接下来应该朝哪个方向努力&#xff1f;”本文试图帮助企业决策者和IT负责人解答这一问题。今天&#xff0c;数据之于企业的重要性已经勿须多…

如何让 python 处理速度翻倍?内含代码

阿里妹导读&#xff1a;作为在日常开发生产中非常实用的语言&#xff0c;有必要掌握一些python用法&#xff0c;比如爬虫、网络请求等场景&#xff0c;很是实用。但python是单线程的&#xff0c;如何提高python的处理速度&#xff0c;是一个很重要的问题&#xff0c;这个问题的…

Zipkin 存储追踪数据至 MySQL

下载zipkin-mysql数据库脚本 https://github.com/openzipkin/zipkin/tree/master/zipkin-storage/mysql-v1/src/main/resources 创建数据库名称为zipkin&#xff0c;字符集编码&#xff1a;utf8mb4 初始化脚本 -- -- Copyright 2015-2019 The OpenZipkin Authors -- -- Licen…

Spring Cloud Alibaba 新一代微服务解决方案

本篇是「跟我学 Spring Cloud Alibaba」系列的第一篇&#xff0c; 每期文章会在公众号「架构进化论」进行首发更新&#xff0c;欢迎关注。 1、Spring Cloud Alibaba 是什么 Spring Cloud Alibaba 是阿里巴巴提供的微服务开发一站式解决方案&#xff0c;是阿里巴巴开源中间件…

它估值25亿!被马云领投,是华为“老战友”,网友:也许股价能超茅台!

最近一条新闻被炒的沸沸扬扬&#xff1a;十年以来中国最大IPO&#xff0c;中芯国际将融资532亿元&#xff01;何为IPO&#xff1f;翻译即为一家公司第一次向全社会公开售出它的股份。买的人越多&#xff0c;代表着社会对其信心越大。为什么2020年&#xff0c;能爆发这样1场最大…

RabbitMQ 最新版安装 (Linux环境)

文章目录一、Erlang1. Erlang下载2. Erlang 上传并解压3. 验证rabbitmq依赖是否安装4. 安装rabbitmq依赖5. Erlang 编译、安装6. Erlang 配置环境变量7. Erlang 验证二、RabbitMQ2.1. RabbitMQ 下载2.2. RabbitMQ 上传并解压2.3. RabbitMQ 配置2.4. 配置环境变2.5. 启动 Rabbit…

双11 背后的全链路可观测性:阿里巴巴鹰眼在“云原生时代”的全面升级

导读&#xff1a;作为一支深耕多年链路追踪技术 (Tracing) 与性能管理服务 (APM) 的团队&#xff0c;阿里巴巴中间件鹰眼团队的工程师们见证了阿里巴巴基础架构的多次升级&#xff0c;每一次的架构升级都会对系统可观测性能力 (Observability) 带来巨大挑战&#xff0c;而这次的…

一切转型始于数据和模型 | 2020 MATLAB EXPO 中国线上用户大会:即将上线

2020 MATLAB EXPO 中国线上用户大会一切转型始于数据和模型2020 年 7 月 21-24 日 | 线上直播MATLAB 和 Simulink&#xff0c;作为业界普遍使用的科学计算与模型仿真软件&#xff0c;已被全球的工程师和科学家们广泛应用于加快汽车、航空、电子、金融服务、生物医药以及其他行业…

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架

从编程开发的角度来说&#xff0c;Apache Dubbo &#xff08;以下简称 Dubbo &#xff09;首先是一款 RPC 服务框架&#xff0c;它最大的优势在于提供了面向接口代理的服务编程模型&#xff0c;对开发者屏蔽了底层的远程通信细节。同时 Dubbo 也是一款服务治理框架&#xff0c;…

Zipkin 基于MQ存 储链路信息至 MySQL

RabbitMQ 最新版安装 (Linux环境) https://gblfy.blog.csdn.net/article/details/120498390 启动rabbitmq 队列是空的 数据库表是无数据的 启动nacos 应用集成rabbitMQ 父工程导入依赖 <!-- 消息队列通用依赖 --><dependency><groupId>org.springframewo…

标签编辑新工具:如何使用控制台标签编辑器(Tag editor)

创建阿里云资源时&#xff0c;您可以给资源绑定标签。已经创建的资源&#xff0c;也可以在资源列表页面或者通过API&#xff0c;批量的添加、更改和删除标签。当遇到如下更为复杂问题和场景&#xff0c;该如何快速解决标签问题呢&#xff1f; 资源跨度大&#xff0c;需要跨资源…

炸裂!这些大厂跪求的人才太牛了!

今年所有的互联网公司都在ALL in AI&#xff0c;百度、腾讯、阿里巴巴、京东等互联网巨头都在四处挖掘AI人才。AI的岗位需求很多&#xff0c;几乎每天都有数百个JD放出。而亿欧智库发布的《2020全球人工智能人才培养研究报告》提到&#xff0c;至今为止AI的人才储备仍跟不上需求…

60TB 数据量的作业从 Hive 迁移到 Spark 在 Facebook 的实践

Facebook 经常使用分析来进行数据驱动的决策。在过去的几年里&#xff0c;用户和产品都得到了增长&#xff0c;使得我们分析引擎中单个查询的数据量达到了数十TB。我们的一些批处理分析都是基于 Hive 平台&#xff08;Apache Hive 是 Facebook 在2009年贡献给社区的&#xff09…

阿里主管通知我试用期延期……

阿里妹导读&#xff1a;接下来的文章是一篇发布在阿里内网里的文章。花木是一位走出体制的博士&#xff0c;讲述自己Landing的经历。今天&#xff0c;她将这段经历分享给大家&#xff0c;告诉我们&#xff1a;脸先着地又怎样&#xff0c;哪有那么多坦途&#xff1b;最美的&…