go 内存泄露

事件回顾

  • 9.15号晚18点服务端发版
  • 9.16号晚21点监控显示自发版后服务器 TCP_alloc 指标一路飙升至40K(如图)

问题分析

看到 tcp_alloc 指标异常,初步怀疑有tcp连接创建后未关闭,应该是上次发版写了什么代码导致的。回顾此次发版清单,问题应该出现在了daemon服务心跳上报上。

daemon服务是一个业务监控服务,通过监听etcd中注册的服务状态变更,向企业微信用户发送消息提醒。在此之前由于消息提醒协程panic异常退出,导致Ad服务停止后消息提醒未正常发出,造成生产P3事故。本次发版通过增加每3秒心跳保活机制,双重保证在服务中断后,消息提醒能正常发出(代码如下)

复制代码
func KeepAliveWithMp() {
	var keepAliveWithMpUrl, _ = config.String("keepAliveWithMpUrl")
	if keepAliveWithMpUrl == "" {
		return
	}
	ticker := time.NewTicker(3 * time.Second)
	for range ticker.C {
		_, _ = http.Get(keepAliveWithMpUrl + "?runningKey=" + getRunningKey())
	}
	ticker.Stop()
}

问题出现在了 http.Get 请求发出后未读取响应主体,也没有关闭此次tcp连接,导致一直在创建新的tcp连接,一个get请求会创建两个goroutine,导致内存泄露。

此处有两种修复方式,一是在http请求完了之后主动关闭此次连接释放资源,另一种则是读取响应主体后复用改链接

代码修复

复制代码
// 方式一
func KeepAliveWithMp() {
	var keepAliveWithMpUrl, _ = config.String("keepAliveWithMpUrl")
	if keepAliveWithMpUrl == "" {
		return
	}
	ticker := time.NewTicker(3 * time.Second)
	for range ticker.C {
		resp, _ := http.Get(keepAliveWithMpUrl + "?runningKey=" + getRunningKey())
		_ = resp.Body.Close()
	}
	ticker.Stop()
}


// 方式二
func KeepAliveWithMp() {
	var keepAliveWithMpUrl, _ = config.String("keepAliveWithMpUrl")
	if keepAliveWithMpUrl == "" {
		return
	}
	ticker := time.NewTicker(3 * time.Second)
	for range ticker.C {
		resp, _ := http.Get(keepAliveWithMpUrl + "?runningKey=" + getRunningKey())
		_,_ = ioutil.ReadAll(resp.Body)
	}
	ticker.Stop()
}

后期预警

通过每小时检测一次服务器 TCP_alloc 指标,当超过30K 后发送短信提醒,避免再次出现该异常。

复制代码
// TCP_alloc 指标查看方式
cat /proc/net/sockstat 

sockets: used 3621
TCP: inuse 2833 orphan 5 tw 1792 alloc 3354 mem 489
UDP: inuse 9 mem 4
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0
相关推荐
CoderIsArt6 分钟前
C#环境中部署MQTT客户端
开发语言·c#
考虑考虑17 分钟前
arthas使用
java·运维·后端
HugoStudio_SWAN29 分钟前
【按键反馈】C++ 实现键盘烟花秀
开发语言·c++·学习·程序人生
李昊哲小课36 分钟前
Spring Boot 4 旅游主题实战教程 阶段三:数据持久化
spring boot·后端·mybatis·旅游
AI 编程助手GPT40 分钟前
Bun 1.4 正式发布:从 Zig 改写为 Rust,内置浏览器、图片处理和并行测试
开发语言·人工智能·后端·ai·chatgpt
运维开发笔记42 分钟前
7.1 Go Map 基础
golang
paopaokaka_luck1 小时前
基于springboot3+vue3的飞行器模型实验室预约管理系统(协同过滤算法、Echarts图形化分析)
开发语言·推荐算法
lingchen19061 小时前
用MATLAB r2010b和r2016b求解微分方程组
开发语言·算法·matlab
ttwosix1 小时前
JavaEE初阶 多线程 3
java·开发语言
峥嵘life1 小时前
Android16 系统 APEX 模块调试总结
android·大数据·开发语言