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)
        }
    }()
    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:}

go socket服务端 socket

神之金坷垃 9 years, 2 months ago

目前的代码上看应该就是HandlerMsg出问题了,看下是否这个函数没有返回过。

名字真好吃 answered 9 years, 2 months ago

1) 你用的什么版本的go,尽量升级到最新版本的go,我做的sever也是make bytes去收包,未发现明显内存泄露
2) HandlerMsg是长连接还是短链接,如果是短连接的话,把相关的资源尝试释放下。

侵食ドルチェ answered 9 years, 2 months ago

Your Answer