因为工作需要,我用 openresty 做了一个websocket推送.在线上环境中存在一天几百MB的内存泄漏,尝试定位问题多次都失败了。
我的设计是:客户端 websocket 协议连上来,lua-resty-websocket 完成 http 到 websocket 的协议转换。
在解析请求后创建一个轻量级线程 (ngx.thread.spawn),轻量级线程连接redis负责接受redis推送并直接把数据push给客户端,
如果客户端断开连接,就用ngx.thread.kill结束对应lightthread。
一天内存使用曲线大致为:
0:00到8:00 1.39G
8:00到11:00 随着连接量上升而上升,最高连接量6000,内存到1.81G
11:00到17:00 连接量上下波动,内存在随之波动。
17:00之后 连接量逐渐下降到100以下,内存逐步下降,最后却稳定在1.66G。
第二天类似,不过起始内存确是1.66G,一天增长270M。
2w连接压测时,使用nginx-gdb-utils分析:
(gdb) lgcstat
42778 str objects: max=851, avg = 41, min=18, sum=1781624
2202 upval objects: max=24, avg = 24, min=24, sum=52848
36031 thread objects: max=976, avg = 748, min=424, sum=26963272
73 proto objects: max=2579, avg = 336, min=80, sum=24543
20479 func objects: max=144, avg = 21, min=20, sum=430920
60 trace objects: max=2308, avg = 614, min=160, sum=36892
0 cdata objects: max=0, avg = 0, min=0, sum=0
173891 tab objects: max=524328, avg = 121, min=32, sum=21211768
94408 udata objects: max=1376, avg = 239, min=32, sum=22592249
sizeof strhash 262144
sizeof g->tmpbuf 1024
sizeof ctype_state 0
sizeof jit_state 3864
total sz 73366380
g->strnum 42778, g->gc.total 73366380
elapsed: 37.780000 sec
有两个问题:
1)压测结束后,内存实际增长700M多,而lgcstat显示的g->gc.total不超过100M,其他内存是谁分配的,为什么没有释放。
2)压测结束后,使用lgcstat获得thread还有3万多个,感觉lightthread并没有收回。