解决golang内存溢出的方法

  

最近在项目中出现golang内存溢出的问题,主人刚开始运行时只有10多米,运行几天后,竟然达到10多了个g而且到凌晨流量变少内存也没有明显降低,内存状态呈现一种很不健康的曲线。

  

解决golang内存溢出的方法

  

解决golang内存溢出的方法

  

像这种情况肯定是golang内存溢出了,为此我持续排查了两天,终于找到问题所在,特此记录下。

  

<强>准备工作

  
      <李>一台较好的环境测试机,单台运行无污染。   <李>压测工具,无论服务是http还是websocket服务,都必须准备好压测工具模拟最真实的用户场景。   <李>将主引入net/http/pprof包,通过http访问获得goroutine,堆信息。   
     //引入pprof   进口_ "net/http/pprof”//在主要中加入   去func () {   log.Println (http。ListenAndServe (“localhost: 9999”, nil))   }()      

浏览器访问:http://127.0.0.1:9999/调试/pprof/<代码>
  

  

解决golang内存溢出的方法”> <br/>
  </p>
  <p>获取goroutine信息<代码> http://10.13.132.91:9999/调试/pprof goroutine& # 63;调试=2 </代码> <br/>
  </p>
  <p>获取堆信息<代码> http://10.13.132.91:9999/调试/pprof/堆# 63;调试=2 </代码> <br/>
  </p>
  <p>使用golang工具进行统计分析,<代码>去工具pprof -inuse_space http://127.0.0.1:9999/调试/pprof/堆> </代码。输入全球可以看出前十占用内存情况,这里我是直接输入png导出图片来查看,以便以后比较,还有两个参数可以选择,-inuse_space顾名思义是正在使用的内存,-alloc_space是已经分配的内存,本次我是一直用-inuse_space进行分析。</p>
  <p> </p>
  <p>去是一门自己gc的语言,大概两分钟会gc一次。如果有内存泄漏,无非就是两种情况。</p>
  <ol>
  <李>有goroutine泄漏,goroutine“飞”了,僵尸goroutine没有结束,这个时候在这个goroutine上分配的内存对象将一直被这个僵尸goroutine引用着,进而导致gc无法回收这类对象,内存泄漏。</李>
  <李>有一些全局(或者生命周期和程序本身运行周期一样长的)的数据结构意外的挂住了本该释放的对象,虽然goroutine已经退出了,但是这些对象并没有从这类数据结构中删除,导致对象一直被引用,无法被回收。</李>
  </ol>
  <p> </p>
  <p>首先,我利用压测工具对服务器进行100个websocket连接,模拟用户浏览行为,然后关闭连接,打开浏览器查看goroutine数量,发现新起的goroutine全部已经销毁,没有观察到有泄漏的goroutine,因此排除此情况。</p>
  <p> </p>
  <p>排除goroutine泄漏,只能是由全局状态变量引起的。再次用压测工具进行压测然后关闭,使用观察内存情况。使用<代码>去工具pprof -inuse_space http://127.0.0.1:9999/调试/pprof/堆> </代码输入<代码> png> </代码导出(在这种情况下,需要等程序gc完再导出,建议等10分钟左右)。<br/>
  </p>
  <p> <img src=解决golang内存溢出的方法