前因:

我写了一个小项目,主要功能是用Spring task定时任务每天定时给用户发送邮件。执行了几个月一直没有问题,前几天,莫名其妙的突然不再发送邮件了。

只好花费一些时间来查看到底是什么原因造成的。

定时任务的作业内容:

step1: http请求方式调用远程的一个WebService接口,来获取数据,一个任务中需要调用n(n>1)次远程接口。

step2: 解析获取的数据,生成数据表和曲线图。

step3: 将数据表和曲线图,以邮件的形式发送给用户。

问题出现:

在步骤1中,需要调用10(假定值)次webservice接口,在日志中可以看到执行了3(假定值)次后,突然不在往下执行了。此时的服务已经执行了好几个月了。

问题分析:

因为步骤1中的代码,全部放在了try{}catch(){}代码快中,如果有异常被捕获,肯定会被记录到日志当中。

所以这个异常不是我本地的代码造成的,如果是我本地的代码,异常肯定会被抛出,并且被记录下来。

如果不是我本地的代码出错,那基本可以确定异常是在http请求远程接口的时候出现的,而且这个异常可能造成了任务线程的阻塞或者死亡。

顺着这个思路,网搜了一下可能或造成http请求中断的可能原因。找到了两篇比较有价值的文章。

Http请求偶尔超时+总结各种超时死掉的可能和相应的解决办法

线程中抛出未捕捉的异常会如何? [修正版]

最终锁定了两个可能的原因:

1. 和远程服务间创建的keep alive的connection过多,导致后面创建的连接会一直连接超时,导致线程出现异常。

2. http请求出现某种错误时,http请求僵死,导致线程也不再往下执行。最终导致后面的定时任务也不再执行。

  之前一直认为http会有一个默认的超时时间(可能是5min),超过这个时间后会报超时异常。这个看法误导了我。

先check是不是第一个原因,逐行的检查http请求部分的代码,发现所有的connection都是即时的关闭的。所以第一个原因排除了。

那么就剩第二个原因了。做个试验来验证是不是果真如此呢。

测试1:

1. 设置每2min执行一个定时任务(为了缩短测试时间,减少了需要请求的次数,设置只请求2次),启动服务。

2. 程序运行,我去吃了个午饭,回来时程序运行了近半小时,邮件一直正常发出,没有出现异常。

3. 在又一次请求远程接口的时候,我拔掉了网线。见证奇迹的时候到了,线程不再继续执行了。而且没有错误日志。

4. 过了30秒,插上网线,恢复网络。线程还是没有继续执行。

5. 过了2min,该是下一次定时任务执行的时候了,线程还是没有继续执行。

6. 过了30min,如果有默认的超时时间,也该抛出time out的异常了吧。结果没有。程序还是停留在第一次断网的那个时候。这个时候我已经开始写这篇日志了。

原因找到了。因为网络的不稳定,可能是暂时性的断网,导致了http请求僵死,最终导致整个线程不再执行。

那么怎么解决呢?如果给http请求设置一个默认的超时时间,能不能解决问题呢?

测试2:

1. 在http请求的代码中设置超时时间,连接超时时间设置为30s,读取数据超时时间设置为3min。

        // 设置连接主机超时(30s)
connection.setConnectTimeout(30 * 1000); // 设置从主机读取数据超时(3min)
connection.setReadTimeout(180 * 1000);

2. 仍然是2min执行一次定时任务,启动服务。

3. 第一次定时任务执行成功,开始执行第二次定时任务,在http发送后还未返回的时候(一次查询耗时10-20s),果断又拔掉网线。线程又中断了。30s后连上网线。

4. 2min后该下一个定时任务执行了,线程还是没有继续执行。

5. 大约3min的时候,报了一个异常出来(好长没全拷贝出来)。报出异常后程序又继续向下执行了。

java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)

不同时间断网,还报了下面3种异常:

java.io.IOException: missing CR
at sun.net.www.http.ChunkedInputStream.processRaw(ChunkedInputStream.java:405)
at sun.net.www.http.ChunkedInputStream.readAheadBlocking(ChunkedInputStream.java:572)
at sun.net.www.http.ChunkedInputStream.readAhead(ChunkedInputStream.java:609)
at sun.net.www.http.ChunkedInputStream.read(ChunkedInputStream.java:696)
at java.io.FilterInputStream.read(FilterInputStream.java:133)
java.net.UnknownHostException: ceshi11.test.com
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:178)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
java.net.NoRouteToHostException: No route to host: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)

6. 大约10min后,在来看看日志。发现,定时任务又开始每2min执行一次。但是因为报错超时导致中间的错过的2个定时任务,却是没有再被执行。

至此,问题应该就可以被解决了。就是在http请求时设置一下超时时间即可。

