每日一博 | Go 服务自动收集线上问题现场
前言
对于 pprof
,相信熟悉 Go 语言的程序员基本都不陌生,一般线上的问题都是靠它可以快速定位。但是实际项目中,很多时候我们为了性能都不会开启它,但是出了问题又要靠它来分析。好在 go-zero 已经帮我们很好的集成进来了,我们只需要像开关一样去开启、关闭它即可,这样我们就可以配合运维监控,当出现 cpu、内存等异常情况时候,自动开始开启收集(比如大半夜你睡的正香的时候),那么第二天可以通过分析当时的采样还原现场,那我们看看 go-zero 是如何做的。
源码分析
我们可以看 go-zero 源码位置 https://github.com/zeromicro/go-zero/blob/master/core/proc/signals.go
func init() { go func() { ... signals := make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGTERM) for { v := <-signals switch v { ... case syscall.SIGUSR2: if profiler == nil { profiler = StartProfile() } else { profiler.Stop() profiler = nil } ... } }() }
服务启动的时候,go-zero 在 init
初始化了监听信号操作(gracefulStop
也是通过这里通知的,这里不展开讲了),可以看到在接收到 syscall.SIGUSR2
信号时候,如果是第一次就开始收集,第二次就停止收集,看到这块可能瞬间就明白了,我们只需要在服务器执行 kill -usr2 <服务进程id>
就可以开始收集这个服务的 pprof
信息了,再执行一次就停止了收集,就可以将这些文件导出到本地,使用 go tool pprof
分析。
一次线上实战
我们线上有一个 mq
的服务监控告警,内存占用比较高,这时候我打开 grafana
看到服务内存累计占用的确异常,如下图:
这时候到线上找到这个服务的服务器,执行了 ps aux | grep xxx_mq
,查询到了这个 mq
服务的进程 ID
是 21181,我们这时候就可以给这个 xxx_mq
服务发送信号收集 pprof
信息:kill -usr2 21181
第一次执行了这个命令后,在对应服务的 access.log
日志中可以看到 enable
了 pprof
,当我们再次执行 kill -usr2 21181
,access.log
日志中可以看到 disable
了 pprof
信息,这时候代表收集完成了。值得注意的是收集的信息都在 /tmp
文件夹下,以这个服务名命名的如下:
- xxxx-mq-cpu-xxx.pprof - xxxx-mq-memory-xxx.pprof - xxxx-mq-mutex-xxx.pprof - xxxx-mq-block-xxx.pprof - .......
这时候就可以下载对应的 pprof
去本地分析,可以使用 go tool pprof xxxx-mq-memory-xxx.pprof
,也可以配合 graphviz
使用 web ui
查看,由于我这边通过命令行就快速定位了问题,就没用使用 web ui
。
我使用 go tool pprof xxxx-**-mq-memory-xxx.pprof
然后进入命令行交互,使用 top 30
查看前面占用较高的资源。
前面基本是底层序列化等操作,发现主要问题集中在红色框中导致持续上涨的内存,因为业务同学在 mq
中消费完了消息又向下游其他的mq服务使用 publisher
发送一个 mq
消息,每次发送都调用一个 NewPublisher
然后在 defer close
,恰恰这个 mq
服务又大量消息消费又特别频繁,导致内存不断上涨,最终解决方案将 NewPublisher
在 svcCtx
中初始化一个 client
就可以了,没必要每次都要 NewPublisher
,世界又恢复清净了。
写在最后
想一下 go-zero 给了我们 pprof
开关,让我们很方便的实现分析问题,但是不是所有问题都是一直存在的,比如半夜突发内存、cpu 过高,早上起来服务正常了,这怎么排查?所以我们希望如果异常了,能保留问题现场,那我们是不是可以配合运维监控实现自动保存问题现场呢?比如内存、cpu 连续超过 80%
指标3分钟的话,我们就调用这个开关收集,之后我们就可以根据这个文件来分析问题了,这样就达到自动化了。
项目地址
go-zero 微服务框架: https://github.com/zeromicro/go-zero
https://gitee.com/kevwan/go-zero
go-zero 微服务最佳实践项目:https://github.com/Mikaelemmmm/go-zero-looklook
欢迎使用 go-zero
并 star 支持我们!
微信交流群
关注『微服务实践』公众号并点击 交流群 获取社区群二维码。</服务进程id>

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
snakeYAML <=1.33 存在反序列化漏洞
漏洞描述 snakeYAML 是一个将 YAML 文件与 Java 对象相互转换的开源代码库。 snakeYAML 受影响版本中的 Constructor 类由于没有对反序列化的类型进行限制,导致在处理恶意 yaml 内容时容易受到反序列化漏洞的影响。 缓解措施:使用 SnakeYaml 的 SafeConsturctor 类解析不受信任的内容 漏洞名称 snakeYAML <=1.33 存在反序列化漏洞 漏洞类型 输入验证不恰当 发现时间 2022-12-02 漏洞影响广度 小 MPS编号 MPS-2022-9425 CVE编号 CVE-2022-1471 CNVD编号 - 影响范围 org.yaml:snakeyaml@[1.4, 1.33] 修复方案 使用 SnakeYaml 的 SafeConsturctor 类解析不受信任的内容 参考链接 https://www.oscs1024.com/hd/MPS-2022-9425 https://nvd.nist.gov/vuln/detail/CVE-2022-1471 https://github.com/google/se...
- 下一篇
rkyv —— Rust 的零拷贝反序列化框架
rkyv是一个用于 rust 的零拷贝反序列化框架。 它类似于其他零拷贝反序列化框架,例如Cap'n Proto和FlatBuffers。然而,前者具有外部模式和严格限制的数据类型,而 rkyv 允许在代码中定义所有序列化类型,并且可以序列化其他类型无法序列化的各种类型。此外,rkyv 被设计为几乎没有开销,并且在大多数情况下将执行与本机类型完全相同的操作。 与serde一样,rkyv 使用 Rust 强大的特征系统来序列化数据而无需反射。尽管具有广泛的功能,但你也只需为使用的功能付费。如果你的数据检出,序列化过程可以像memcpy一样简单。与 serde 一样,这允许 rkyv 以类似于手写序列化程序的速度执行。 与 serde 不同,rkyv 生成的数据保证没有反序列化。如果你将数据写入磁盘,你只需将文件mmap写入内存,投射一个指针,你的数据就可以使用了。这使其成为高性能和 IO 密集型应用程序的理想选择。 通过 PinAPI 支持有限的数据突变,如果需要完整的突变功能,归档的值可以通过 Deserialize 真正反序列化。 rkyv 有一个 hashmap 实现,...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS关闭SELinux安全模块
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Linux系统CentOS6、CentOS7手动修改IP地址
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16