1、概述
什麼是elastic-job-lite,它是定位爲輕量級無中心化解決方案,使用jar包的形式提供分佈式任務的協調服務,具體可以點擊鏈接進入官網Elastic-Job-Lite查看,本文主要使用elastic-job-lite和spring進行二次封裝,搭建自己的分佈式定時任務程序。設計思路是利用spring的自動裝載和ApplicationListener特性,在運行時掃描註冊相關標註爲Job註解類。
2、引入包名
<!--Spring 相關--->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!--elastic-job--->
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-spring</artifactId>
</dependency>
3、定義註解
定義一個接口或類註解該註解,運行時掃描所有使用該註解的接口或方法。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Component
public @interface ElasticScheduledJob {
/**
* cron 表達式
*/
String cron();
}
4、定義抽象類
繼承elastic-job中的SimpleJob,擴展兩個方法,方便繼承類使用。
public abstract class AbsSingleJob implements SimpleJob {
protected final Logger log = LoggerFactory.getLogger(getClass());
@Override
public void execute(ShardingContext shardingContext) {
String name = getClass().getSimpleName();
long startTime = System.currentTimeMillis();
try {
log.info("Job {} execute start, sharding context = {}", name, shardingContext);
process(shardingContext);
log.info("Job {} execute finish after {}ms", name, System.currentTimeMillis() - startTime);
} catch (Exception e) {
log.error("Job " + name + " error occur", e);
handleException();
}
}
/**
* 捕獲異常(需要處理異常可重載handleException方法)和記錄執行日誌
*/
protected void handleException() {
}
/**
* 業務邏輯在這裏實現
*/
protected abstract void process(ShardingContext shardingContext);
}
5、註冊Job
- 註冊
啓動時從 ApplicationContext 中掃描 scheduler,對所有標註ElasticScheduledJob類進行掃描並進行註冊
/**
* 加載所有job, 從 ApplicationContext 中掃描 scheduler
*/
private void initialize(ConfigurableApplicationContext applicationContext) {
// 掃描註解ElasticScheduledJob的類
for (Object bean : applicationContext.getBeansWithAnnotation(ElasticScheduledJob.class).values()) {
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
ElasticScheduledJob annotation = AnnotationUtils.findAnnotation(targetClass, ElasticScheduledJob.class);
if (annotation != null) {
// 獲取job配置
JobConfig jobConfig = JobConfig.newSingle(annotation.cron(), (AbsSingleJob) bean);
JobScheduler scheduler = buildScheduler(jobConfig);
scheduler.init();// 初始化
applicationContext.getBeanFactory().registerSingleton(targetClass.getCanonicalName() + "Scheduler", scheduler);
}
}
}
- 創建任務
private JobScheduler buildScheduler(JobConfig jobConfig) {
return NewJobBuilder.newJobBuilder()
.setRegCenter(registryCenter)
.build(jobConfig);
}
- 構建JobScheduler
public JobScheduler build(JobConfig jobConfig) {
// 創建job配置
LiteJobConfiguration jobConfiguration = createJobConfiguration(checkJobConfig(jobConfig));
// 註冊監聽
ElasticJobListener[] l;
if (listeners != null) {
l = new ElasticJobListener[listeners.getListeners().size()];
listeners.getListeners().toArray(l);
} else {
l = new ElasticJobListener[0];
}
// 不使用作業事件監聽器
if (jobEventConfiguration == null) {
return jobConfig.getElasticJob() != null
? new SpringJobScheduler(jobConfig.getElasticJob(), regCenter, jobConfiguration)
: new JobScheduler(regCenter, jobConfiguration, l);
}
// 使用作業事件監聽器
return jobConfig.getElasticJob() != null
? new SpringJobScheduler(jobConfig.getElasticJob(), regCenter, jobConfiguration, jobEventConfiguration)
: new JobScheduler(regCenter, jobConfiguration, jobEventConfiguration, l);
}
6、使用
使用方式很簡單,直接繼承AbsSingleJob,重寫相關方法,並類加入@ElasticScheduledJob註解即可。
@ElasticScheduledJob(cron = "0/2 * * * * ? * ")
public class CsgoBattleJob extends AbsSingleJob {
@Override
protected void process(ShardingContext shardingContext) {
// 定時任務業務邏輯
}
}
elastic-job-lite二次封裝核心內容上面已經介紹完,具體代碼可以到github查看。