elastic-job学习 第一篇

根据官方文档实现了一个简单的simple类型(Elastic-Job提供Simple、Dataflow和Script 3种作业类型)的Demo。

官方介绍:

基本概念

1. 分片概念

任务的分布式执行,需要将一个任务拆分为多个独立的任务项,然后由分布式的服务器分别执行某一个或几个分片项。

例如:有一个遍历数据库某张表的作业,现有2台服务器。为了快速的执行作业,那么每台服务器应执行作业的50%。 为满足此需求,可将作业分成2片,每台服务器执行1片。作业遍历数据的逻辑应为:服务器A遍历ID以奇数结尾的数据;服务器B遍历ID以偶数结尾的数据。 如果分成10片,则作业遍历数据的逻辑应为:每片分到的分片项应为ID%10,而服务器A被分配到分片项0,1,2,3,4;服务器B被分配到分片项5,6,7,8,9,直接的结果就是服务器A遍历ID以0-4结尾的数据;服务器B遍历ID以5-9结尾的数据。

2. 分片项与业务处理解耦

Elastic-Job并不直接提供数据处理的功能,框架只会将分片项分配至各个运行中的作业服务器,开发者需要自行处理分片项与真实数据的对应关系。

3. 个性化参数的适用场景

个性化参数即shardingItemParameter,可以和分片项匹配对应关系,用于将分片项的数字转换为更加可读的业务代码。

例如:按照地区水平拆分数据库,数据库A是北京的数据;数据库B是上海的数据;数据库C是广州的数据。 如果仅按照分片项配置,开发者需要了解0表示北京;1表示上海;2表示广州。 合理使用个性化参数可以让代码更可读,如果配置为0=北京,1=上海,2=广州,那么代码中直接使用北京,上海,广州的枚举值即可完成分片项和业务逻辑的对应关系。

核心理念

1. 分布式调度

Elastic-Job-Lite并无作业调度中心节点,而是基于部署作业框架的程序在到达相应时间点时各自触发调度。

注册中心仅用于作业注册和监控信息存储。而主作业节点仅用于处理分片和清理等功能。

2. 作业高可用

Elastic-Job-Lite提供最安全的方式执行作业。将分片总数设置为1,并使用多于1台的服务器执行作业,作业将会以1主n从的方式执行。

一旦执行作业的服务器崩溃,等待执行的服务器将会在下次作业启动时替补执行。开启失效转移功能效果更好,可以保证在本次作业执行时崩溃,备机立即启动替补执行。

3. 最大限度利用资源

Elastic-Job-Lite也提供最灵活的方式,最大限度的提高执行作业的吞吐量。将分片项设置为大于服务器的数量,最好是大于服务器倍数的数量,作业将会合理的利用分布式资源,动态的分配分片项。

例如:3台服务器,分成10片,则分片项分配结果为服务器A=0,1,2;服务器B=3,4,5;服务器C=6,7,8,9。 如果服务器C崩溃,则分片项分配结果为服务器A=0,1,2,3,4;服务器B=5,6,7,8,9。在不丢失分片项的情况下,最大限度的利用现有资源提高吞吐量。

整体架构图

eaee31beda94ebcff90445f1209eb8002a9.jpg

环境说明

这里使用去中心化的版本elastic-job-lite。

JDK:1.8(elastic-job要1.7以上)

zookeeper:zookeeper-3.4.12 (官方要求zookeeper-3.4.6以上)

elastic-job-lite-core:2.0.3

依赖

        <dependency>
            <groupId>com.dangdang</groupId>
            <artifactId>elastic-job-lite-core</artifactId>
            <version>2.0.3</version>
        </dependency>

因为我使用了slf4j所以还需要引入依赖:

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.2</version>
        </dependency>

代码

我写了两个类一个是任务作业的实现类MyELasticJob,非常简单,这里只是写了一些日志的打印:

package com.elasticjob.demo;

import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.lite.api.JobScheduler;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.reg.base.CoordinatorRegistryCenter;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
 * @Description: 作业实现类
 * @Author: 张颖辉(yh)
 * @CreateDate: 2018/7/20 14:01
 * @UpdateUser: 张颖辉(yh)
 * @UpdateDate: 2018/7/20 14:01
 * @UpdateRemark: The modified content
 * @Version: 1.0
 */
public class MyELasticJob implements SimpleJob {

