关于go-zero服务自动收集问题分析
作者:Mikaelemmmm 发布时间:2024-04-26 17:29:51
前言
对于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的服务监控告警,内存占用比较高,这时候我打开grafna看到服务内存累计占用的确异常,如下图:
这时候到线上找到这个服务的服务器,执行了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
go-zero微服务最佳实践项目:https://github.com/Mikaelemmmm/go-zero-looklook
来源:https://blog.csdn.net/jj546630576/article/details/128093394


猜你喜欢
- 这里给大家分享的是使用python实现将100以内的质数挑选出来代码非常简单,就不多废话了。"""使用filt
- python 判断三个数字中的最大值,具体代码如下所示:#判断三个数中最大值n1= int(input('please enter
- 看代码吧~import torchprint(torch.__version__)补充:pytorch不同版本安装以及版本查看一:基于con
- 下面对实现页面定时跳转(也称倒计时跳转)做一下总结,各种定时跳转代码记录如下: (1)使用setTimeout函数实现定时跳转(如下代码要写
- 本文实例讲述了JavaScript内置对象math,global功能与用法。分享给大家供大家参考,具体如下:学习要点:1.Global对象2
- 首先新建一个dataframe:In[8]: df = pd.DataFrame({'name':list('ABC
- 下面就是简单的例子,这里提供2中方法:test.htm &
- 定义一个变量,直接输出会输出变量的属性,并不能输出变量值。那么怎么输出变量值呢?请看下面得意import tensorflow as tf
- cv的xdm可以直接翻到 需求 和 代码 用,想看中间的分析就老实往下看吧little 背景最近在做毕设,需要将几百篇整体结构差不多的文章中
- PyTorch加载模型model.load_state_dict()问题希望将训练好的模型加载到新的网络上。如上面题目所描述的,PyTorc
- 实例如下所示:import pandas as pdimport reimport mathdframe1 = pd.read_excel(
- 本文实例为大家分享了JavaScript实现烟花特效的具体代码,供大家参考,具体内容如下本特效使用面向对象编程分析OOA点击触发事件烟花运动
- 问:怎样才能取得局域网中所有SQL Server的实例?答:请参考以下的具体步骤:SmoApplication.EnumAvailableS
- vscode是一款非常轻量级的编辑器,你可以通过安装甚至自己编写一些小的插件来满足各种不同的使用需求,使用起来非常简介方便。方式一:图形安装
- 前言本篇文章,阐述一下Flask中数据库的迁移为什么要说数据库迁移呢?比如我们以前有一个数据库,里面的信息有 id, name现在我想再加一
- asyncio介绍熟悉c#的同学可能知道,在c#中可以很方便的使用 async 和 await 来实现异步编程,那么在p
- 什么是函数重载?简单的理解,支持多个同名函数的定义,只是参数的个数或者类型不同,在调用的时候,解释器会根据参数的个数或者类型,调用相应的函数
- 语义分割是对图像中的每一个像素进行分类,从而完成图像分割的过程。分割主要用于医学图像领域和无人驾驶领域。和其他算法一样,图像分割发展过程也经
- Go 语言教程Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。Go是从2007年末由Robert Griesemer,
- 一,进程的理论基础一个应用程序,归根结底是一堆代码,是静态的,而进程才是执行中的程序,在一个程序运行的时候会有多个进程并发执行。进程和线程的