高CPU/高内存问题排查场景

高CPU

  1. 业务类型问题
    • 死循环
    • 死锁
  2. 大量计算密集型任务
    • 图像处理
    • 视频转码
  3. 大量并发线程
  4. 内存不足
  5. 频繁GC(内存不足,导致频繁GC)

高内存

  • 内存泄漏
  • 大量文件上传/下载

工具使用

  • pprof
  • 火焰图观察
  1. 使用 go tool pprof 来分析:
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
-- 分析堆内存
go tool pprof http://localhost:6060/debug/pprof/heap

在生成的 pprof 交互式界面中,可以使用命令如 top、list 和 web 来查看热点函数和调用图。 2. 分析 Goroutine 状态: 高 CPU 使用可能由过多的 Goroutine 引起。可以使用 pprof 或 runtime/pprof 包获取 Goroutine 的快照:

go tool pprof http://localhost:6060/debug/pprof/goroutine
  1. 检查锁竞争: 如果程序中的并发部分存在锁竞争,会导致 CPU 利用率过高。可以通过 pprof 生成的锁分析报告进行检查
go tool pprof http://localhost:6060/debug/pprof/block
  1. 检查内存泄漏:
    • 内存泄漏会导致程序的内存使用不断增长。使用 pprof 可以帮助识别是否存在内存泄漏。
    • 在程序中记录堆快照,并分析内存分配情况,找出是否有未释放的对象或数据结构。
  2. 优化内存使用:
    • 检查是否有不必要的数据存储在内存中,考虑使用更高效的内存管理策略。
    • 使用内存池(sync.Pool)来减少内存分配和释放的开销。
  3. 分析程序中的大对象和长寿命对象:
    • 查找大对象(如大切片、映射、结构体)以及长寿命对象(生命周期很长的对象),它们可能导致内存使用过高。
  4. 调优 GC 设置:
    • 在一些情况下,GC(垃圾回收)设置可能影响内存使用。可以通过调整 GOGC 环境变量来控制 GC 的频率:
    export GOGC=100
    

火焰图使用

火焰图的基本结构

  1. X 轴(横轴):
    • 表示调用栈的深度或不同函数在调用栈中的位置。
    • 从左到右显示函数调用的层次结构,每个矩形的宽度表示该函数占用的时间。
  2. Y 轴(纵轴):
    • 表示函数调用的深度,栈的深度越大,函数的位置越高。
    • 通常,Y 轴的上部表示栈的顶部,即调用栈的最上层,底部则表示栈的最底层。
  3. 矩形:
    • 每个矩形代表一个函数调用。矩形的宽度表示该函数在火焰图上占据的时间(或占用的内存),越宽表示函数消耗的时间越长。
    • 矩形的颜色通常表示不同的函数或模块,但颜色的具体含义可能取决于具体的火焰图工具。

阅读火焰图的步骤

  1. 定位宽矩形:
    • 关注图中最宽的矩形,它们表示消耗时间最多的函数。这些函数可能是性能瓶颈的主要来源。
  2. 查看函数调用链:
    • 从底部(调用栈的底层)向上查看函数调用链。每个函数都可能调用其他函数,火焰图帮助你识别哪些函数被频繁调用或时间占用较多。
  3. 分析函数层级:
    • 识别调用链中的热点区域。函数调用的深度和广度会影响整体性能,高度层次上的函数往往是性能的关键点。
  4. 识别函数之间的关系:
    • 通过观察函数间的调用关系,找出是否有不必要的嵌套调用或重复调用,导致时间浪费。
  5. 比较不同的快照:
    • 如果可能,比较不同时间点或不同负载下生成的火焰图,识别性能变化的模式。

示例火焰图分析

  • 宽矩形:如果你看到一个矩形很宽,表示这个函数的执行时间较长。检查这个函数是否在代码中频繁调用。
  • 顶部的矩形:顶部的矩形是最上层函数调用,它们可能有很多子调用。查找这些函数,看看它们是否有可以优化的地方。
  • 高深度的矩形:如果某些矩形位于较高的层次,表示它们在调用链的较深处。分析这些函数,检查是否有深层次的递归或复杂逻辑。