quartz集群

来源:互联网 发布:什么是软件过程模型 编辑:程序博客网 时间:2024/06/07 19:11

用quartz实现了请求重发机制,每间隔一段时间便去数据库中查询需要重发的请求,然后调用httpclient执行重发,对结果进行处理。

(1)配置spring-quartz..xml

        <bean id="autoRepeatRequestTask"class="org.springframework.scheduling.quartz.JobDetailFactoryBean"><property name="jobClass"><value>com..job.AutoRequestRepeatJob</value></property><property name="durability" value="true" /><property name="requestsRecovery" value="true" /></bean><!-- 定义触发时间 --><bean id="autoRepeatRequestDoTime"class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"><property name="jobDetail"><ref bean="autoRepeatRequestTask" /></property><!-- 错过的定时任务不再执行 --><!-- <property name="misfireInstruction" value="2"></property> --><!-- cron表达式 --><property name="cronExpression"><value>0 * * * * ?</value><!--每分钟执行一次 --></property></bean><!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 --><bean id="startQuartz" lazy-init="false" autowire="no"class="org.springframework.scheduling.quartz.SchedulerFactoryBean"destroy-method="destroy"><property name="configLocation" value="classpath:quartz.properties" /><property name="dataSource" ref="dataSourceMysql" /><property name="triggers"><list><ref bean="autoRepeatRequestDoTime" /></list></property><property name="startupDelay" value="10" /><property name="applicationContextSchedulerContextKey" value="applicationContextKey" /></bean>
(2)MethodInvokingJobDetailFactoryBean在集群环境下会出现job无法序列化的问题,spring目前为止还没有修复。

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

@PersistJobDataAfterExecution@DisallowConcurrentExecution // 不允许并发执行public class AutoRequestRepeatJob extends QuartzJobBean {    private static final Logger LOGGER = LoggerFactory.getLogger(AutoRequestRepeatJob.class);        @Override    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {        RequestRepeatService requestRepeatService = getApplicationContext(context).getBean(RequestRepeatService.class);        requestRepeatService.autoRepeatRequest();    }    private ApplicationContext getApplicationContext(final JobExecutionContext jobexecutioncontext) {        try {            return (ApplicationContext) jobexecutioncontext.getScheduler().getContext().get("applicationContextKey");        } catch (SchedulerException e) {            LOGGER.error("jobexecutioncontext.getScheduler().getContext() error!", e);            throw new RuntimeException(e);        }    }}

(3)集群配置quartz.properties

#==============================================================    #Configure Main Scheduler Properties    #==============================================================     org.quartz.scheduler.instanceId=AUTOorg.quartz.scheduler.instanceName=AUTO_REPEAT_REQUEST#============================================================================  # Configure JobStore    #============================================================================  org.quartz.jobStore.isClustered=trueorg.quartz.jobStore.clusterCheckinInterval=15000org.quartz.jobStore.misfireThreshold = 60000 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX  org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate  org.quartz.jobStore.tablePrefix = t_esfjy_qrtz_  org.quartz.jobStore.useProperties = false#prevent lock time-outorg.quartz.jobStore.txIsolationLevelSerializable=true#============================================================================  # Configure ThreadPool    #============================================================================ org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPoolorg.quartz.threadPool.threadCount=10org.quartz.threadPool.threadPriority=5org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true  

这其中有两个碰到的坑

一个是

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

第二个是

org.quartz.jobStore.misfireThreshold = 60000 
这个大坑我研究了好久,因为之前开发时候为了调试方便,然后定的15s执行一次quartz任务,导致了任务重发执行。后来发现是这个配置的原因。

详见点击打开链接

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

还有一个是

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

0 0
原创粉丝点击