当前位置: 首页 > 知识库问答 >
问题:

重复几次后,Quartx SimpleTrigger将进入阻塞状态

金毅
2023-03-14

我使用SimpleTrigger来安排一个应该无限期运行的作业(重复计数-1)。

我正在使用JDBC store在数据库中持久化作业状态。

但是触发器会触发一段时间(在我的例子中总是8次)并进入阻塞状态。具体来说,在QRTZ_触发器表中,触发器_状态的值将更改为BLOCKED。注意:我的Quartx表格前缀是QRTZ_uuu,下面是我的工作触发信息。

重复计数:-1,重复间隔:6秒,开始延迟:10秒

我的石英配置:

#===============================================================
#Configure ThreadPool
#===============================================================
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
#===============================================================
#Configure JobStore
#===============================================================
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.maxMisfiresToHandleAtATime=20
# Flag to turn off to ignore all misfires
scheduler.ignoreMisfire=no

# Configuring JDBCJobStore with the Table Prefix
org.quartz.jobStore.tablePrefix = QRTZ_

# Using DriverDelegate
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
org.quartz.jobStore.useProperties = false

调度程序类:

public static void scheduleJob(Class<? extends Job> job,JobDataMap dataMap) 
{

    Scheduler scheduler = schedulerFactoryBean.getScheduler();
    try
    {
        JobDetail jobDetail = newJob(job)
                .withIdentity(job.getSimpleName()+"_"+DateUtil.getSystemDate(), job.getSimpleName() + "_group")
                .storeDurably()
                .usingJobData(dataMap)
                .requestRecovery()
                .build();

        SimpleTrigger trigger = (SimpleTrigger) newTrigger()
                .withIdentity(job.getSimpleName() + "_trigger_"+DateUtil.getSystemDateWithMs(), job.getSimpleName() + "_trigger_group")
                .startNow()                 
                .withSchedule(simpleSchedule().repeatSecondlyForever(10).withMisfireHandlingInstructionFireNow())
                .build();

        scheduler.scheduleJob(jobDetail, trigger);

        //logger.debug(scheduler.getMetaData().toString());
        scheduler.start();
    }
    catch (SchedulerException e)
    {
        e.printStackTrace();
        throw new SchedulerException("", e);
    }
}

职业类别:

@PersistJobDataAfterExecution
public class MyJob  Implements Job
{
    private SessionFactory sessionFactory;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException
    {
        getBeansFromContext(context);
        Session session = sessionFactory.openSession(); // Hibernate Session Factory
        // to do some DB opetations
    }

    private void getBeansFromContext(JobExecutionContext context) throws SchedulerException
    {
        ApplicationContext applicationContext = (ApplicationContext)context.getScheduler().getContext().get("applicationContext");
        this.sessionFactory=applicationContext.getBean(SessionFactory.class);
    }
}

石英调度器工厂的Spring bean配置。

<beans:bean id="schedulerFactoryBean"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<beans:property name="jobFactory">
    <beans:bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory"></beans:bean>
</beans:property>
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="transactionManager" ref="txManager" />
<beans:property name="configLocation"
    value="resources/scheduler/Scheduler.properties" />
<beans:property name="applicationContextSchedulerContextKey"
    value="applicationContext" />
<beans:property name="autoStartup" value="true" />
</beans:bean>

<beans:bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"
p:corePoolSize="5" p:maxPoolSize="10" p:queueCapacity="100"
p:waitForTasksToCompleteOnShutdown="true" />

非常感谢您的帮助。提前谢谢

共有2个答案

西门建安
2023-03-14

我在CRON触发器方面遇到了类似的问题,根本原因也是Spring管理的事务。

然而,我所做的解决问题的方法与你的有点不同。

我在代码级别保留了@Transactional注释,并为Quartz配置了专用的dataSource,用于自己的DB操作,而无需Spring的干预。

 <!-- Datasource used by Quartz -->
