golang 内存泄漏以及异常退出的问题解决

项目要求要求开发一个agent来监控主机的性能,这个agent最好是编译好后能直接在主机上运行,所以选择了用go来编写。由于第一次用go,这里面踩了不少坑。

内存泄漏

当agent部署到主机上的时候,运行一段时间就停掉了,而且还没有错误提示,最后在阿里云这个主机的监控图形中看到,这个主机的内存是慢慢向上的,等内存使用率接近100%的时候,内存突然降了下来,当时就怀疑当内存使用率接近100%的时候,agent就会被停掉,然后内存得以释放。

利用linux命令找到这个agent的内存变化,发现随着时间的增长,它的内存是不断上升的,和前面的怀疑是一致的,查找到agent的进程id,然后用  top -p 12440  ,12440是进程的进程id。
ps -ef|grep cloudMonitor
top -p 12440

这个agent是利用定时任务将监控到的数据传输到其他工程,当时就怀疑是定时任务导致的内存泄漏,在网上查找go的time.NewTicker也会出现很多说当不调用t.top就会造成内存泄漏,我当时确实没有defer t.Stop()这行代码,加上这行代码后,改造成了下面的代码,:

func main() {
	durationTime := 2*time.Second
	t := time.NewTicker(durationTime)
	defer t.Stop()
	for{
		<-t.C
		fmt.Println("执行业务逻辑,发送http请求")
	}
}

满以为问题得到解决,但是过段时间后,发现内存还是在不断升高,问题没有解决,最后想到了java的发送hhtp请求后一般都会调用close方法的,一检查发现go发送http请求的时候没有调用close方法,后面再到网上查找,有人确实出现过发送http请求后,没有调用close方法导致内存泄漏的,最后再在发送完http请求后加上了defer resp.Body.Close()

reqCountBytes, err :=json.Marshal(obj) // 把请求结构体解析为json
	if err != nil {
		log.Info("marshal failed. the error info: ",err)
	}
	log.Info("==================分割线===================")
	log.Info(string(reqCountBytes))
	//"application/json"
	resp,err := http.Post(url,"application/json", bytes.NewReader(reqCountBytes)) // 调用rest接口
	if err != nil {
		log.Info("发送数据推送报错:",err)
	}
	defer resp.Body.Close()

最后启动agent监控agent内存的使用率,发现agent的内存使用率没怎么变化过。
 

go有点和java不一样的就是,当如果不对go的异常进行捕获的话,go会退出运行,也就是进程会死掉。这个agent利用定时任务获取主机的信息然后利用http将信息传输到数据中心,如果数据中性挂掉的话,这个agent由于http请求被拒绝也会挂掉,这样就很不好了,因为如果我改了数据中心的代码需要重启,那agnet都会挂掉,然后等数据中心重启完成后,再重启agent,这样明显不合理,所以这里需要对go抛出的异常进行捕获,够没有像java那样有try cach ,但go有panic,defer,recover,这里的panic就等于java中throws的作用,defer就等于java中finally的作用,代码改造成下面的样子:
 

idleDuration := time.Duration(num) * time.Second
	idleDelay := time.NewTimer(idleDuration)
	defer idleDelay.Stop()

	for {
		func() {
			idleDelay.Reset(idleDuration)
			defer func() {
				if r := recover(); r != nil {
					log.Errorf("捕获到的错误:%s\n", r)
				}
			}()
			select {
				case <-idleDelay.C:
					sendUrlData(name,cloudType,url,num)
			}
		}()
	}

这算是水了一篇博客,主要是弄这个agent弄了很久,感觉今天才算完善的差不多了。以上就是我遇到的一些比较大的问题,并得到了解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值