你好,我是小X。

曹大最近开 Go 课程了,小X 正在和曹大学 Go。

这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go。

最近线上事故频发,搞得焦头烂额,但是能用上跟曹大学的知识并定位出了问题,还是值得高兴一把的。毕竟“打破砂锅问到底”,“定位出根因”一直是技术人的优良品质。

虽然我们总是逃不过事故驱动开发的魔咒,但吃一堑长一智,看别人的事故,学到的是自己的能力。

现象

一个平凡的午高峰,服务在全量上线的过程中,碰到一个非常重要的下游接口超时(后来发现该下游也在上线,可用实例数变少,正常实例负载变高,超时了一丢丢),拿不到该拿的数据,阻塞了启动。这样,打到线上正常实例上的流量就增加了。

不大会儿,线上大量实例 OOM,报警满天飞。不得已,回滚(遇到事故,第一件事就是回滚)。没想到,回滚无效,OOM 的实例数还是一直在增加,给跪了。

中间查到服务在启动过程中,一直在尝试调那个超时的下游,就临时把超时时间加大,并取消回滚,紧急上线了一把。

之后,正常启动的实例越来越多,服务逐渐恢复。

第一天排查

发生事故之后就是排查过程了。

第一天,只查到了 OOM 的实例 goroutine 数暴涨,接口 QPS 有尖峰,比正常翻了几倍。所以,得到的结论就是接口流量太多,超过服务极限,导致 OOM。

接着尝试在预览环境压测,没有复现 OOM,gg。

结论有问题!

第二天排查

第二天运气比较好,发现了线上有一个实例在不断地重启,一看监控,发现正常启动后,5 分钟左右就 OOM 了。

有现场就不慌。

正好跟着曹大学会了如何用 pprof 查问题,马上就安排,三下五除二就搞定了。

先看 inuse_space:

inuse_space

虽然,这个 model 占用的内存比较高,但这是正常的业务逻辑,看了看相关的代码最近也没有改动。

所以,这个只能是果,不是因。

再看 CPU:

CPU

中间加粗的红色线条和方框就差要告诉我有问题的代码在哪一行了!图上方有调 metrics 的函数名(这里没展示出来),一搜就搜出来了。

再看了下 goroutine:

goroutine

结论还是一样的。

顺着图上的函数名,马上就在一个多重嵌套循环里找到了一处不那么显眼的打点。

metrics 打点的剧本我熟,之前看了曹大的“几个 Go 系统可能遇到的锁问题”的文章(点击阅读原文可读),逻辑大概是这样的:

由于 metrics 底层是用 udp 发送的,有文件锁,大量打点的情况下,会引起激烈的锁冲突,造成 goroutine 堆积、请求堆积,和请求关联的 model 无法释放,于是就 OOM 了。

然后我们替换 bin 上到这台 OOM 的机器,果然恢复正常了,收工!

最后看了下 metrics 的代码,其实还不是文件锁的原因。不过也差不多了,也是一把大锁,所有 goroutine 的打点都会先 append 到一个 slice 里,append 前要先加锁。

由于这个地方的打点非常多,几十万 QPS,一冲突,goroutine 都 gopark 去等锁了,持有的内存无法释放,服务一会儿就 gg 了。

总结

引发这次事故的代码其实是一年多前写的,跑了一年都没出事,这次就遇到了,你说可气不?

幸亏不是自己写的,但也要敲个警钟:我写的每一行代码,将来都可能会引发事故,一定要认真对待。

遇到 OOM 不可怕,有现场就行。拿不到现场,我也没啥好办法。实在不行,用曹大的 holmes 试试,这个工具还是很厉害的,还帮曹大贡献了个 golang 的 mr。

平时要多看相关的事故排查文章,必要的时候练习一下 pprof 工具的使用,关键的时候还是能顶用的。

好了,这就是今天全部的内容了~ 我是小X,我们下期再见~


