Golang Go语言中 websocket server 开启压缩内存占用高的问题
很多普通开发者, 甚至库的作者, 没有意识到 flate
算法内存占用过高的问题, 一个压缩器, 占用内存超过了 640KB !!!
package main
import (
“compress/flate”
“unsafe”
)
func main() {
writer, _ := flate.NewWriter(nil, flate.BestSpeed)
println(unsafe.Sizeof(*writer))
}
// output: 656648
我测试了一下三个 websocket package
, 10000 连接, 开启压缩, 10s 广播一次, 结果如下
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
18563 caster 20 0 1340732 225504 4000 S 0.0 5.6 16:15.86 gws-linux-amd64
18542 caster 20 0 1469756 351172 4912 S 0.0 8.8 25:17.99 gorilla-linux-a
30294 caster 20 0 4791548 1.7g 880 S 0.0 44.6 0:07.33 nhooyr-linux-am
nhooyr
降低到开 5000 连接才能正常测试
Golang Go语言中 websocket server 开启压缩内存占用高的问题
更多关于Golang Go语言中 websocket server 开启压缩内存占用高的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
虚拟机, 工具是自己写的 https://go.dev/play/p/EUC4J0XY3Mr
在这个库的基础上改了点代码 https://github.com/lxzan/wsbench
websocket server 客户端直连?一般不是还有一个 http/https 网关吗,压缩放在网关上应该会有所不同?
或者 caddy 这种,给 http 开压缩也会有类似问题吗
同样好奇
自
这个问题是有解的,http 的流行度比 ws 高一个数量级,一般不会有问题。网关只会在握手阶段解析 http header ,websocket frame 的压缩它是不管的
网关解析完整的 ws 协议并压缩帧也可以做到,性能上会差一些,具体要看文档
websocket 压缩的问题比较突出,nhooyr 的内存占用是其他两个的 5-8 倍,gorilla 也有相关 issue ,不知道要怎么复现。
这个应该算是一个老问题了 https://github.com/golang/go/issues/32371
issue 太多了看不过来😂nhooyr/websocket
的作者意识到了这个问题, 然而他没去解决
在Golang中使用WebSocket服务器时,开启压缩功能确实可能会增加内存占用,这主要是因为压缩算法需要额外的内存来进行数据块的存储和处理。针对这一问题,可以考虑以下几个方向进行优化:
-
压缩级别调整:WebSocket的压缩通常使用Per-Message Deflate扩展,它允许配置压缩级别。降低压缩级别可以减少内存占用,但可能会增加传输的数据量。根据实际需求权衡压缩率和内存使用。
-
内存池使用:实现自定义的内存池来管理压缩和解压缩过程中所需的内存。这可以有效减少内存分配和回收的开销,提高内存使用效率。
-
流量控制:通过流量控制机制限制同时处理的WebSocket连接数或消息大小,避免内存过度消耗。
-
优化数据处理:检查并优化WebSocket消息处理逻辑,确保在处理压缩数据时不会造成不必要的内存泄漏或过度分配。
-
监控与调优:使用Go的pprof等工具监控内存使用情况,定位内存占用高的代码段,并针对性地进行优化。
-
硬件升级:如果以上方法仍不能满足需求,考虑增加服务器内存或采用更高规格的硬件资源。
总之,处理WebSocket压缩带来的内存占用问题需要从多个角度综合考虑,通过合理的配置和优化,可以在保证性能的同时有效控制内存使用。