xsocket死锁问题排查

来源:互联网 发布:华师大网络教育好不好 编辑:程序博客网 时间:2024/05/16 00:43

今天同事告诉我,生产环境的kafka队列中没有数据了。生产环境中和数据生产者相关的服务器有2台,最近这两台老搞事情:
这里写图片描述
客户端是基于xsocket开发的,服务端是直接使用NIO开发的。
背景交代完了,下面回顾一下我排查这个问题的思路 :

  1. 查日志

    半天查不到什么有用信息,遂放弃。

  2. 检查socket是否还在

    看日志之前就怀疑socket是不是断开了。这算是查这类问题的套路吧。
    在A机上运行netstat,命令就不细说了:

    netstat -ntap | grep xxx #xxx是B机监听的端口号

    还好socket还在。
    然而,现在仍然判断不来AB机之间是否有问题,还得想办法。

  3. 检查网络流量是否正常

    我想,既然socket还在,那就看看socket上有没有流量。流量正常的话,基本可以排除客户端和服务器之间的问题。

    使用iptraf命令查看socket流量,在A机上运行iptraf:

    此处应有截图,然而我忘截了

    iptraf的结果是,socket上面有数据流,但是远少于正常情况,隔一阵一小包数据。这说明问题出在A、B机之间。我猜想小包数据是登录报文或者心跳包一类的。

  4. 抓包看报文

    为了验证刚才的猜想,我决定抓几个包来瞧瞧。在A机上运行下面命令:

    tcpdump tcp port xxxx and host xxx.xxx.xxx.xxx

    这里写图片描述

    抓了好长时间,报文都是上面那样的,不是我猜的登录或心跳报文(报文数据长度为0)。我抓到的大概是tcp协议的心跳一类的吧。
    当时分析,A、B之间没数据,大概会是这几种情况吧:

    1. A机发数据线程没创建起来/已经终止
    2. A或B机阻塞在某处
    3. 特殊情况下代码逻辑跳过了发数据部分
    4. A机没有要发送的数据

    仔细检查了代码逻辑,排除了后两种情况。

  5. 使用jstack查看线程堆栈
    从socket上已经找不出更多线索了,只好去看jvm。在A机上连续使用jstack查看线程状态几次,发现发数据的那个线程的堆栈状态就没变过,仔细一看,线程发生了死锁!
    这里写图片描述

找到问题的原因,还有了详细的堆栈调用层级,接下来就好办了。找到xsocket的源代码,找到死锁的那一行,发现那行下面就有一个警告日志:

synchronized flushing in NonThreaded mode could cause dead locks (hint: set flush mode to ASYNC).

在程序中设置flush mode为异步,问题得到解决~

0 0
原创粉丝点击