[Java代码] quartz集群

来源:互联网 发布:程序员微电影 编辑:程序博客网 时间:2024/06/09 18:11
用quartz实现了请求重发机制,每间隔一段时间便去数据库中查询需要重发的请求,然后调用httpclient执行重发,对结果进行处理。

(1)配置spring-quartz..xml

  1. <bean id="autoRepeatRequestTask"
  2. class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
  3. <property name="jobClass">
  4. <value>com..job.AutoRequestRepeatJob</value>
  5. </property>
  6. <property name="durability" value="true" />
  7. <property name="requestsRecovery" value="true" />
  8. </bean>
  9. <!-- 定义触发时间 -->
  10. <bean id="autoRepeatRequestDoTime"
  11. class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
  12. <property name="jobDetail">
  13. <ref bean="autoRepeatRequestTask" />
  14. </property>
  15. <!-- 错过的定时任务不再执行 -->
  16. <!-- <property name="misfireInstruction" value="2"></property> -->
  17. <!-- cron表达式 -->
  18. <property name="cronExpression">
  19. <value>0 * * * * ?</value>
  20. <!--每分钟执行一次 -->
  21. </property>
  22. </bean>
  23. <!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
  24. <bean id="startQuartz" lazy-init="false" autowire="no"
  25. class="org.springframework.scheduling.quartz.SchedulerFactoryBean"
  26. destroy-method="destroy">
  27. <property name="configLocation" value="classpath:quartz.properties" />
  28. <property name="dataSource" ref="dataSourceMysql" />
  29. <property name="triggers">
  30. <list>
  31. <ref bean="autoRepeatRequestDoTime" />
  32. </list>
  33. </property>
  34. <property name="startupDelay" value="10" />
  35. <property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
  36. </bean>http://m.nvzi91.cn/penqiangyan/29380.html
复制代码
(2)MethodInvokingJobDetailFactoryBean在集群环境下会出现job无法序列化的问题,spring目前为止还没有修复。

点击打开链接上面提供了一种2.*版本以前的解决方案,但是我使用 的2.2.1很多类都变成了接口,jira上提供的这种方案已经不可取,所以使用了另外一种方案。

  1. @PersistJobDataAfterExecution
  2. @DisallowConcurrentExecution // 不允许并发执行
  3. public class AutoRequestRepeatJob extends QuartzJobBean {
  4. private static final Logger LOGGER = LoggerFactory.getLogger(AutoRequestRepeatJob.class);
  5. @Override
  6. protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
  7. RequestRepeatService requestRepeatService = getApplicationContext(context).getBean(RequestRepeatService.class);
  8. requestRepeatService.autoRepeatRequest();
  9. }
  10. private ApplicationContext getApplicationContext(final JobExecutionContext jobexecutioncontext) {
  11. try {
  12. return (ApplicationContext) jobexecutioncontext.getScheduler().getContext().get("applicationContextKey");
  13. } catch (SchedulerException e) {
  14. LOGGER.error("jobexecutioncontext.getScheduler().getContext() error!", e);
  15. throw new RuntimeException(e);
  16. }
  17. }
  18. }
复制代码


(3)集群配置quartz.properties

  1. #==============================================================
  2. #Configure Main Scheduler Properties
  3. #==============================================================
  4. org.quartz.scheduler.instanceId=AUTO
  5. org.quartz.scheduler.instanceName=AUTO_REPEAT_REQUEST
  6. #============================================================================
  7. # Configure JobStore
  8. #============================================================================
  9. org.quartz.jobStore.isClustered=true
  10. org.quartz.jobStore.clusterCheckinInterval=15000
  11. org.quartz.jobStore.misfireThreshold = 60000
  12. org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
  13. org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
  14. org.quartz.jobStore.tablePrefix = t_esfjy_qrtz_
  15. org.quartz.jobStore.useProperties = false
  16. #prevent lock time-out
  17. org.quartz.jobStore.txIsolationLevelSerializable=true
  18. #============================================================================
  19. # Configure ThreadPool
  20. #============================================================================
  21. org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
  22. org.quartz.threadPool.threadCount=10
  23. org.quartz.threadPool.threadPriority=5
  24. org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = truem.nvzi91.cn
复制代码


这其中有两个碰到的坑

一个是
  1. org.quartz.jobStore.txIsolationLevelSerializable=truehttp://m.nvzi91.cn/luanchaonanzhong/29381.html
复制代码
之前碰到过集群环境下出现锁超时的问题,网上说是因为mysql innodb默认的事务隔离级别导致的。然后我加上了这条配置,但是后来仔细研究集群各节点的日志,发现可能是因为我同事启动了一台集群环境外的机器执行了quartz任务。由于未知的原因,导致他的机器不在集群中,但是却能每次拿到quartz锁,(而且只能是他拿到),资料说可能是服务器时间不同步的原因,未能验证。

第二个是

  1. org.quartz.jobStore.misfireThreshold = 60000http://m.nvzi91.cn/niaodaoyan/29382.html
复制代码
这个大坑我研究了好久,因为之前开发时候为了调试方便,然后定的15s执行一次quartz任务,导致了任务重发执行。后来发现是这个配置的原因。

详见点击打开链接

大致问题就是,服务器重启后,超时1min的任务不会立即执行,小于1min的会立即重新执行。任务间隔时间小于15s就会出现问题。

还有一个是

之前用的quartz结合线程池做请求重发,每次到达任务执行时间,会提交很多任务到线程池中,然后quartz线程就结束了。然而如果线程池中的任务没有执行完,就到达了下一个任务执行节点,就会存在任务重复的问题。后来使用了线程池的任务阻塞方法,在线程池中的所有任务全部执行完成之后,quartz线程才会退出。
0 0
原创粉丝点击