Spring task定时任务执行一段时间后莫名其妙停止的问题的更多相关文章

  1. Spring Boot定时任务运行一段时间后自动关闭的解决办法

    用Spring Boot默认支持的 Scheduler来运行定时任务,有时在服务器运行一段时间后会自动关闭.原因:Schedule默认是单线程运行定时任务的,即使是多个不同的定时任务,默认也是单线程运 ...

  2. C#中通过调用Dll函数时,执行一段时间后,就会报内存可能被破坏的错的解决办法

    遇到同样的问题,已经解决的:http://blog.csdn.net/youxiazzz12/article/details/24313347

  3. 多线程时,请求执行不是按顺序的,可添加Critical Section Controller(临界部分控制器),执行顺序是固定的,但执行一段时间后,该逻辑器下的请求不再循环,无解ing

  4. 关于ScheduledExecutorService执行一段时间之后就不执行的问题

    在项目中使用java的定时任务时,有的时候执行一段时间后没任何反应了.这里有篇文章说了这个问题.猛击下面的链接. http://blog.163.com/scuqifuguang@126/blog/s ...

  5. IIS服务器运行一段时间后卡死,且无法打开网站(IIS管理无响应,必须重启电脑)

    问题描述: 公司希望使用IIS配合网站显示一些订单跟进的情况并展示出来,所以我们在一台演示的Win7 Pro电脑上安装了IIS,但使用了一段时间后发现每过几天页面就无法正常访问了,而且打开IIS管理器 ...

  6. 基于struts2、spring的应用闲置一段时间后报空指针错(转)

    在做struts2.spring网站时,在系统闲置一段时间后,访问页面会出错,第二次再访问就正常了.后来查了后台日志,发现是数据库连接关闭了,导致页面访问出错.页面上报空指针错误,错误没有保留,日志中 ...

  7. win10锁屏或睡眠一段时间后弹不出登录框

    win10锁屏或睡眠一段时间后弹不出登录框 文:铁乐与猫 通常发生在win10更新到10周年版后发生,也就是会卡在登录状态,但不见输入登录框. 我出现这种情况的时候不是很严重,一般等久些也能出现,但问 ...

  8. CENTOS 配置好SVN服务环境后,其他服务器无法访问 Error: Can't connect to host '192.168.1.103': 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。

    CENTOS 配置好SVN服务环境后,其他服务器无法访问   根据 下面的步骤配置好服务后,使用本机可以正常 连接到 SVN 服务, 但是使用局域网的其他服务器访问时出现下面的错误, Error: C ...

  9. USB鼠标过一段时间后失灵问题的修复

    现象: USB鼠标计算机锁屏一段时间后,不能动了,拔下来重新插上后,又恢复正常了. 原因: 这是系统默认USB电源管理造成的.一段时间不用后,自动关闭了USB电源. 解决方法: 1.进入设备管理器 在 ...

随机推荐

  1. 详解Paint的setColorFilter(ColorFilter filter)

    一.简介 setColorFilter(ColorFilter filter) 设置颜色过滤,这个方法需要我们传入一个ColorFilter参数同样也会返回一个ColorFilter实例.我们在set ...

  2. Directx11代码下载

    很多年前的代码,看还有朋友需要,上传到百度网盘了 https://pan.baidu.com/s/1pnGFt84htvdXeK86pvyR8Q https://pan.baidu.com/s/1zT ...

  3. 440P 测试三星ssd840pro 512g

    下面是鲁大师的截屏 安装win8.1 x64颇费周折,计算机->管理模糊,解决方法 现在最大的问题是cpu风扇噪音和温度,看网上确实存在此问题,纯铜风扇+7783硅脂是必须的,下面鲁大师温度截屏 ...

  4. ELK菜鸟手记 (二) - 高级配置之多应用索引过滤

    我们在实际的场景中,经常是多个网站或者服务端在一台服务器上,但是如果这些应用全部 记录到一台logstash服务器,大家日志都混在一起不好区分. 有人说,我可以在日志中打项目名,但是这样并不方便. 其 ...

  5. 微软BI SSRS 2012 Metro UI Win 8 风格的报表课程案例全展示

    开篇介绍 微软BI SSRS 2012 Metro UI 高端报表视频教程 (http://www.hellobi.com/course/15)课程从2014年6月开始准备,于2014年9月在 天善B ...

  6. 一些Vim使用的小技巧

    1. 全局替换(1) v + G + $ 选定全部,然后输入 :s/原始字符串/目标字符串/(2) :%s/原始字符串/目标字符串/ 2. 清除页面中所有行尾的空白符::%s/s+$// 3. 清除所 ...

  7. iOS 7设计备忘单

    With the release of iOS 7, app designers and developers will need to adjust their visual language to ...

  8. Seaslog安装和参数配置

    详细文档访问:https://github.com/Neeke/SeasLog/blob/master/README_zh.md 源码安装步骤: 1.先下载Seaslog源码,下载地址:http:// ...

  9. 在Asp.Net中操作PDF – iTextSharp - 操作图片

    iTextSharp支持所有主流的图片格式,比如:jpg, tif, gif, bmp, png和wmf.在iTextSharp中使用Image.GetInstance()方法创建图片有很多种方式,或 ...

  10. golang ----gc问题

    go程序内存占用大的问题 这个问题在我们对后台服务进行压力测试时发现,我们模拟大量的用户请求访问后台服务,这时各服务模块能观察到明显的内存占用上升.但是当停止压测时,内存占用并未发生明显的下降.花了很 ...