Quartz定时任务调度器堵塞原理和解决
发布日期:2021-07-20 20:53:23 浏览次数:55 分类:技术文章

本文共 2250 字,大约阅读时间需要 7 分钟。

Quartz 调度器以多线程的方式执行调度任务JobDetail,缺省线程池大小为10,也就是说若调度器中已有10个Job在工作(线程没有结束),那么即使有JobDetail到了被触发的时间,新的JobDetail不会被执行,也就是说阻塞的条件是,调度器中正在运行的JobDetail数量达到了设定值10。

 

举一个具体的例子:

a. 单一Job

配置:

JobA 触发时间为 每秒运行一次,每个Job执行时间为30秒

 

运行:

1、 10个JobA将连续启动

2、 到第10个JobA启动后,线程池中所有线程被耗尽,调度器出现了阻塞,即没有新的JobA启动,尽管设置为每秒执行一次。

3、30秒后,将有1个以上JobA执行完毕,在短时间内,新的10个JobA又被启动,再次进入2的阻塞状态

 

    2状态可以称做调度器阻塞状态,没有新的Job能执行,导致一些诸如定时读取数据的操作无法继续下去。除非有JobA执行完毕,新的JobA才能被执行。实际运行中,假设调度器中有一个JobA线程的执行时间大于两次启动间隔,则经过若干次操作后,将耗尽所有10个线程资源,导致其他的调度任务阻塞。

 

b. 多个Job(无状态Job)

    在这个测试中,可以有多种不同的Job(无状态Job),但它们均共享这10个线程,任何一个Job 线程执行时间大于两次启动间隔均有可能导致调度器被阻塞。例如:

配置:

JobA 触发时间为 每秒运行一次,每个Job执行时间为30秒;JobB 触发时间为每秒运行一次,每次执行时间小于1秒

 

运行:

1。JobA和JobB相继启动

2。几秒钟后JobA数量达到10,其间JobB被执行若干次,则新的JobA和JobB均不能被启动,调度器进入阻塞状态

3。30秒后,JobA(0-9)相继执行完毕,新的JobA和JobB均有机会被重新启动,短时间内,再次进入2的阻塞状态

 

如何解决调度器阻塞问题?

1、 延长可能需要较长时间执行的JOB的时间间隔,假设Job执行时间最大时间为t1, 两次任务执行间隔调度时间为d1, 则d1>t1

2、 使用有状态调度任务StatefulJob代替没有状态的Job. 对于要求执行间隔时间尽可能短,又不希望造成阻塞的比较适合。可以同时有无状态的调度任务JobA,和有状态的调度任务JobB,JobB堵塞后不会对JobA造成影响,即读报文的任务阻塞了,不会对调度器中其他任务造成影响,同时JobA执行完后,可再次继续下一个任务。

    如果JobA执行时间较长的话,可能造成JobA始终占用一个线程资源。

3、注意:一个调度器中如果有很多个Job(JobA,JobB,JobC...),其中有一个很容易堵塞,则该Job也会造成其他的Job阻塞

 

线程池大小配置在org.quartz下的quartz.properties文件中

org.quartz.threadPool.threadCount = 10

如若要修改线程池的大小,可以修改该文件中的 org.quartz.threadPool.threadCount值。亦可建一org.quartz包,包下放置quartz.properties文件,覆盖掉quartz.jar中的配置

但是,修改线程池的大小并不能解决调度器阻塞问题,因为资源消耗的速度不及资源释放的速度时,资源就会被耗尽。

 

阻塞的原因:

两次JOB不是stateFul(实现stateFul接口,意义为防止并发, 即要串行,上一次执行完此次才执行)的,而job执行时间大于间隔时间,会导致阻塞.  异常情况为Job执行时间过长,

