大型系统在线问题诊断与定位

标签: 系统 在线 问题 | 发表时间:2021-04-19 06:11 | 作者:Xargin
出处:https://juejin.cn/tag/%E6%9E%B6%E6%9E%84

本文是武汉 gopher meetup 的分享内容整理而成,分享内容在 “无人值守” 的两篇和其它社区分享中亦有提及。(也就是说你看过那两篇,这个可以不用看了)

先来看看苦逼的开发人员

老板说:

队友说:

外组同事说:

底层团队说:

你:

业界的思路?

混口饭吃也是不容易,既然有问题了,我们还是要解决的。要先看看有没有现成的思路可以借鉴?

Google 在 这篇论文里提到过其内部的线上 profile 流程:

架构图已经比较简单了,线上应用暴露 profile 接口,collector 定时将 profile 信息采集到二进制存储,由统一的在线平台展示。

这篇论文催生了一些开源项目和创业公司,例如在 这篇文章 中,对 continuous profiling 有很不错的解释。

我们日常的 CI 和 CD 流水线可以高频次发布线上系统,当线上有 continuous profiling 系统在运行时,每次发布我们都能够得到实时的性能快照,并与发布前的性能做快速对照。

系统的性能问题和其它技术问题一样,同样是发现得越早,解决起来就越快,损失越小。

Google Cloud 上也有 profiler 相关的 产品,是由 Go 原先的 pprof 开发者开发的,她在文章中声称每分钟对应用采集 10s 的 profile,大约有 5% 的性能损失,还是可以接受的。

简单来说,continuous profiling 带给我们的优势主要就是三点:

  • 缩短性能问题反馈周期
  • 节省服务器成本
  • 改进开发者的工作流程

有了思路,再看看有没有具体的开源产品可以参考。

相关开源产品

stackimpact-go 是社区比较早的开源项目了,不过只开源了 client 部分,所以 dashboard 和后端部分一直是一个谜,不过我们大概也能看出来,有这种曲线图形式的 profile 数据,有性能衰减时能及时发现。

conprof 其实也差不多。

profefe 也差不多。

看起来思路都一样,这个需求很简单,我们只要找监控团队帮忙做一套皮肤就可以了!

但监控团队也很无奈。

我们的方案

求人不如求己,我们需要定位的是抖动问题,那我们以 5s 为单位,把进程的 CPU 使用 (gopsutil),RSS(gopsutil),goroutine 数 (runtime.NumGoroutine),用 10 大小的环形数组保存下来,每次采集到新值时,与之前多个周期的平均值进行 diff 就可以了:

当波动率超过可以接受的范围,则认为当前进程发生了资源使用抖动,那么:

  • 若 CPU 抖动,从当前开始采集 CPU profile 5 秒
  • 若 RSS 抖动,将当前进程的 heap profile 记录下来
  • 若 goroutine 抖动,将当前进程的 goroutine profile 记录下来

一套方案做下来,还挺简单的。当我们收到模块的 CPU、内存或 goroutine 数报警时,上线到相应的实例来查看即可。

实际的案例

解码 bug

某模块突然出现了 RSS 使用飚升,上线看之后发现自动 dump 文本的 profile 中,单个对象的 inuse_space 超过了 1GB:

   // inuse_objects: inuse_space [alloc_objects : alloc_space]
1 : 1024000000 [1 : 1024000000]  git.xxx.xxx


复制代码

这是很反常的,阅读代码后发现在 decode 中没有对这些情况进行一定的防御操作,有形如下面的代码:

   var l = readLenFromPacket()
var list = make([]byte, l)


复制代码

虽然理论上 body 是可以传 1GB 的,不过内部的 RPC 框架,还是应该对这种情况进行一些限制。

CPU 尖刺

有些在线系统是定时任务调用的,所以其访问峰值非常不平均,在定时任务触发后,会有一段时间 CPU 使用非常高,有了自动 CPU profile dump,就非常容易找到具体哪里使用的 CPU 很高了。

goroutine 泄露

类似这样的 goroutine 泄露问题,也是可以很容易发现的。

deadlock(扩展)

因为我们可以采集到所有 goroutine 的栈信息,所以理论上通过遍历我们可以发现哪些 goroutine 是持锁的,例如下列代码,当发生死锁时,我们可以直接把持锁的 goroutine dump 下来,就很容易发现死锁了:

thread block(扩展)

,当线程因为调用 cgo 等原因发生了阻塞,会造成线程数暴涨,这时候我们可以将 goroutine 和 thread profile dump 下来,进行诊断。

总结

有了自动化的工具,日子更好过了。

相关 [系统 在线 问题] 推荐:

大型系统在线问题诊断与定位

