曹大带我学 Go(8)—— 一个打点引发的事故
你好,我是小X。
曹大最近开 Go 课程了,小X 正在和曹大学 Go。
这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go。
最近线上事故频发,搞得焦头烂额,但是能用上跟曹大学的知识并定位出了问题,还是值得高兴一把的。毕竟“打破砂锅问到底”,“定位出根因”一直是技术人的优良品质。
虽然我们总是逃不过事故驱动开发的魔咒,但吃一堑长一智,看别人的事故,学到的是自己的能力。
现象
一个平凡的午高峰,服务在全量上线的过程中,碰到一个非常重要的下游接口超时(后来发现该下游也在上线,可用实例数变少,正常实例负载变高,超时了一丢丢),拿不到该拿的数据,阻塞了启动。这样,打到线上正常实例上的流量就增加了。
不大会儿,线上大量实例 OOM,报警满天飞。不得已,回滚(遇到事故,第一件事就是回滚)。没想到,回滚无效,OOM 的实例数还是一直在增加,给跪了。
中间查到服务在启动过程中,一直在尝试调那个超时的下游,就临时把超时时间加大,并取消回滚,紧急上线了一把。
之后,正常启动的实例越来越多,服务逐渐恢复。
第一天排查
发生事故之后就是排查过程了。
第一天,只查到了 OOM 的实例 goroutine 数暴涨,接口 QPS 有尖峰,比正常翻了几倍。所以,得到的结论就是接口流量太多,超过服务极限,导致 OOM。
接着尝试在预览环境压测,没有复现 OOM,gg。
结论有问题!
第二天排查
第二天运气比较好,发现了线上有一个实例在不断地重启,一看监控,发现正常启动后,5 分钟左右就 OOM 了。
有现场就不慌。
正好跟着曹大学会了如何用 pprof 查问题,马上就安排,三下五除二就搞定了。
先看 inuse_space:
虽然,这个 model 占用的内存比较高,但这是正常的业务逻辑,看了看相关的代码最近也没有改动。
所以,这个只能是果,不是因。
再看 CPU:
中间加粗的红色线条和方框就差要告诉我有问题的代码在哪一行了!图上方有调 metrics 的函数名(这里没展示出来),一搜就搜出来了。
再看了下 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)—— 一个打点引发的事故相关推荐
- 『曹大带我学 Go 』系列文章汇总
你好,我是小 X. 之前写了 11 篇跟着曹大学 Go 的文章,今天来汇总一下. 曹大的功力深厚,但能学到多少全看自己.第一期 Go 训练营也早就结束了,但学习还得继续.后面我也会继续发布这个系列,希 ...
- 曹大带我学 Go(6)—— 技术之外
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 有学员私下和我说,这个课程挺打击他的自信心.我 ...
- 曹大带我学 Go(2)—— 迷惑的 goroutine 执行顺序
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 上一篇文章我们讲了 Go 调度的本质是一个生产 ...
- 曹大带我学 Go(11)—— 从 map 的 extra 字段谈起
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 熟悉 map 结构体的读者应该知道,hmap ...
- 曹大带我学 Go(10)—— 如何给 Go 提性能优化的 pr
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 之前 qcrao 写了一篇<成为 Go ...
- 曹大带我学 Go(9)—— 开始积累自己的工具库
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 不知道你有没有这样的经验:看了很多计算机相关的 ...
- 曹大带我学 Go(7)—— 如何优雅地指定配置项
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 最近一个年久失修的库导致了线上事故,不得不去做 ...
- 曹大带我学 Go(5)—— 哪里来的 goexit
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 在学员群里,有同学在用 dlv 调试时看到了令 ...
- 曹大带我学 Go(1)——调度的本质
你好,我是小X. 曹大最近开 Go 课程了,小X 正在和曹大学 Go. 这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go. 上周课程已经开始了,曹大直播了第一期,干货满满 ...
最新文章
- 【Docker】日常记录
- java 轮询请求接口_js调用轮询接口
- 【Android Fragment】解决Fragment多层嵌套时onActivityResult无法正确回调的问题
- Python 全栈开发 -- 监控篇
- winform生成exe俩秒钟就退出_Python有多牛逼?三万多条数据,几秒钟全部搞定~
- 360搜集隐私程序员级分析,供方舟子及大众参考
- 年前的面试经历(二)
- 基于JSP的小区停车管理系统设计与实现
- 【解决问题】java.lang.ClassNotFoundException: com.Application 问题的几种解决方案
- 用计算机唱歌 丑八怪乐谱,《成都》计算器谱子 抖音计算器按出的音乐乐谱大全...
- ORACLE计算2个时间段相差时间小时、分、秒
- 触屏计算机显示器CDU,科技:关于电脑显示器你所需要知道的
- java使用网易企业邮箱,发送邮件失败
- linux tar exclude 多个目录,tar 过滤多个文件目录 打包
- 换个好看舒服的jupter notebook风格
- 深入浅出SQL读书笔记
- 开机后黑屏看不到桌面_开机后黑屏看不到桌面怎么解决
- 54-基于51单片机GSM模块的家庭防火防盗报警系统
- 考研数学公式Day2:对1/(a+bcosx)的积分
- 订餐App回顾与总结
热门文章
- 边缘计算架构_更灵活的自动化系统架构、通信和编程——在自动化领域部署边缘计算...
- 结构体位域及联合体解析
- 关于myeclipse buildpath的jar包不能复制到tomcat lib下的问题
- (二)java版spring cloud+spring boot 社交电子商务平台 - 整合企业架构的技术点
- mybatis中mapUnderscoreToCamelCase自动驼峰命名转换
- C语言之从内存角度理解不同类型的变量
- 新手站长必须养成的五个好习惯
- 6.494 - Kindergarten Counting Game
- 虚拟打印的实现-EMF转换成BMP
- AtCoder - arc098_b Xor Sum 2(尺取+位运算)