记录一次服务器CLOSE_WAIT不停增加的解决过程

程序是基于cowboy的erlang web服务器。

起初是一个简单的http服务器,后来功能越加越多,客户端通过http请求服务器,有天晚上,报警显示,http请求多次无正常返回,显示超时。 登录上服务器,看日志,没有报错。用命令,

ss -n | awk '/^tcp/ {++state[$2]} END {for(key in state) print key,"\t",state[key]}'

发现1000多个 CLOSE_WAIT的链接,结合上面的现象,链接都是客户端超时主动断开,导致CLOSE_WAIT一直增加。

接下来是查看可能引起问题的原因,因为是cowboy框架,有链接CLOSE_WAIT状态,那就会有很多进程,用

erlang:processes(),打印出来,大量的进程,随意调了中间几个进程,用命令erlang:process_display(Pid, backtrace),来跟踪这些进程的栈情况,发现是mysql语句阻塞了, 程序中是用一个进程池来调mysql驱动,一个连接就是一个进程,把这些进程存到变量Pids,

手写了下面几个函数:

F1 = fun(P) -> S = erlang:process_info(P, message_queue_len), io:format("~p, ~p~n", [P, S]) end.
F2 = fun(P) -> S = erlang:process_info(P, messages), io:format("~p, ~p~n", [P, S]) end.
F3 = fun(P) -> io:format(~p~n", [P]), erlang:process_display(P, backtrace), io:format("~n", []) end.

其实只要F1就可以,

运行:lists:foreach(F1, Pids), 会列出所有进程及对应的消息队列长度,发现其中有一个进程的队列达到1000多,和CLOSE_WAIT的长度一致,再用命令erlang:process_display(Pid, backtrace),来查看这个进程的栈使用情况,发现是一个较长的mysql语句阻塞了,这个mysql语句,每天执行一次统计,语句有点问题,一直阻塞住了。 先把这个统计功能关闭掉,重启了一下这个进程,问题解决。  其实总结一下,写代码的时侯可以避免这个问题,使用mysql连接池的进程,需要设一个超时。

发布了1 篇原创文章 · 获赞 1 · 访问量 76

猜你喜欢

转载自blog.csdn.net/jurenaa/article/details/104381150