xxl-job源码学习笔记之调度中心

启动日志

22:29:59.031 logback [main] INFO  c.x.r.r.p.XxlRpcProviderFactory - >>>>>>>>>>> xxl-rpc, provider factory add service success. serviceKey = com.xxl.job.core.biz.AdminBiz, serviceBean = class com.xxl.job.admin.service.impl.AdminBizImpl
22:29:59.036 logback [main] INFO  c.x.j.a.core.conf.XxlJobScheduler - >>>>>>>>> init xxl-job admin success.
22:29:59.438 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerAdapter - Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@16eccb2e: startup date [Sun Aug 04 22:29:54 CST 2019]; root of context hierarchy
22:29:59.503 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/help]}" onto public java.lang.String com.xxl.job.admin.controller.IndexController.help()
22:29:59.506 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/]}" onto public java.lang.String com.xxl.job.admin.controller.IndexController.index(org.springframework.ui.Model)
22:29:59.507 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/chartInfo]}" onto public com.xxl.job.core.biz.model.ReturnT> com.xxl.job.admin.controller.IndexController.chartInfo(java.util.Date,java.util.Date)
22:29:59.507 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/logout],methods=[POST]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.IndexController.logout(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
22:29:59.508 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/toLogin]}" onto public java.lang.String com.xxl.job.admin.controller.IndexController.toLogin(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
22:29:59.508 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/login],methods=[POST]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.IndexController.loginDo(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse,java.lang.String,java.lang.String,java.lang.String)
22:29:59.509 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/api]}" onto public void com.xxl.job.admin.controller.JobApiController.api(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException
22:29:59.511 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobcode]}" onto public java.lang.String com.xxl.job.admin.controller.JobCodeController.index(javax.servlet.http.HttpServletRequest,org.springframework.ui.Model,int)
22:29:59.511 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobcode/save]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobCodeController.save(org.springframework.ui.Model,int,java.lang.String,java.lang.String)
22:29:59.513 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobgroup]}" onto public java.lang.String com.xxl.job.admin.controller.JobGroupController.index(org.springframework.ui.Model)
22:29:59.514 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobgroup/remove]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobGroupController.remove(int)
22:29:59.514 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobgroup/update]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobGroupController.update(com.xxl.job.admin.core.model.XxlJobGroup)
22:29:59.515 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobgroup/save]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobGroupController.save(com.xxl.job.admin.core.model.XxlJobGroup)
22:29:59.515 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobgroup/loadById]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobGroupController.loadById(int)
22:29:59.522 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobinfo]}" onto public java.lang.String com.xxl.job.admin.controller.JobInfoController.index(javax.servlet.http.HttpServletRequest,org.springframework.ui.Model,int)
22:29:59.522 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobinfo/add]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobInfoController.add(com.xxl.job.admin.core.model.XxlJobInfo)
22:29:59.523 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobinfo/remove]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobInfoController.remove(int)
22:29:59.524 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobinfo/update]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobInfoController.update(com.xxl.job.admin.core.model.XxlJobInfo)
22:29:59.524 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobinfo/start]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobInfoController.start(int)
22:29:59.524 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobinfo/pageList]}" onto public java.util.Map com.xxl.job.admin.controller.JobInfoController.pageList(int,int,int,int,java.lang.String,java.lang.String,java.lang.String)
22:29:59.525 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobinfo/trigger]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobInfoController.triggerJob(int,java.lang.String)
22:29:59.525 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/jobinfo/stop]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobInfoController.pause(int)
22:29:59.529 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/joblog]}" onto public java.lang.String com.xxl.job.admin.controller.JobLogController.index(javax.servlet.http.HttpServletRequest,org.springframework.ui.Model,java.lang.Integer)
22:29:59.529 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/joblog/pageList]}" onto public java.util.Map com.xxl.job.admin.controller.JobLogController.pageList(javax.servlet.http.HttpServletRequest,int,int,int,int,int,java.lang.String)
22:29:59.530 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/joblog/getJobsByGroup]}" onto public com.xxl.job.core.biz.model.ReturnT> com.xxl.job.admin.controller.JobLogController.getJobsByGroup(int)
22:29:59.530 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/joblog/logDetailCat]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobLogController.logDetailCat(java.lang.String,long,long,int)
22:29:59.530 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/joblog/logDetailPage]}" onto public java.lang.String com.xxl.job.admin.controller.JobLogController.logDetailPage(int,org.springframework.ui.Model)
22:29:59.531 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/joblog/clearLog]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobLogController.clearLog(int,int,int)
22:29:59.531 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/joblog/logKill]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.JobLogController.logKill(int)
22:29:59.533 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/user]}" onto public java.lang.String com.xxl.job.admin.controller.UserController.index(org.springframework.ui.Model)
22:29:59.535 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/user/add]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.UserController.add(com.xxl.job.admin.core.model.XxlJobUser)
22:29:59.536 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/user/remove]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.UserController.remove(javax.servlet.http.HttpServletRequest,int)
22:29:59.537 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/user/update]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.UserController.update(javax.servlet.http.HttpServletRequest,com.xxl.job.admin.core.model.XxlJobUser)
22:29:59.537 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/user/pageList]}" onto public java.util.Map com.xxl.job.admin.controller.UserController.pageList(int,int,java.lang.String,int)
22:29:59.538 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/user/updatePwd]}" onto public com.xxl.job.core.biz.model.ReturnT com.xxl.job.admin.controller.UserController.updatePwd(javax.servlet.http.HttpServletRequest,java.lang.String)
22:29:59.540 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
22:29:59.541 logback [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
22:29:59.582 logback [main] INFO  o.s.w.s.h.SimpleUrlHandlerMapping - Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
22:29:59.582 logback [main] INFO  o.s.w.s.h.SimpleUrlHandlerMapping - Mapped URL path [/static/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
22:29:59.623 logback [main] INFO  o.s.w.s.h.SimpleUrlHandlerMapping - Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
22:29:59.903 logback [main] INFO  o.s.w.s.v.f.FreeMarkerConfigurer - ClassTemplateLoader for Spring macros added to FreeMarker configuration
22:30:00.364 logback [main] INFO  o.s.j.e.a.AnnotationMBeanExporter - Registering beans for JMX exposure on startup
22:30:00.629 logback [main] INFO  o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-9001"]
22:30:00.799 logback [main] INFO  o.a.tomcat.util.net.NioSelectorPool - Using a shared selector for servlet write/read
22:30:00.834 logback [main] INFO  o.s.b.c.e.t.TomcatEmbeddedServletContainer - Tomcat started on port(s): 9001 (http)
22:30:00.844 logback [main] INFO  c.x.job.admin.XxlJobAdminApplication - Started XxlJobAdminApplication in 6.379 seconds (JVM running for 12.187)
22:30:04.000 logback [xxl-job, admin JobScheduleHelper#scheduleThread] INFO  c.x.j.a.c.thread.JobScheduleHelper - >>>>>>>>> init xxl-job admin scheduler success.
22:31:05.559 logback [http-nio-9001-exec-5] INFO  o.a.c.c.C.[.[.[/xxl-job-admin] - Initializing Spring FrameworkServlet 'dispatcherServlet'
22:31:05.559 logback [http-nio-9001-exec-5] INFO  o.s.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcherServlet': initialization started
22:31:05.584 logback [http-nio-9001-exec-5] INFO  o.s.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcherServlet': initialization completed in 25 ms

启动流程

XxlJobScheduler初始化过程中调用afterPropertiesSet()方法

XxlJobScheduler.java
//属性初始化后的处理方法
@Override
public void afterPropertiesSet() throws Exception {
    // init i18n
    //国际化属性文件
    initI18n();

    // admin registry monitor run
    // 注册中心
    JobRegistryMonitorHelper.getInstance().start();

    // admin monitor run
    // 失败报警处理器
    JobFailMonitorHelper.getInstance().start();

    // admin-server
    // 初始化 rpc 提供者
    initRpcProvider();

    // start-schedule
    //开启定时任务线程
    JobScheduleHelper.getInstance().start();

    logger.info(">>>>>>>>> init xxl-job admin success.");
}

JobRegistryMonitorHelper

package com.xxl.job.admin.core.thread;
JobRegistryMonitorHelper.java
public void start(){
	registryThread = new Thread(new Runnable() {
		@Override
		public void run() {
			while (!toStop) {
				try {
					// auto registry group
					// 自动注册作业job集合
					List<XxlJobGroup> groupList = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().findByAddressType(0);
					if (groupList!=null && !groupList.isEmpty()) {
	
						// remove dead address (admin/executor)
						// 机器宕机或者销毁的时候,主动把自己摘除掉
						List<Integer> ids = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().findDead(RegistryConfig.DEAD_TIMEOUT);
						if (ids!=null && ids.size()>0) {
							XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().removeDead(ids);
						}
	
						// fresh online address (admin/executor)
						// 刷新在线地址列表
						HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
						List<XxlJobRegistry> list = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().findAll(RegistryConfig.DEAD_TIMEOUT);
						if (list != null) {
							for (XxlJobRegistry item: list) {
								if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {
									String appName = item.getRegistryKey();
									List<String> registryList = appAddressMap.get(appName);
									if (registryList == null) {
										registryList = new ArrayList<String>();
									}
	
									if (!registryList.contains(item.getRegistryValue())) {
										registryList.add(item.getRegistryValue());
									}
									appAddressMap.put(appName, registryList);
								}
							}
						}
	
						// fresh group address
						//刷新集群中的注册机器列表
						for (XxlJobGroup group: groupList) {
							List<String> registryList = appAddressMap.get(group.getAppName());
							String addressListStr = null;
							if (registryList!=null && !registryList.isEmpty()) {
								Collections.sort(registryList);
								addressListStr = "";
								for (String item:registryList) {
									addressListStr += item + ",";
								}
								addressListStr = addressListStr.substring(0, addressListStr.length()-1);
							}
							group.setAddressList(addressListStr);
							XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().update(group);
						}
					}
				} catch (Exception e) {
					if (!toStop) {
						logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
					}
				}
				try {
					TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
				} catch (InterruptedException e) {
					if (!toStop) {
						logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
					}
				}
			}
			logger.info(">>>>>>>>>>> xxl-job, job registry monitor thread stop");
		}
	});
	registryThread.setDaemon(true);
	registryThread.setName("xxl-job, admin JobRegistryMonitorHelper");
	registryThread.start();
}

启动失败报警处理器线程

public void start(){
	monitorThread = new Thread(new Runnable() {

		@Override
		public void run() {

			// monitor
			while (!toStop) {
				try {

					List<Long> failLogIds = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().findFailJobLogIds(1000);
					if (failLogIds!=null && !failLogIds.isEmpty()) {
						for (long failLogId: failLogIds) {

							// lock log
							int lockRet = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateAlarmStatus(failLogId, 0, -1);
							if (lockRet < 1) {
								continue;
							}
							XxlJobLog log = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().load(failLogId);
							XxlJobInfo info = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(log.getJobId());

							// 1、fail retry monitor
							//失败重试
							if (log.getExecutorFailRetryCount() > 0) {
								JobTriggerPoolHelper.trigger(log.getJobId(), TriggerTypeEnum.RETRY, (log.getExecutorFailRetryCount()-1), log.getExecutorShardingParam(), null);
								String retryMsg = "

>>>>>>>>>>>"+ I18nUtil.getString("jobconf_trigger_type_retry") +"<<<<<<<<<<<
"
; log.setTriggerMsg(log.getTriggerMsg() + retryMsg); XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateTriggerInfo(log); } // 2、fail alarm monitor //失败告警 int newAlarmStatus = 0; // 告警状态:0-默认、-1=锁定状态、1-无需告警、2-告警成功、3-告警失败 if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) { boolean alarmResult = true; try { alarmResult = failAlarm(info, log); } catch (Exception e) { alarmResult = false; logger.error(e.getMessage(), e); } newAlarmStatus = alarmResult?2:3; } else { newAlarmStatus = 1; } XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateAlarmStatus(failLogId, -1, newAlarmStatus); } } TimeUnit.SECONDS.sleep(10); } catch (Exception e) { if (!toStop) { logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e); } } } logger.info(">>>>>>>>>>> xxl-job, job fail monitor thread stop"); } }); monitorThread.setDaemon(true); monitorThread.setName("xxl-job, admin JobFailMonitorHelper"); monitorThread.start(); }

开启定时任务线程

package com.xxl.job.admin.core.thread;
JobScheduleHelper.java
//定时线程
scheduleThread = new Thread(new Runnable() {
     @Override
     public void run() {

         try {
             TimeUnit.MILLISECONDS.sleep(5000 - System.currentTimeMillis()%1000 );
         } catch (InterruptedException e) {
             if (!scheduleThreadToStop) {
                 logger.error(e.getMessage(), e);
             }
         }
         logger.info(">>>>>>>>> init xxl-job admin scheduler success.");

         while (!scheduleThreadToStop) {

             // Scan Job
             long start = System.currentTimeMillis();

             Connection conn = null;
             Boolean connAutoCommit = null;
             PreparedStatement preparedStatement = null;

             boolean preReadSuc = true;
             try {

                 conn = XxlJobAdminConfig.getAdminConfig().getDataSource().getConnection();
                 connAutoCommit = conn.getAutoCommit();
                 conn.setAutoCommit(false);

                 //读取xxl_job_lock 任务调度锁表,一次循环在一个事务中
                 preparedStatement = conn.prepareStatement(  "select * from xxl_job_lock where lock_name = 'schedule_lock' for update" );
                 preparedStatement.execute();

                 // tx start

                 // 1、pre read
                 long nowTime = System.currentTimeMillis();
                 List<XxlJobInfo> scheduleList = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().scheduleJobQuery(nowTime + PRE_READ_MS);
                 if (scheduleList!=null && scheduleList.size()>0) {
                     // 2、push time-ring
                     for (XxlJobInfo jobInfo: scheduleList) {

                         // time-ring jump
                         //如果trigger-expire > 5s,当前时间戳大于(任务下次触发时间+PRE_READ_MS),跳过并更新下次触发时间
                         if (nowTime > jobInfo.getTriggerNextTime() + PRE_READ_MS) {
                             // 2.1、trigger-expire > 5s:pass && make next-trigger-time

                             // fresh next
                             Date nextValidTime = new CronExpression(jobInfo.getJobCron()).getNextValidTimeAfter(new Date());
                             if (nextValidTime != null) {
                                 jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime());
                                 jobInfo.setTriggerNextTime(nextValidTime.getTime());
                             } else {
                                 jobInfo.setTriggerStatus(0);
                                 jobInfo.setTriggerLastTime(0);
                                 jobInfo.setTriggerNextTime(0);
                             }

                         }
                         //如果trigger-expire < 5s,当前时间戳大于任务下次触发时间,触发任务并更新下次触发时间
                         else if (nowTime > jobInfo.getTriggerNextTime()) {
                             // 2.2、trigger-expire < 5s:direct-trigger && make next-trigger-time

                             CronExpression cronExpression = new CronExpression(jobInfo.getJobCron());
                             long nextTime = cronExpression.getNextValidTimeAfter(new Date()).getTime();

                             // 1、trigger
                             //触发器
                             JobTriggerPoolHelper.trigger(jobInfo.getId(), TriggerTypeEnum.CRON, -1, null, null);
                             logger.debug(">>>>>>>>>>> xxl-job, shecule push trigger : jobId = " + jobInfo.getId() );

                             // 2、fresh next
                             jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime());
                             jobInfo.setTriggerNextTime(nextTime);


                             // next-trigger-time in 5s, pre-read again
                             if (jobInfo.getTriggerNextTime() - nowTime < PRE_READ_MS) {

                                 // 1、make ring second
                                 int ringSecond = (int)((jobInfo.getTriggerNextTime()/1000)%60);

                                 // 2、push time ring
                                 pushTimeRing(ringSecond, jobInfo.getId());

                                 // 3、fresh next
                                 Date nextValidTime = new CronExpression(jobInfo.getJobCron()).getNextValidTimeAfter(new Date(jobInfo.getTriggerNextTime()));
                                 if (nextValidTime != null) {
                                     jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime());
                                     jobInfo.setTriggerNextTime(nextValidTime.getTime());
                                 } else {
                                     jobInfo.setTriggerStatus(0);
                                     jobInfo.setTriggerLastTime(0);
                                     jobInfo.setTriggerNextTime(0);
                                 }

                             }

                         } else {
                             // 2.3、trigger-pre-read:time-ring trigger && make next-trigger-time

                             // 1、make ring second
                             int ringSecond = (int)((jobInfo.getTriggerNextTime()/1000)%60);

                             // 2、push time ring
                             pushTimeRing(ringSecond, jobInfo.getId());

                             // 3、fresh next
                             Date nextValidTime = new CronExpression(jobInfo.getJobCron()).getNextValidTimeAfter(new Date(jobInfo.getTriggerNextTime()));
                             if (nextValidTime != null) {
                                 jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime());
                                 jobInfo.setTriggerNextTime(nextValidTime.getTime());
                             } else {
                                 jobInfo.setTriggerStatus(0);
                                 jobInfo.setTriggerLastTime(0);
                                 jobInfo.setTriggerNextTime(0);
                             }

                         }

                     }

                     // 3、update trigger info
                     for (XxlJobInfo jobInfo: scheduleList) {
                         XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().scheduleUpdate(jobInfo);
                     }

                 } else {
                     preReadSuc = false;
                 }

                 // tx stop


             } catch (Exception e) {
                 if (!scheduleThreadToStop) {
                     logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#scheduleThread error:{}", e);
                 }
             } finally {
                 //提交事务
                 if (conn != null) {
                     try {
                         conn.commit();
                     } catch (SQLException e) {
                         if (!scheduleThreadToStop) {
                             logger.error(e.getMessage(), e);
                         }
                     }
                     try {
                         conn.setAutoCommit(connAutoCommit);
                     } catch (SQLException e) {
                         if (!scheduleThreadToStop) {
                             logger.error(e.getMessage(), e);
                         }
                     }
                     try {
                         conn.close();
                     } catch (SQLException e) {
                         if (!scheduleThreadToStop) {
                             logger.error(e.getMessage(), e);
                         }
                     }
                 }

                 // close PreparedStatement
                 if (null != preparedStatement) {
                     try {
                         preparedStatement.close();
                     } catch (SQLException ignore) {
                         if (!scheduleThreadToStop) {
                             logger.error(ignore.getMessage(), ignore);
                         }
                     }
                 }
             }
             long cost = System.currentTimeMillis()-start;
             
             // Wait seconds, align second
             if (cost < 1000) {  // scan-overtime, not wait
                 try {
                     // pre-read period: success > scan each second; fail > skip this period;
                     TimeUnit.MILLISECONDS.sleep((preReadSuc?1000:PRE_READ_MS) - System.currentTimeMillis()%1000);
                 } catch (InterruptedException e) {
                     if (!scheduleThreadToStop) {
                         logger.error(e.getMessage(), e);
                     }
                 }
             }
         }
         logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper#scheduleThread stop");
     }
 });
 scheduleThread.setDaemon(true);
 scheduleThread.setName("xxl-job, admin JobScheduleHelper#scheduleThread");
 scheduleThread.start();
// ring thread
ringThread = new Thread(new Runnable() {
    @Override
    public void run() {
        // align second
        try {
            TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis()%1000 );
        } catch (InterruptedException e) {
            if (!ringThreadToStop) {
                logger.error(e.getMessage(), e);
            }
        }
        while (!ringThreadToStop) {
            try {
                // second data
                List<Integer> ringItemData = new ArrayList<>();
                int nowSecond = Calendar.getInstance().get(Calendar.SECOND);   // 避免处理耗时太长,跨过刻度,向前校验一个刻度;
                for (int i = 0; i < 2; i++) {
                    List<Integer> tmpData = ringData.remove( (nowSecond+60-i)%60 );
                    if (tmpData != null) {
                        ringItemData.addAll(tmpData);
                    }
                }

                // ring trigger
                logger.debug(">>>>>>>>>>> xxl-job, time-ring beat : " + nowSecond + " = " + Arrays.asList(ringItemData) );
                if (ringItemData!=null && ringItemData.size()>0) {
                    // do trigger
                    for (int jobId: ringItemData) {
                        // do trigger
                        JobTriggerPoolHelper.trigger(jobId, TriggerTypeEnum.CRON, -1, null, null);
                    }
                    // clear
                    ringItemData.clear();
                }
            } catch (Exception e) {
                if (!ringThreadToStop) {
                    logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread error:{}", e);
                }
            }

            // next second, align second
            try {
                TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis()%1000);
            } catch (InterruptedException e) {
                if (!ringThreadToStop) {
                    logger.error(e.getMessage(), e);
                }
            }
        }
        logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread stop");
    }
});
ringThread.setDaemon(true);
ringThread.setName("xxl-job, admin JobScheduleHelper#ringThread");
ringThread.start();
}

你可能感兴趣的:(xxl-job源码学习)