http - 每个持久连接的 HTTP 内存使用

标签 http memory go profile

我正在编写一个发送 Server-Sent Events 的 Go 网络服务器给一大堆客户。我希望它支持数以万计的同时连接。这是我的代码(它只是保持连接打开并发送保持事件事件):

func handleTest(w http.ResponseWriter, r *http.Request) {
    h := w.Header()
    h.Set("Content-Type", "text/event-stream; charset=utf-8")
    h.Set("Cache-Control", "no-cache, no-store, must-revalidate")
    h.Set("Connection", "keep-alive")

    flusher := w.(http.Flusher)
    notifier := w.(http.CloseNotifier)

    flusher.Flush()

    // Just send keep-alives.
    keepAliveTime := 5 * time.Second
    keepAlive := time.NewTimer(keepAliveTime)
    defer keepAlive.Stop()

    for {
        select {
        case <-notifier.CloseNotify():
            // The connection has been closed.
            return

        case <-keepAlive.C:
            if _, err := io.WriteString(w, "event: keep-alive\ndata: null\n\n"); err != nil {
                log.Println(err)
                return
            }
            flusher.Flush()
            keepAlive.Reset(keepAliveTime)
        }
    }
}

对于 1000 个连接,Windows 报告每个连接大约使用 70 kB RAM。如果我添加我实际正在做的所有事情(还有另一个 goroutine 和一些小事件编码函数),它会膨胀到每个连接 300 kB。这似乎很多。这里有 1000 个连接是 pprof heap 说的:

14683.25kB of 14683.25kB total (  100%)
Dropped 12 nodes (cum <= 73.42kB)
Showing top 10 nodes out of 23 (cum >= 512.19kB)
      flat  flat%   sum%        cum   cum%
11091.50kB 75.54% 75.54% 11091.50kB 75.54%  io.copyBuffer
    2053kB 13.98% 89.52%     2053kB 13.98%  net/http.newBufioWriterSize
     514kB  3.50% 93.02%      514kB  3.50%  net/http.newBufioReader
  512.56kB  3.49% 96.51%   512.56kB  3.49%  runtime.makeslice
  512.19kB  3.49%   100%   512.19kB  3.49%  net.newFD
         0     0%   100% 11091.50kB 75.54%  io.Copy
         0     0%   100%  1540.19kB 10.49%  main.main
         0     0%   100%   512.19kB  3.49%  net.(*TCPListener).AcceptTCP
         0     0%   100%   512.19kB  3.49%  net.(*netFD).accept
         0     0%   100%   512.19kB  3.49%  net.(*netFD).acceptOne

所以我有几个问题:

  1. 为什么内存使用率看起来如此之高。我原以为每个连接大约 10 kB。
  2. 为什么 pprof 认为堆是 14 MB,而 Windows 却说内存使用是 70 MB?剩下的是堆栈吗?
  3. 有什么方法可以将 HTTP 响应的控制权转移到中央 goroutine,并在不关闭连接的情况下从 handleTest() 返回?这会节省我的内存,还是 http.ResponseWriter 对象中的所有内存?

编辑:对于 3. 看起来我可以使用 Hijacker

编辑 2:我尝试使用 Hijacker 重新实现它。它将每个连接的内存使用量减少到大约 10 kB,这更加合理!

最佳答案

Why does pprof think the heap is 14 MB, but Windows says the memory use is 70 MB? Is the rest the stack?

除了堆,还有Go运行时,栈,代码段。此外,操作系统可能会分配比实际需要更多的资源。另外,Windows 报告的内存量是常驻内存还是操作系统内存分配的总量?

关于http - 每个持久连接的 HTTP 内存使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34785048/

相关文章:

php - 脚本在 HTTP 服务器上的可见性

Python 列出异常内存使用情况

memory - 关于redis如何使用momery的一些问题

c# - 发送矩阵的方向...转换为度数?弧度?没有小数点的东西?

正则表达式查找长度为 n 的重复数

ios - Swift 3 无法读取 HTTP Post 请求数据

jquery - Elasticsearch CORS绝望

http - gRPC 服务器错误处理程序 golang

反射:按字符串构造

dictionary - 如何找出 'map[string][][]int' 是否有值