go语言服务端内存持续增长,求解惑!
最近用golang开发了一个socket服务端,主要逻辑就是接收客户端发来的数据解析后存入opentsdb中,但是跑一段时间后发现内存就会增长,而且不会被gc回收,初步判定是由于大量make []byte 导致内存不释放,代码如下,求高人解惑?
func StartTCP() error {
tcp_addr, _ := net.ResolveTCPAddr("tcp4", tcp_listen)
listener, err := net.ListenTCP("tcp4", tcp_addr)
if err != nil {
return err
}
defer listener.Close()
log.Info("start tcp listen on %s", tcp_listen)
for {
conn, err := listener.AcceptTCP()
if err != nil {
log.Error("accept error %s", err.Error())
continue
}
log.Info("new session create %s", conn.RemoteAddr().String())
go HandlerConn(conn)
}
}
func ReadPacket(conn *net.TCPConn) []byte {
head := make([]byte, 4)
_, err := io.ReadFull(conn, head)
if err != nil {
return nil
}
size := binary.BigEndian.Uint32(head)
data := make([]byte, size)
_, err = io.ReadFull(conn, data)
if err != nil {
return nil
}
return data
}
func HandlerConn(conn *net.TCPConn) {
addr := conn.RemoteAddr().String()
defer func() {
if err := conn.Close(); err != nil {
log.Error("close session error %s", err.Error())
} else {
log.Info("session closed %s", addr)
}
}()
for{
data := ReadPacket(conn)
if len(data) == 0 {
log.Warn("empty data")
return
}
go HandlerMsg(conn, data, t)
}
}
附pprof信息
(pprof) top
9.92GB of 9.93GB total ( 100%)
Dropped 359 nodes (cum <= 0.05GB)
flat flat% sum% cum cum%
9.92GB 100% 100% 9.92GB 100% main.ReadPacket
0 0% 100% 9.92GB 100% main.HandlerConn
0 0% 100% 9.92GB 100% runtime.goexit
(pprof) list main.ReadPacket
Total: 9.93GB
ROUTINE ======================== main.ReadPacket in /tmp/td- server/tcp_server.go
9.92GB 9.92GB (flat, cum) 100% of Total
. . 30: go HandlerConn(conn)
. . 31: }
. . 32:}
. . 33:
. . 34:func ReadPacket(conn *net.TCPConn) []byte {
. . 35: head := make([]byte, 4)
. . 36: _, err := io.ReadFull(conn, head)
. . 37: if err != nil {
. . 38: return nil
. . 39: }
. . 40: size := binary.BigEndian.Uint32(head)
9.92GB 9.92GB 41: data := make([]byte, size)
. . 42: _, err = io.ReadFull(conn, data)
. . 43: if err != nil {
. . 44: return nil
. . 45: }
. . 46: return data
. . 47:}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
后来opentsdb出过一次故障修复后就恢复正常了,内存使用维持在200M上下,pprof heap也稳定在2k左右,而且该现象也无法复现,只能判定是opentsdb的问题而导致内存不释放了。
1) 你用的什么版本的go,尽量升级到最新版本的go,我做的sever也是make bytes去收包,未发现明显内存泄露
2) HandlerMsg是长连接还是短链接,如果是短连接的话,把相关的资源尝试释放下。
目前的代码上看应该就是HandlerMsg出问题了,看下是否这个函数没有返回过。
handleMsg得贴出来 data释不释放取决于还有没有对象引用 另外这个程序有2个问题
1. conn在handleMsg里还需要使用 但很可能conn提前就被close了
2. 调用handleMsg没必要再起一个goroutine了吧
go HandlerMsg(conn, data, t)
中的go
去掉试试,我觉得可能是HandlerConn
中定义了一个内部函数defer func()
,它关闭conn
后可能会导致HandlerMsg
中的conn
不可用,另外由于HandlerConn
已经处于退出状态,而HandlerMsg
是另外一个协程,其参数data
使用data := ReadPacket(conn)
中的data
可能会有问题吧.