我在有TCP服务器的软件包中使用goroutines。大多数情况下,响应是很沉重的,但是当例程结束时,不会从内存中清除它。

func Handle() {
    service := ":7777"
    tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
    checkError(err)
    listener, err := net.ListenTCP("tcp", tcpAddr)
    checkError(err)
    defer listener.Close()

    for {
        conn, err := listener.Accept()
        checkError(err)
        go handleRequest(conn, db)

    }
}

func handleRequest(conn net.Conn, db *sql.DB) {
    message := make([]byte, 0, 4096)
    tmp := make([]byte, 256)
    n, err := conn.Read(tmp)
    if err != nil {
        if err != io.EOF {
            fmt.Println("read error:", err)
        }
    }
    message = append(message, tmp[:n]...)
    fmt.Println("Message Received:", string(message))
    // do something to get resp
    conn.Write(append(resp, []byte("\n")...))
    conn.Close()
    debug.FreeOSMemory()
    return
}

因此,在这种情况下,响应很大,并且可以使用10%的内存作为goroutine,因为我从数据库中获取了170.000个用户并将结果解析为JSON。但是当handleRequest仍然在内存中时,如果我不使用debug.FreeOsMemory()的话。我怀疑这是个好方法,因为它在调试包中,所以我的问题是清空内存的好方法吗,goroutine正在使用吗?我对其进行了测试,因此它不会对系统造成影响,并且无法很好地工作。如果没有,什么是好的方法?我等不及要清理GC吗?!我读了this,这就是为什么我开始使用它的原因,在第一个答案中有最后一个建议。

最佳答案

Go运行时不会“立即”将可用内存释放回操作系统,这会造成效率低下。在此处了解更多信息:Golang - Cannot free memory once occupied by bytes.Buffer

您应该让Go运行时处理此问题。如果您的应用程序不稳定而未调用 debug.FreeOsMemory() ,则存在更大的问题,即使它“看似”有所帮助,您也不应对此加以掩盖。甚至可能使情况变得更糟,好像为一个请求提供服务确实需要大量内存(在完成请求时,GC会适当释放该内存),调用FreeOsMemory()只会将其返回到运行时必须询问的操作系统。为/分配另一个请求时再次分配。如果您还没有将其交还给操作系统,它将可用于下一个请求...

尝试减少请求处理程序的内存需求。如果不可能(可疑),请限制可能需要同时处理的需要大内存的请求的数量。

看到这个问题和答案,如何做到这一点:Process Management for the Go Webserver

另外:Is this an idiomatic worker thread pool in Go?

10-07 12:41