TongWeb关于队列满问题详细说明或者8080无法访问问题说明

如果最近遇到一个现象,当日志看到 Maximum connections queued reached (10000) 队列满,但访问量小后,端口依然无法访问,只能重启TongWeb解决时,这多半是产品bug,近期已有几家银行,证券遇到这个问题。问题原因见附件说明, 解决办法:

  1.默认NIO2改为NIO。
  2. 针对不同版本,向开发提制作 NIO2线程池的补丁。附件仅是针对TongWeb7.0.4.3的补丁。

郑商所8080无法访问问题说明

一、问题的定位
1.1 锁定问题的分析过程:

  1. 根据复现材料,可以看到以下线索:

网络状态分析:
在这里插入图片描述

8080通道对应的连接都是CLOSE_WAIT的状态,产生此问题的原因是客户端主动断开连接,而服务端由于socket状态异常而无法关闭此连接。
日志分析:
在这里插入图片描述

通过以上应用日志可以看到,应用中出现很多websocket连接异常,并且由此导致客户端连接断开。TW服务端日志中的ClientAbortException异常验证了这一点,该异常就是客户端主动断开连接才会报的异常信息。
TongWeb的server.log:
在这里插入图片描述

同时日志红框中的信息代表TongWeb接收请求的通道的连接数已经到达最大值,后续请求都会直接被放弃掉。
Jstack信息:
在这里插入图片描述

结合tongweb日志,同时根据现场打印的jstack线程快照也可以看到通道接收请求的代码会判断该通道已经到达配置的连接数最大值,阻塞在这里,等待连接数计数器的释放,在释放计数器之前,通道对应的serversocket将拒绝后续请求的处理,直接丢弃掉。

  1. 分析问题产生的原因:

通过以上素材的分析,问题产生的原因应该是由于应用连接异常关闭,服务端无法判断socket状态,导致连接数计数器未被正常释放,导致通道连接数到达最大值后无法继续接收处理请求,最终导致现场环境出现“8080端口卡死”。

针对为什么连接计数器未正常释放的问题,通过分析TongWeb中对Nio2模式通道的处理代码,对于计数器的释放是在closeSocket()方法中进行,如下图:
在这里插入图片描述

释放计数器之前需要先判断socket的状态是否是isOpen,如果这时候客户端由于某种原因主动断开了连接,那么此时socket的状态就不再是isOpen状态,那么TongWeb的代码就无法进入到正常的更新计数。这就会导致以上问题的出现。

1.2 问题的确定:
周六通过加调试日志的方式,在TongWeb接收请求及关闭socket等关键流程加了打印日志。
另外由于怀疑是连接数占满导致,建议现场测试环境调小最大连接数,并很快成功复现问题。

针对上述closeSocket内打印的日志可以清楚的看到:
在这里插入图片描述

问题复现时,大量打印的日志是客户端socket的确是被关闭了,同时socket的isOpen方法为false,所以导致肯定无法继续做计数器更新。

二、问题的解决
对TongWeb中SocketWrapperBase类中增加了volatile boolean closed = false;目的是通过标志位解决计数器依赖socket的状态,可以正确的进行连接数计数,避免客户端异常关闭导致连接数无法计数问题。

在这里插入图片描述

需要找东方通替换补丁,验证问题解决;
TongWeb测试验证正式补丁对其他功能无影响。

三.为什么其他项目没有遇到这个问题
因为正常来说http协议从1.1版本开始默认都是长连接的,客户端不会快速频繁主动断开连接,所以没有遇到这个问题。


版权声明:本文为qq_33476768原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。