我们有个定时任务会每天去请求一下别人提供的webservice来拿到今天签署的合同的数据,某天早上巡检服务器的时候,发现定时任务没有执行,通过dump线程的状态,发现执行这个定时任务的线程被阻塞住了
阻塞的原因是读操作的超时时间没有设置,默认值是-1 导致了客户端一直等待,然后程序一直阻塞
解决的方法也很简单,参照jdk的文档我们可以在启动参数上加上超时的相关的属性
-Dsun.net.client.defaultConnectTimeout=10000
-Dsun.net.client.defaultReadTimeout=10000
但是这里又会遇到一个问题:怎样确定这些参数生效了,也就是说怎样模拟服务器端超时的情况,毕竟服务器端不会每次都超时
针对这种情况,我们可以使用iptables来丢弃掉服务器端的相关端口返回的SYN包或者数据包,来模拟连接超时和读数据超时的情况
我们以百度为例,模拟weget访问百度的时候的超时情况
用到的两个wget的参数:
-T 设置以秒为单位的超时时间
-t 则是设置重试的次数
DROP掉百度返回的连接的建立连接的握手数据包:
iptables -A INPUT -p tcp -m tcp -s baidu.com --tcp-flags SYN SYN --sport 80 -j DROP
清除掉上一个规则,DROP掉百度返回的传输数据的数据包:
因为iptables的INPUT链里里只设置了这一条规则,所以直接根据行号为1来DROP即可
iptables -D INPUT 1
iptables -A INPUT -p tcp -m tcp -s baidu.com --tcp-flags PSH PSH --sport 80 -j DROP
通过这种方式,将我们的定时任务的程序请求的webservice的服务器返回的数据包也做这样的处理,这样就可以测试超时之后的情况了
模拟连接超时之后程序的报错信息:
读超时:
程序记录超时之后抛出的异常再做相应的处理即可(比如将这次失败的定时任务写入数据库,下次再继续尝试等)不会再阻塞线程影响其他任务的执行了