1.简介
elastic-job是当当网基于Zookepper,Quartz开发并开源的Java分布式定时任务,解决Quartz不支持分布式的弊端。由两个相互独立的子项目Elastic-job-lite和Elastic-job-cloud组成。
2.基本概念
- 分片:任务分布式执行,需要将一个任务拆分成多个独立的任务项,然后由分布式的服务器分别执行某一个或几分分片项。
- 个性化参数:shardingItemParameter,可以和分片项匹配对应关系,用于将分片项的数字转换为更加可读的业务代码。比如:将商品状态分为启用、禁用。那么配置0=禁用,1=启用,代码中直接使用启用禁用的枚举值即可完成分片项与业务逻辑的对应关系。
- 作用高可用:将任务拆分成N个任务项后,多台服务器执行作业将采用1主N从的方式执行。比如将分片总数设置为1,并使用多于1台的服务器执行作业,作业将会以1主N从的方式执行。一旦执行作业的服务器崩溃,等待执行的服务器将会在下次作业启动时替补执行,开启失效转移效果更好,可以保证在本次作业执行时崩溃,备用机器立即启动替补执行。
- 弹性扩容:将任务拆分成N个任务项后,各个服务器分别执行各自分配到的任务项。一旦有新的服务器加入集群或有服务器宕机,Elastic-job将保留本次任务不变,下次任务开始前重新分片。
- 并行调度:采用任务分片方式实现,将一个任务拆分成N个独立的任务项,由分布式的服务器并行执行各自分配到的分片项。
3.用法
1)引入maven依赖
<!-- elastic-jobs核心模块 --> <dependency><groupId>com.dangdang</groupId><artifactId>elastic-job-lite-core</artifactId><version>${elastic-job.version}</version> </dependency><!-- 使用springframework自定义命名空间时引入 --> <dependency><groupId>com.dangdang</groupId><artifactId>elastic-job-lite-spring</artifactId><version>${elastic-job.version}</version> </dependency>
2)作业配置:
application-dev.properties:
<!-- 作业注册中心 --> regCenter.serverList=*.*.*.*:2182
application.properties:
<!-- 配置定时发送提醒消息作业 --> simpleJob.productJob.cron=0 0/1 * * * ? simpleJob.productJob.shardingTotalCount=2 simpleJob.productJob.shardingItemParameters=0=A,1=B
参数说明:
cron:控制作业触发时间
shardingTotalCount:作业分片总数。可以将分片项设置为大于服务器的数量,最好是大于服务器倍数的数量,作业将会合理的利用分布式资源,动态的分配分片项。例如三台服务器XYZ,分成10片,则分片项分配结果为服务器X=0,1,2,服务器Y=3,4,5,服务器Z=6,7,8,9。如果服务器Z崩溃,则分片项分配结果为服务器X=0,1,2,3,4,服务器Y=5,6,7,8,9。在不丢失分片项的情况下,最大项度的利用现有资源提高吞吐量。
sharding-item-paramters:分片序列号和参数用等号分隔,多个键值对用逗号分隔片。序列号从0开始,不可大于或等于作业分片总数,如:0=a,1=b,2=c。
3)与springboot整合,解决zk注册中心的注入
@Configuration @ConditionalOnExpression("'${regCenter.serverList}'.length() > 0") public class RegistryCenterConfig {@Bean(initMethod = "init")public ZookeeperRegistryCenter regCenter(@Value("${regCenter.serverList}") final String serverList, @Value("${regCenter.namespace}") final String namespace) {return new ZookeeperRegistryCenter(new ZookeeperConfiguration(serverList, namespace));} }
4)组装并注入各种自定义的定时任务
@Configuration public class SimpleJobConfig {private Logger logger = LoggerFactory.getLogger(SimpleJobConfig.class);@Resourceprivate ZookeeperRegistryCenter regCenter;@Beanpublic ProductJob simpleProductJob() {return new ProductJob();}@Bean(initMethod = "init")public JobScheduler productTaskJobScheduler(final ProductJob simpleJob,@Value("${simpleJob.productJob.cron}") final String cron,@Value("${simpleJob.productJob.shardingTotalCount}") final int shardingTotalCount,@Value("${simpleJob.productJob.shardingItemParameters}") final String shardingItemParameters) {return new SpringJobScheduler(simpleJob, regCenter, getLiteJobConfiguration(simpleJob.getClass(), cron, shardingTotalCount, shardingItemParameters));}private LiteJobConfiguration getLiteJobConfiguration(final Class<? extends SimpleJob> jobClass, final String cron, final int shardingTotalCount,final String shardingItemParameters) {logger.info("Init scheduler : jobClass = {} , corn = {}", jobClass.getName(), cron);return LiteJobConfiguration.newBuilder(new SimpleJobConfiguration(JobCoreConfiguration.newBuilder(jobClass.getName(), cron, shardingTotalCount).shardingItemParameters(shardingItemParameters).build(), jobClass.getCanonicalName())).overwrite(false).build();}}
5)作业开发
public class ProductJob implements SimpleJob {@Overridepublic void execute(ShardingContext context) {logger.info("************ 商品任务同步开始 ************");//获取分片,根据不同的分片,执行不同的任务switch(context.getShardingItem()){case 0://处理id为基数的商品break;case 1://处理id为偶数的商品break;}logger.info("************ 商品任务同步结束 ************");} }
注意:上边只用到了分片索引和分片数,并不需要参数,所以随便配置了一个类似0=A,1=B就可以了。如果有业务场景希望知道分片索引的同时,还希望额外传一些参数进来,就可以在这里配置你希望的参数,然后在execute中读取到相应的参数,context.getShardingParameter()。