1: 外部接口调用没有设置超时时间, 一直阻塞.

         在项目中使用了quartz的分布式功能,两个节点协调运行定时任务,近期发现quartz的有个定时任务经常会一直处于blocked堵塞状态,后续一直都没有再触发,看日志也没任何错误信息,一直在纳闷。经过一系列的研究,发现定时任务的逻辑里是需要通过http请求外部系统的,使用的apache的httpclient框架,当时没有设置连接超时和读取超时时间,仔细看了httpclient框架的源码,底层调用socket的时候,可以设置超时时间,会一直堵塞等待数据的返回,导致整个线程都堵塞了。终于明白,其实定时任务时根本没有执行完毕的,只是线程一直被堵塞了,这个坑巨大啊。有使用http、ftp、socket等进行通信的,一定要设置超时时间,不然,就真的是出麻烦。

 

2.事务未提交, 锁就不会释放, 导致下次Job进来,锁等待超时

①事务未提交

在使用spring test 做单元测试时,debug导致事务没有提交,Lock wait timeout exceeded;
定位到该表,直接navicat 上insert 该表,Lock wait timeout exceeded;
确认是该表的事务没有提交,锁被占用没释放:
select * from information_schema.innodb_trx;
查看到堵塞的线程,kill  trx_mysql_thread_id,

②表级锁被阻塞
同事在查询数据库数据写入到excel时,数据量较大有200万,未能正确分页,导致数据库锁等待卡死;
show processList;
查看到多个线程处于sending data的状态,
kill掉 线程,恢复数据库;
并将存储引擎由MyIsam 改为 INnnoDB,可减少表级锁。
 

转载地址:https://blog.csdn.net/liao0801_123/article/details/83827099 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:对于Spring中事务的readonly属性理解
下一篇:Java并发编程:volatile关键字解析

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年03月06日 03时19分09秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

洞泾智能机器人产业基地_G60科创走廊洞泾人工智能产业基地(核心区块)暨洞泾镇招商人员培训班顺利开班... 2019-04-21
java 拼接路径优雅方式_Java安全编码实践总结 2019-04-21
realme x2 深度测试打不开_搭载65W超级闪充,realme真我X7手机充电评测 2019-04-21
java并发编程指南博客_Java并发编程-synchronized指南 2019-04-21
java怎么中断阻塞状态_java并发编程()阻塞方法与中断方法 2019-04-21
java zlib 位运算_位运算入门:找出一个二进制数的最右端的第一个1;计算一个二进制数中1的个数;找出数组中唯一一个出现次数为奇数的数;找出数组中唯二两个出现次数为奇数的数... 2019-04-21
java lua热更新_lua热更新学习 2019-04-21
script执行php文件_php命令行(cli)下执行PHP脚本文件的相对路径的问题解决方法... 2019-04-21
apache 2.4 php5.4_apache2.4+php5.4+my sql 5.6,网站经常无故不能访问 2019-04-21
php apc.dll下载,PHP之APC缓存详细介绍 apc模块安装 2019-04-21
html贝塞尔曲线在线,贝塞尔曲线的一些事情_html/css_WEB-ITnose 2019-04-21
Java前台显示近20天的东西_第十次课:前台首页设计及显示商品信息 2019-04-21
java开发web网站的路由设计_理解Web路由(浅谈前后端路由与前后端渲染) 2019-04-21
excel如何把顺序倒过来_在excel中怎么使文字颠倒顺序反过来显示呢? 2019-04-21
php正则表达式获取图片路径,php 常用正则表达式实例(图片地址,与指定内容获取)... 2019-04-21
脚本语言php是什么意思,PHP脚本语言 2019-04-21
matlab数学规划模型,数学规划模型 2019-04-21
视频提取音频php,如何提取视频中的音频,从视频文件中提取出音频输出成MP3格式... 2019-04-21
diy.php添加验证码,织梦dedecms自定义表单中加入验证码 2019-04-21
在php脚本中 通过可以获取,在PHP中,可以使用Unix时间戳获取精确的脚本执行时间。... 2019-04-21