1. 问题描述
系统有多个定时任务,其中一个定时任务需要去FTP上下载文件并且解析文件,其他的定时任务有将更新数据推送到其他节点。现场运维反馈在某一段时间内没有更新数据,也就是没有执行到定时任务。
2. 问题解决
- 首先看日志,明确下是否是真的定时任务不执行了,还是说执行了但是有问题。
发现日志并没有打印出关于定时任务的启动日志,说明定时任务没有启动。
- 然后将运维进行执行jstack pid > a.txt 命令,将jvm中线程状态打印出来。
发现文件中有好几个线程状态都是blocked,在等待获取同一把锁,并且都指向同一类,然后去文件搜索这对应的锁,发现获得这把锁的线程在runnable。
- 定位到这把锁的执行方法中
这个执行方法是进行FTP connection操作,也就是进行socket连接,socket连接明确表明timeout的时间为0,也就是说会一直等待FTP服务器返回响应。
- 分析结果
线程只所以会blocked,是因为这个线程一直在获得锁不释放,导致线程一直堵塞下去,但是为什么同步数据其他的定时任务也不执行?
- 再次分析
采用的定时任务都是springboot自带的schedule类,默认都是单线程的,然后怀疑的态度去搜索scheule类相关配置,发现有一个配置类,给这个schedule配置了线程池。
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
@Bean
public Executor taskExecutor() {
// 线程数量
return Executors.newScheduledThreadPool(10);
}
结论
FTP服务器出现故障,导致访问FTP的定时任务一直堵塞住,然后定时任务采用线程池的方法,如果FTP的线程一直堵塞,线程池达到最大的线程数,那么其他的定时任务就不能启动了。
解决
给FTP请求设置超时时间。
|