分布式作业: Elastic-Job

1. 背景介绍

Spring框架自带的定时任务scheduled如果部署多台机器时,同一个任务会执行多次,比如给用户计算收益定时任务,每天定时给用户计算收益,如果部署了多台,同一个用户将重复计算多次收益(业务错误),但如果只部署一台机器,无法保证高可用性,如果定时任务机器宕机,无法故障转移;

Elastic-Job基于Zookeeper、Quartz开发的Java分布式定时任务解决方案。

2. 优点

  • 高可用性:可用于分布式系统,可在多台机器上部署同一套定时任务,由于是基于zookeeper注册中心的,如果分片只有一个只会在其中一台机器上执行,不会出现同一任务执行多次的情况,如果该台机器故障,会将定时任务转移到其他正常的机器上实现故障转移。

  • 热点分布:如果分片大于一个,调度中心会根据分片总数和部署的机器总数,会将分片均匀安排到各个机器上执行;每一个分片只执行一次;

  • 故障转移:如果某台机器故障,会将定时任务转移到其他正常的机器上实现故障转移。

3. SpringBoot整合SimpleJob作业

3.1引入依赖
<dependency>
    <groupId>com.dangdang</groupId>
    <artifactId>elastic-job-lite-core</artifactId>
    <version>2.1.5</version>
</dependency>
<dependency>
    <groupId>com.dangdang</groupId>
    <artifactId>elastic-job-lite-spring</artifactId>
    <version>2.1.5</version>
</dependency>
3.2 环境信息配置
# Zookeeper注册中心
regCenter.serverList = localhost:2181
# Zookeeper的命名空间
regCenter.namespace = vincent-job-springboot
# 定时
vincentJob.cron = 0/6 * * * * ?
# 作业分片总数
vincentJob.shardingTotalCount = 4
# 分片序列号和参数用等号分隔,多个键值对用逗号分隔
# 分片序列号从0开始,不可大于或等于作业分片总数
# 未指定分片参数,默认null
# 如:0=a,1=b,2=c
vincentJob.shardingItemParameters = 0=a,1=b
3.3 注册中心配置
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;

@Configuration
public class ElasticRegCenterConfig {
    @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));
    }
}

注册中心是通过zookeeper实现的,其类型为:ZookeeperRegistryCenter而他需要一个zookeeper的配置ZookeeperConfiguration实体类;

参数说明

  • serverLists:连接Zookeeper服务器的列表,包括IP地址和端口号,多个地址用逗号分隔,如: host1:2181,host2:2181

  • namespace:Zookeeper的命名空间,/如果你有多个不同 Elastic-Job集群 时,使用相同 Zookeeper,可以配置不同的 namespace 进行隔离

  • baseSleepTimeMilliseconds:等待重试的间隔时间的初始值 单位:毫秒

  • maxSleepTimeMilliseconds:等待重试的间隔时间的最大值 单位:毫秒

  • maxRetries:最大重试次数

  • sessionTimeoutMilliseconds:会话超时时间 单位:毫秒

  • connectionTimeoutMilliseconds:连接超时时间 单位:毫秒

  • digest:连接Zookeeper的权限令牌,缺省为不需要权限验证

3.4 数据库配置用于日志记录(可选)
/**
 * 自定义数据源配置,一般只需要在application.yml文件中配置即可
 */
@Configuration
@AutoConfigureBefore(org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {

    @Resource
    DataSourceProperties properties;

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(properties.getUrl());
        dataSource.setUsername(properties.getUsername());
        dataSource.setPassword(properties.getPassword());
        dataSource.setDriverClassName(properties.getDriverClassName());
        return dataSource;
    }
}
3.5 自定义注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ElasticSimpleJob {
    String jobName() default "simpleJob";
    String core() default "0/5 * * * * ?";
    int shardingTotalCount() default 1;
    String shardingItemParameters() default "";
    String jobParameter() default "";
    boolean overWriter() default  false;
}
3.6 定时任务

实现SimpleJob接口

@Component
@ElasticSimpleJob(
        jobName = "myElasticJob",
        core = "0/10 * * * * ?",
        shardingTotalCount = 4,
        shardingItemParameters = "0=a,1=b",
        overWriter = true
)
public class MyElasticJob implements SimpleJob {

    @Override
    public void execute(ShardingContext shardingContext) {
        System.out.println(shardingContext.getShardingTotalCount() + "  " + shardingContext.getShardingItem()
        +"  "+shardingContext.getShardingParameter());
        switch (shardingContext.getShardingItem()) {
            //总共分成四片,定义每个分片上执行的具体任务,根据部署的机器台数不同分片将在不同机器上执行
            case 0:
                System.out.println("hello one " + shardingContext.getShardingParameter());
                break;
            case 1:
                System.out.println("hello two " + shardingContext.getShardingParameter());
                break;
            case 2:
                System.out.println("hello three " + shardingContext.getShardingParameter());
                break;
            case 3:
                System.out.println("hello fore " + shardingContext.getShardingParameter());
                break;
        }
    }
}

@Component
@ElasticSimpleJob(
        jobName = "simpleJobDemo",
        core = "0/5 * * * * ?",
        shardingTotalCount = 2,
        shardingItemParameters = "0=a,1=b",
        overWriter = true
)
public class SimpleJobDemo implements SimpleJob {
    public void execute(ShardingContext shardingContext) {
      //分片任务数2,没有区分分片任务,则两个分片上执行的任务一样,若只有一台机器则执行两次,若有两台机器则在两台机器上分别执行一次
        System.out.println(String.format("------Thread ID: %s, %s,任务总片数: %s, " +"当前分片项: %s.当前参数: %s," +"当前任务名称: %s.当前任务参数 %s",
                Thread.currentThread().getId(),
                new SimpleDateFormat("HH:mm:ss").format(new Date()),
                shardingContext.getShardingTotalCount(),
       
  • 19
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值