我正在编写一个发送 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
所以我有几个问题:
- 为什么内存使用率看起来如此之高。我原以为每个连接大约 10 kB。
- 为什么 pprof 认为堆是 14 MB,而 Windows 却说内存使用是 70 MB?剩下的是堆栈吗?
- 有什么方法可以将 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/