<bean id="quartzDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${db.driver}"/>
    <property name="url" value="${db.url}"/>
    <property name="username" value="${db.user}"/>
    <property name="password" ref="dbPassword"/>
    <property name="maxActive" value="${db.conn.pool.maxActive:30}"/>
    <property name="maxIdle" value="${db.conn.pool.maxIdle:15}"/>
    <property name="minIdle" value="${db.conn.pool.minIdle:0}"/>
</bean>
<!-- Datasource used by Quartz --> 


 <!-- Assign an dedicated dataSource to quartz scheduler-->
 <bean id="cronJobScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="configLocation" value="classpath:META-INF/quartz/quartz.properties"/>
    <property name="jobFactory" ref="springBeanJobFactory"/>
    <property name="dataSource" ref="quartzDataSource"/>
 </bean>
袁旻
2023-03-14

我终于明白了这个问题,并且能够解决它。

正如@zerologiko所评论的,问题在于事务。我将Spring管理的事务与hibernate一起使用。一旦我声明了我的事务策略,Spring就会负责事务的开始/结束。

在我的例子中出现问题的原因是:Springbean生命周期在调度程序作业中无效。为了详细说明这一点,正如在主要帖子中给出的那样,我甚至不得不使用

jobContext.getScheduler(). getContext(). get("Application ationContext");

我正在尝试在工作完成后用一些状态将DB更新回我们的一个事务数据库

我最初没有意识到,即使是事务也由Spring控制。当这些数据库更新是从作业类触发时,在我的业务方法上声明的事务没有任何影响。

根据我的理解,触发器将被获取,因为完成任务的线程无法返回池。

为了解决这个问题,我在我的作业类中手动打开/关闭事务,而不依赖Spring CMT,并且它工作正常。

希望这对面临同样问题的人有所帮助。

 类似资料:
  • 我发现这是超过2岁的线。我想问一个新问题这样我就能得到更多的关注 非阻塞子流程。呼叫 我的问题: 我和@DavidJB有着相同的情况,正如他在之前的帖子中所描述的 谢谢,这似乎可以工作,但是当我在slave.py中包括一个虽然循环时,它似乎卡住了,没有在循环中执行任何东西(即使有一个timer.sleep()函数...?-DavidJB Apr 17'13 at 23:59 有人对此有什么最新消息

  • 我完全混淆了,,。 哪个是阻塞,哪个不是? 我的意思是如果我使用父进程是否等待子进程返回/才继续执行。 如何影响这些调用?

  • 我有一个应用程序,在其中按下开始按钮后,服务将开始轮询几个传感器,每当传感器值发生变化时,将传感器数据存储到某个对象中。每10毫秒,就会发生一次数据库插入,获取对象的当前值并将其存储到数据库中。这会发生30分钟 考虑到插入的速度和持续时间,我想在一个独立于UI线程的线程中运行它,这样导航就不会受到影响。因此,我的服务将通过将数据添加到队列中来为线程提供一些数据,然后另一个线程(消费者)将从队列中取

  • 问题内容: 我正在通过TCP / IP套接字读取数据流。流负载非常不均匀。有时每秒会有大量数据到达,有时一个小时没有数据到达。在长时间不活动的情况下(远程服务器没有数据,但连接仍然在线),我的程序应采取一些措施。 我正在使用select()实现超时。它告诉我是否已经准备好数据,但是我不知道在不引起read()阻塞的情况下我可以读取多少数据。阻止是无法接受的,因为它的持续时间可能远远超过我需要的超时

  • 我想用Tkinter创建一个非阻塞消息窗口。这是为了在另一个函数正在等待答复时显示等待消息。收到回复后,窗口可自动关闭。我设法在网上找到了一些信息,我做了以下工作: 当我将其作为主脚本执行时,这运行良好,但是当我在得到以下错误RuntimeError之后想要使用Tkinter运行另一个gui应用程序时:主线程不在主循环中 另外,当我在App.destroy()之后运行另一段代码时。然后应用程序窗口