attachments-2021-11-iwJ6Q2n9619ddb1a3882e.png

这两天用golang在写一个监控的agent,发现长时间运行后会有内存泄露的情况,着实让人郁闷半天… 要解决golang泄露的问题,要理解goalng gc那是事情,再就是利用pprof监视golang的运行环境。

这Golang GC垃圾回收我就先不多说了,等我自己深入了解了,会专门找个时间聊这事. 

在golang中用来做监控分析的库包,一般用都是pprof库包… pprof可以在两个地方引入:

  1. net/http/pprof
  2.  
  3. runtime/pprof

其实net/http/pprof中只是使用runtime/pprof包来进行封装了一下,并在http端口上暴露出来。 runtime/pprof可以用来产生dump文件,再使用go tool pprof来分析这运行日志.

使用net/http/pprof可以做到直接看到当前web服务的状态,包括cpu占用情况和内存使用情况等。

这次重点说些pprof web显示的模式,我自己主要是关注heap,profile两个数据源。

关于golang运行环境heap的信息、内存mem等

  1. http://localhost:7777/debug/pprof/heap

关于profile、cpu计算百分比等

  1. http://localhost:7777/debug/pprof/profile

上面简单介绍了pprof的监控接口,但怎么查看这些数据? 有这么几个查看方式.

交互模式, 可以通过用help查看pprof各种命令。 每次运行后拿到的数据是固定的,不会动态更新该数据。 

  1. go tool pprof http://localhost:7777/debug/pprof/heap
  2. go tool pprof http://localhost:7777/debug/pprof/profile

如果你不想使用交互模式,当然这每次都是新数据:

  1. go tool  pprof --text http://localhost:7777/debug/pprof/heap

网页查看模式:

http://localhost:7777/debug/pprof/

下面是我随便写的一段伪业务代码. 大家可以长时间运行这段代码,会发现内存在缓慢的增长中.

  1. #xiaorui.cc
  2. package main
  3.  
  4. import (
  5. "flag"
  6. "fmt"
  7. "io/IoUtil"
  8. "log"
  9. "net/http"
  10. _ "net/http/pprof"
  11. "sync"
  12. "time"
  13. )
  14.  
  15. func counter() {
  16. list := []int{1}
  17. c := 1
  18. for i := 0; i < 10000000; i++ {
  19. httpGet()
  20. c = i + 1 + 2 + 3 + 4 - 5
  21. list = append(list, c)
  22. }
  23. fmt.Println(c)
  24. fmt.Println(list[0])
  25. }
  26.  
  27. func work(wg *sync.WaitGroup) {
  28. for {
  29. counter()
  30. time.Sleep(1 * time.Second)
  31. }
  32. wg.Done()
  33. }
  34.  
  35. func httpGet() int {
  36. queue := []string{"start..."}
  37. resp, err := http.Get("http://www.163.com")
  38. if err != nil {
  39. // handle error
  40. }
  41.  
  42. //defer resp.Body.Close()
  43. body, err := IoUtil.ReadAll(resp.Body)
  44. if err != nil {
  45. // handle error
  46. }
  47. queue = append(queue, string(body))
  48. return len(queue)
  49. }
  50.  
  51. func main() {
  52. flag.Parse()
  53.  
  54. //这里实现了远程获取pprof数据的接口
  55. go func() {
  56. log.Println(http.ListenAndServe("localhost:7777", nil))
  57. }()
  58.  
  59. var wg sync.WaitGroup
  60. wg.Add(10)
  61. for i := 0; i < 100; i++ {
  62. go work(&wg)
  63. }
  64.  
  65. wg.Wait()
  66. time.Sleep(3 * time.Second)
  67. }

另外需要说的一点,pprof可以生成一个svg的矢量图,可以通过这svg图确认代码的流程及调用情况. svg是使用graphviz生成的,mac下直接brew install graphviz就能安装,centos下,yum -y install graphviz .

根据pprof的统计信息我们可以找到cpu过度计算及内存泄露的大概的点。 现在越来越觉得Golang gc有些让人摸不清头脑.  看来有必要深入学习Golang gc垃圾回收原理.

如果你想用Python开辟副业赚钱,但不熟悉爬虫与反爬虫技术,没有接单途径,也缺乏兼职经验
关注下方微信公众号:Python编程学习圈,获取价值999元全套Python入门到进阶的学习资料以及教程,还有Python技术交流群一起交流学习哦。

attachments-2022-06-jTHaEaoQ62b1387f29726.jpeg