- - 掘金 架构
本文是武汉 gopher meetup 的分享内容整理而成,分享内容在 “无人值守” 的两篇和其它社区分享中亦有提及. (也就是说你看过那两篇,这个可以不用看了). 混口饭吃也是不容易,既然有问题了,我们还是要解决的. 要先看看有没有现成的思路可以借鉴. Google 在 这篇论文里提到过其内部的线上 profile 流程:.

思考系统API设计的问题

- edware_love - C++博客-首页原创精华区
最近正好在思考系统API设计中考量的一些问题,. 我现在的理解是这样的,假设有巨大的真实内存. windows首先将高2G的内存自己占了,用作各种内核对象. 这2G内存共享给每个进程,但进程不能直接访问,只能通过windows给定的函数访问. : 然后每个进程都给他2G内存,进程如果创建自己的对象就放到自己那2G内存里面,如果要建立内核对象就放到共享的那高2G里面去.

搜索系统中的纠错问题

- -
纠错是搜索引擎中一个非常有特色的模块,对用户输入的内容进行改写从而让用户得到正确的结果,有的时候也会带有一些惊喜度,所以纠错技术是一个搜索体验的加分项,近期突然对这块有兴趣,所以就了解了一下. (学习周报本周停,学习内容都在这了). 人非圣贤,孰能无过,别说是搜索的时候,哪怕是我们打字、写作文的时候,都会出现错字,一般的错别字不会对最终目标带来很大影响,且出现频率很低,不拘小节的我们常常会忽略这样的小问题,但是,在搜索场景下,错别字意味着可能就搜不到内容了,对于用户而言,就是需求无法满足,造成了很差的体验,因此在搜索场景中,就很有必要去纠错.

开发者寄望Android 4.0缓解系统分化问题

- 中雨 - cnBeta.COM
美国IT网站PCWorld今天撰文称,开发者希望最新的“冰淇淋三明治”系统能够从一定程度上缓解Android目前的平台分化问题,并修复一些漏洞.

tag推荐系统的关键问题以及解决方案

- - CSDN博客推荐文章
最近在做推荐产品,读了一些论文,客观的说,扯淡的居多,基本的思路也差不多,结合工作的情况,谈一下tag推荐的产品形态、主要问题以及如何推荐. tag 的推荐系统,顾名思义,利用用户或者item的 tag信息进行推荐,涉及到两个产品形态:. 1.tag-based recommend,基于tag信息推荐item给用户.

从问题域出发认识Hadoop生态系统

- - 董的博客
Dong | 新浪微博: 西成懂 | 可以转载, 但必须以超链接形式标明文章原始出处和作者信息及 版权声明. 网址: http://dongxicheng.org/mapreduce-nextgen/rethinking-hadoop-from-problems-solved/. 本博客的文章集合: http://dongxicheng.org/recommend/.

分布式系统中的事务一致性问题

- - CSDN博客架构设计推荐文章
在分布式系统中,我们经常遇到多数据副本保持一致的问题,在我们所能找到的资料中该问题讲的很笼统,模模糊糊的,把多个问题或分类糅合在一起,难以理解. 在思考和翻阅资料后,通俗地把一致性的问题可分解为2个问题:. 1、任何一次修改保证数据一致性. 在弱一致性的算法,不要求每次修改的内容在修改后多副本的内容是一致的,对问题1的解决比较宽松,更多解决问题2,该类算法追求每次修改的高度并发性,减少多副本之间修改的关联性,以获得更好的并发性能.

关于分布式系统的数据一致性问题

- - 互联网 - ITeye博客
现在先抛出问题,假设有一个主数据中心在北京M,然后有成都A,上海B两个地方数据中心,现在的问题是,假设成都上海各自的数据中心有记录变更,需要先同步到主数据中心,主数据中心更新完成之后,在把最新的数据分发到上海,成都的地方数据中心A,地方数据中心更新数据,保持和主数据中心一致性(数据库结构完全一致).

留心那些潜在的系统设计问题

- - ITeye博客
在系统设计阶段考虑全面很难,有许多人倾向于把整个设计分成若干阶段,在迭代中完成整个设计,这本身是非常好的,但是,就如同“先做出来,以后再优化”这样的经典谎言一样,本身并无错,只是许多程序员都不习惯于真正的迭代设计和迭代优化. 举例来说,有一个日益复杂的类,每个人都修改一点点,一直到最后都没有人愿意去做重构,大家的心态都是一样的:“我只修改了一点点,为什么要我去动那么大的刀,于我没有任何好处”.

解决win7以上系统 java只获取IPv6的问题

- - 编程语言 - ITeye博客
如果系统中开启了IPV6协议(比如window7),java网络编程经常会获取到IPv6的地址,这明显不是我们想要的结果,搜索发现很多蹩脚的做法是:禁止IPv6协议. 其实查看官方文档有详细的说明:. 在实际的运用中有以下几种办法可以实现指定获取IPv4的地址:. 在java启动命令中增加一个属性配置:-Djava.net.preferIPv4Stack=true.