记录一次服务器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驱动,一个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连接池的进程,需要设一个超时。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值