• spring定时器任务多任务串行执行问题排查


    原文:https://www.cnblogs.com/youtianhong/p/6027249.html

        最近发现个生产问题,定时器任务某些任务没有及时执行。经过研究排查发现spring 定时器任务scheduled-tasks默认配置是单线程串行执行的,这就造成了若某个任务执行时间过长,其他任务一直在排队,业务逻辑没有及时处理的问题。

    如下是scheduled定义了3个任务。

    <task:scheduled-tasks >
      <task:scheduled ref="myTask1" method="run" cron="0 0/59 10-23 * * ?"/>
      <task:scheduled ref="myTask2" method="run" cron="0/10 * * * * ?"/>
      <task:scheduled ref="myTask3" method="run" cron="0/10 * * * * ?"/>
    </task:scheduled-tasks>

    查看该任务17点的执行日志(task名字已修改)

    zgrep -e '2016-10-28 17:' channel-task.log.2016-10-28.log.gz | grep -e 'MyTask2' 

    2016-10-28 17:14:25,002 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] start task >> .MyTask2@186d315
    2016-10-28 17:14:35,980 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] complete task MyTask2@186d315
    2016-10-28 17:14:40,002 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] start task >> .MyTask2@186d315
    2016-10-28 17:14:50,681 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] complete task .MyTask2@186d315
    2016-10-28 17:14:55,003 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] start task >> .MyTask2@186d315
    2016-10-28 17:15:05,613 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] complete task MyTask2@186d315

    2016-10-28 17:20:35,246 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] start task >> .MyTask2@186d315
    2016-10-28 17:20:46,051 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] complete task .MyTask2@186d315

    2016-10-28 17:20:50,003 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] start task >> .MyTask2@186d315
    2016-10-28 17:21:00,974 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] complete task MyTask2@186d315

    MyTask2每10秒钟执行一次,但是在17:15:05 到17:20:35之间,5分钟内定时任务没有执行

    执行命令 zgrep -e '2016-10-28 17:1' task.log.2016-10-28.log.gz  (当天17点10几分发生的日志)

    然后在查询日志发现,这5分钟之内有大量的日志在执行

    2016-10-28 17:17:20,202 INFO [pool-8-thread-1 - ] task.MyTask3 - compare query order[ 211621610280893418 ] 
    2016-10-28 17:17:20,477 INFO [pool-8-thread-1 - ] task.MyTask3 - compare query order[ 211621610280893401 ] 
    2016-10-28 17:17:20,731 INFO [pool-8-thread-1 - ] task.MyTask3 - compare query order[ 211621610280893402 ] 
    .........中间省略n条日志

    2016-10-28 17:19:59,752 INFO [pool-8-thread-1 - ] task.MyTask3 - compare query order[ 211621610280894049 ]

    通过过以上日志可以看出,该线程[pool-8-thread-1 - ] 一直在处理MyTask3任务,此时断定 task:scheduled 配置默认是单线程串行的,

    网上查找资料发现如下配置可以解决问题

    <task:scheduler id="scheduler" pool-size="3" />
    <task:scheduled-tasks scheduler="scheduler" >
      <task:scheduled ref="myTask1" method="run" cron="0 0/59 11-23 * * ?"/>
      <task:scheduled ref="myTask2" method="run" cron="0/10 * * * * ?"/>
      <task:scheduled ref="myTask3" method="run" cron="0/10 * * * * ?"/>
    </task:scheduled-tasks>

    如果是注解的方式

    @Scheduled(cron = "0 0/1 * * * ?")

    那就在applicationContext.xml文件加入<task:scheduler id="scheduler" pool-size="2" />这一行,pool-size表示线程的个数

    或者是下面的这一种方式

        1.简单单任务定时器的spring配置

    <!-- 配置定时任务,用于初始化定时器 -->  
        <bean id="InitJobDetail"  
            class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
            <property name="targetObject">  
                <ref bean="ReportJobTodo"/>  
            </property>  
            <property name="targetMethod">  
                <value>initJobTrigger</value>  
            </property>  
            <property name="concurrent" value ="false"/>    
        </bean>  
        <bean id="ReportJobTodo"  
            class="cn.com.gsoft.report.timetask.ReportJobTodo">  
        </bean>  
        <bean id="InitTrigger"  
            class="org.springframework.scheduling.quartz.CronTriggerBean">  
            <property name="jobDetail">  
                <ref bean="InitJobDetail"/>  
            </property>  
            <property name="cronExpression">  
                <value>* * * * * ?</value>  
            </property>  
        </bean>  
        <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
            <property name="triggers">  
                <list>  
                    <ref local="InitTrigger"/>  
                </list>  
            </property>  
        </bean>  
    <!-- 配置定时任务,用于初始化定时器 -->
     <bean id="InitJobDetail"
      class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
      <property name="targetObject">
       <ref bean="ReportJobTodo"/>
      </property>
      <property name="targetMethod">
       <value>initJobTrigger</value>
      </property>
         <property name="concurrent" value ="false"/> 
     </bean>
     <bean id="ReportJobTodo"
      class="cn.com.gsoft.report.timetask.ReportJobTodo">
     </bean>
     <bean id="InitTrigger"
      class="org.springframework.scheduling.quartz.CronTriggerBean">
      <property name="jobDetail">
       <ref bean="InitJobDetail"/>
      </property>
      <property name="cronExpression">
       <value>* * * * * ?</value>
      </property>
     </bean>
     <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
      <property name="triggers">
       <list>
        <ref local="InitTrigger"/>
       </list>
      </property>
     </bean>

    说明:(1).InitJobDetail实例声明了需要执行的任务。其中targetObject说明了需要执行的方法所在的实例对象,targetMethod说明了要执行的方法,concurrent用于说明多个任务是否同步执行。

             (2).InitTrigger声明了一个触发器。jobDetail属性指明需要执行的任务,cronExpression声明了该任务在什么时候执行,该表达式跟linux下的crontab定时程序中使用的表达式是一样的,具体使用方法可以参考文后的参考资料。

             (3).SchedulerFactoryBean中可以定义多个触发器,以实现多任务。

  • 相关阅读:
    香港2013迷你制汇节即将启幕
    neuroph轻量级神经网络框架
    java如何实现python的urllib.quote(str,safe='/')
    python 的日志logging模块
    Python 代码使用pdb调试技巧
    python中reload(module)的用法,以及错误提示
    Notepad++如何取消打开最近的历史文件
    机器学习--入门答疑
    计算机的启动过程
    缓存设计
  • 原文地址:https://www.cnblogs.com/shihaiming/p/8447132.html
Copyright © 2020-2023  润新知