Quartz动态设置并发数量
quartz存在一个问题,当正在进行的任务已经达到了设置的个数,后续触发的任务没有线程可用,会导致系统宕机;
Quartz通过StdSchedulerFactory工厂创建调度器,initialize方法通过解析quartz.properties配置信息进行加载,默认线程个数为10,可以通过覆盖信息定义线程个数,通过Apollo信息进行线程个数配置
Scheduler scheduler = (new StdSchedulerFactory()).getScheduler(); //获取Apollo配置信息 Config config = ConfigService.getConfig("application"); String threadCount = config.getProperty("org.quartz.threadPool.threadCount", ""); //对quartz.properties配置信息进行覆盖 Properties props = new Properties(); InputStream in = TaskScheduleServiceImpl.class.getClassLoader().getResourceAsStream("quartz.properties"); props.load(in); String threadCountProperties = props.get("org.quartz.threadPool.threadCount").toString(); if ("".equals(threadCount)) { if (!threadCount.equals(threadCountProperties)) { props.setProperty("org.quartz.threadPool.threadCount", threadCount); //重新创建调度器 StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory(); stdSchedulerFactory.initialize(props); //关闭原先调度器 scheduler.shutdown(); scheduler = stdSchedulerFactory.getScheduler(); in.close(); } }
上面代码是在系统初始化中执行的,若想实现系统运行中进行动态扩容/缩容调度器线程池大小,可以加一个flag标志进行判断,通过获取当前系统正在执行的任务个数和系统定义的总数进行对比,当达到一定个数或一定比例时,再次调用上面代码进行动态扩容/缩容。
上面代码存在的问题是当关闭调度器时,会杀死原先存在正在进行的任务,这是不友好的操作,可以添加一个中间件(Redis),将每次触发执行的任务加入Redis中,执行完从Redis删除,所以每次系统重启都从Redis读取数据,对任务重新执行,执行完再将其从Redis删除,同时为了保证任务的唯一性(集群环境下不管是定时还是立即执行),需要对任务进行加锁操作,由于只需要保证同一时刻只能有一个任务在运行,保证高可用而不追求强一致性,所以选择的是Redis分布式锁Redisson,根据先到先得策略使用了Redisson的公平锁。
作者:huangrenhui
欢迎任何形式的转载,但请务必注明出处。
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】。
如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注我】。
如果,您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是【码猿手】。
如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注我】。
如果,您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是【码猿手】。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。