欢迎关注曹大的 TechPaper 以及码农桃花源~

曹大带我学 Go(8)—— 一个打点引发的事故相关推荐

  1. 『曹大带我学 Go 』系列文章汇总

    你好,我是小 X. 之前写了 11 篇跟着曹大学 Go 的文章,今天来汇总一下. 曹大的功力深厚,但能学到多少全看自己.第一期 Go 训练营也早就结束了,但学习还得继续.后面我也会继续发布这个系列,希 ...

  2. 曹大带我学 Go(6)—— 技术之外

    你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 有学员私下和我说,这个课程挺打击他的自信心.我 ...

  3. 曹大带我学 Go(2)—— 迷惑的 goroutine 执行顺序

    你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 上一篇文章我们讲了 Go 调度的本质是一个生产 ...

  4. 曹大带我学 Go(11)—— 从 map 的 extra 字段谈起

    你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 熟悉 map 结构体的读者应该知道,hmap ...

  5. 曹大带我学 Go(10)—— 如何给 Go 提性能优化的 pr

    你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 之前 qcrao 写了一篇<成为 Go ...

  6. 曹大带我学 Go(9)—— 开始积累自己的工具库

    你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 不知道你有没有这样的经验:看了很多计算机相关的 ...

  7. 曹大带我学 Go(7)—— 如何优雅地指定配置项

    你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 最近一个年久失修的库导致了线上事故,不得不去做 ...

  8. 曹大带我学 Go(5)—— 哪里来的 goexit

    你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 在学员群里,有同学在用 dlv 调试时看到了令 ...

  9. 曹大带我学 Go(1)——调度的本质

    你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 上周课程已经开始了,曹大直播了第一期,干货满满 ...

最新文章

  1. 【Docker】日常记录
  2. java 轮询请求接口_js调用轮询接口
  3. 【Android Fragment】解决Fragment多层嵌套时onActivityResult无法正确回调的问题
  4. Python 全栈开发 -- 监控篇
  5. winform生成exe俩秒钟就退出_Python有多牛逼?三万多条数据,几秒钟全部搞定~
  6. 360搜集隐私程序员级分析,供方舟子及大众参考
  7. 年前的面试经历(二)
  8. 基于JSP的小区停车管理系统设计与实现
  9. 【解决问题】java.lang.ClassNotFoundException: com.Application 问题的几种解决方案
  10. 用计算机唱歌 丑八怪乐谱,《成都》计算器谱子 抖音计算器按出的音乐乐谱大全...
  11. ORACLE计算2个时间段相差时间小时、分、秒
  12. 触屏计算机显示器CDU,科技:关于电脑显示器你所需要知道的
  13. java使用网易企业邮箱,发送邮件失败
  14. linux tar exclude 多个目录,tar 过滤多个文件目录 打包
  15. 换个好看舒服的jupter notebook风格
  16. 深入浅出SQL读书笔记
  17. 开机后黑屏看不到桌面_开机后黑屏看不到桌面怎么解决
  18. 54-基于51单片机GSM模块的家庭防火防盗报警系统
  19. 考研数学公式Day2:对1/(a+bcosx)的积分
  20. 订餐App回顾与总结

热门文章

  1. 边缘计算架构_更灵活的自动化系统架构、通信和编程——在自动化领域部署边缘计算...
  2. 结构体位域及联合体解析
  3. 关于myeclipse buildpath的jar包不能复制到tomcat lib下的问题
  4. (二)java版spring cloud+spring boot 社交电子商务平台 - 整合企业架构的技术点
  5. mybatis中mapUnderscoreToCamelCase自动驼峰命名转换
  6. C语言之从内存角度理解不同类型的变量
  7. 新手站长必须养成的五个好习惯
  8. 6.494 - Kindergarten Counting Game
  9. 虚拟打印的实现-EMF转换成BMP
  10. AtCoder - arc098_b Xor Sum 2(尺取+位运算)