    private Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * @Description: 要执行的作业(分片)
     * @Author: 张颖辉(yh)
     * @Date: 2018/7/23 14:42
     * @param: [shardingContext]
     * @return: void
     * @Version: 1.0
     */
    @Override
    public void execute(ShardingContext shardingContext) {
        //任务分片
        switch (shardingContext.getShardingItem()) {
            case 0:
                logger.info("job名称={},分片数量={},当前分片={},当前分片名称={},当前自定义参数={} -----------", shardingContext.getJobName(), shardingContext.getShardingTotalCount(), shardingContext.getShardingItem(), shardingContext.getShardingParameter(), shardingContext.getJobParameter());
                break;
            case 1:
                logger.info("job名称={},分片数量={},当前分片={},当前分片名称={},当前自定义参数={} -----------", shardingContext.getJobName(), shardingContext.getShardingTotalCount(), shardingContext.getShardingItem(), shardingContext.getShardingParameter(), shardingContext.getJobParameter());
                break;
            case 2:
                logger.info("job名称={},分片数量={},当前分片={},当前分片名称={},当前自定义参数={} -----------", shardingContext.getJobName(), shardingContext.getShardingTotalCount(), shardingContext.getShardingItem(), shardingContext.getShardingParameter(), shardingContext.getJobParameter());
                break;
        }
    }
}

另外一个就是关于任务作业的设置和注册中心的设置以及任务的启动:

package com.elasticjob.demo;

import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.JobRootConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.lite.api.JobScheduler;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.reg.base.CoordinatorRegistryCenter;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;

/**
 * @Description: Description
 * @Author: 张颖辉(yh)
 * @CreateDate: 2018/7/23 11:30
 * @UpdateUser: 张颖辉(yh)
 * @UpdateDate: 2018/7/23 11:30
 * @UpdateRemark: The modified content
 * @Version: 1.0
 */
public class TestJob {
    public static void main(String[] args) {
        //作业参数
        String jobParameter = "作业节点-linux";
        if (isWindows()) {
            jobParameter = "作业节点-windows";
        }
        new JobScheduler(createRegistryCenter(), createJobConfiguration(jobParameter)).init();
    }

    /**
     * @Description: 创建注册中心
     * @Author: 张颖辉(yh)
     * @Date: 2018/7/20 15:09
     * @param: []
     * @return: com.dangdang.ddframe.job.reg.base.CoordinatorRegistryCenter
     * @Version: 1.0
     */
    private static CoordinatorRegistryCenter createRegistryCenter() {
        CoordinatorRegistryCenter registryCenter = new ZookeeperRegistryCenter(new ZookeeperConfiguration("192.168.5.100:2181", "elastic-job-demo"));
        registryCenter.init();
        return registryCenter;
    }


    /**
     * @Description: 创建作业配置
     * @Author: 张颖辉(yh)
     * @Date: 2018/7/20 15:08
     * @param:
     * @return:
     * @Version: 1.0
     */
    private static LiteJobConfiguration createJobConfiguration(String jobParameter) {
        // demoSimpleJob 为jobname, 0/10 * * * * ?为cron表达式,  3 分片数量,  0=北京,1=上海,2=广州 分片对应参数内容,  jobParameter 作业自定义参数
        // 定义作业核心配置
        JobCoreConfiguration jobCoreConfiguration = JobCoreConfiguration.newBuilder("demoSimpleJob_3p", "0/10 * * * * ?", 3).shardingItemParameters("0=北京,1=上海,2=广州").jobParameter(jobParameter).build();
        // 定义SIMPLE类型配置
        SimpleJobConfiguration simpleJobConfiguration = new SimpleJobConfiguration(jobCoreConfiguration, MyELasticJob.class.getCanonicalName());
        // 定义Lite作业根配置
        LiteJobConfiguration liteJobConfiguration = LiteJobConfiguration.newBuilder(simpleJobConfiguration).build();
        return liteJobConfiguration;
    }

    /**
     * @Description: 是不是windows
     * @Author: 张颖辉(yh)
     * @Date: 2018/7/23 15:15
     * @param:
     * @return:
     * @Version: 1.0
     */
    private static boolean isWindows() {
        return System.getProperties().getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1;
    }
}

关于作业的分片数量要与作业类中的execute方法里分支相匹配。

然后我在虚拟机下linux中安装了注册中心zookeeper(对应上面代码中指定的zookeeper配置)安装教程

将上面的两个类打成jar,上传到linux中执行,本地windows也执行一份。就会发现三个任务分片有两个在window下执行,

28cc61ac8c5569a0b7aa6fb8679002470da.jpg

剩下的一个在linux中执行了。

46252a66a6e455e84a76f4a4a00d0f94842.jpg

注意:需要两台不同ip的机器去启动job(作业服务器) 因为ElasticJob默认的分片机制是根据ip来分片的 如果ip相同 它会默认为一台服务器 。所以这里我把代码上传到linux上执行一份。

转载于:https://my.oschina.net/iyinghui/blog/1861444

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值