【急速入門】Elastic-Job分佈式定時任務框架

前言

急速入門,分佈式框架O(∩_∩)O哈哈~


Elastic-Job

分佈式調度解決方案,使用jar包提供協調服務
https://mvnrepository.com/search?q=elastic-job-lite-core

  • 需要注意的是,我們在使用Elastic-Job時需要整合ZooKeeper集羣。

本地使用Windows版本ZooKeeper,單機版

https://zookeeper.apache.org/
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

  • 單機啓動
    **加粗樣式**
  • 修改配置文件
    在這裏插入圖片描述
    在這裏插入圖片描述
  • 雙擊啓動
    在這裏插入圖片描述
  • (*❦ω❦)成功
    在這裏插入圖片描述

Elastic-Job 分片

一個任務拆分成多個獨立的任務項,每個服務獲得一個或幾個分片項。

  • 【案例:】
    如果遍歷數據庫某張表的作業,供兩臺服務器。
    每臺服務器執任務的50%,即服務器A執行ID尾號爲奇數的數據,服務器B執行ID尾號爲偶數的數據。
    在這裏插入圖片描述
高可用

分片總數設置爲1,多於1臺服務器執行作業,1主n從。
執行服務器崩潰後,等待的服務器將啓動,執行下次任務。
在這裏插入圖片描述

Demo演示

Simple作業詳解

意爲定時任務的簡單實現,只需實現execute方法。提供了彈性的擴容和分片功能。
1.搭建項目
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
2.引入maven依賴

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.zcw</groupId>
  <artifactId>zcw-java-simple-job</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>zcw-java-simple-job</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!--Elastic-job-lite-core-->
    <dependency>
      <groupId>com.dangdang</groupId>
      <artifactId>elastic-job-lite-core</artifactId>
      <version>2.1.5</version>
    </dependency>
  </dependencies>

 
</project>


3.實現SimpleJob接口,實現execute方法

package com.zcw.job;

import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;

/**
 * @ClassName : MySimpleJob
 * @Description :
 * @Author : Zhaocunwei
 * @Date: 2020-06-04 13:45
 */
public class MySimpleJob implements SimpleJob {
    @Override
    public void execute(ShardingContext shardingContext) {
        System.out.println("我是當前分片項"+shardingContext.getShardingItem()+
                ",總分片項:"+shardingContext.getShardingTotalCount());
    }
}



4.配置作業

  • 定義作業核心配置(作業名稱,定時策略,分片總數)
  • 定義作業類型(Simple,Dataflow,Scripe,實現類的全包名)
  • 定義Lite作業根配置(overwrite屬性的重要性)
    5.配置zookeeper的鏈接方式(單機版)
package com.zcw;

import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.JobTypeConfiguration;
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.lite.internal.schedule.JobScheduleController;
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 com.zcw.job.MySimpleJob;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) {
        System.out.println( "Hello World!" );
        new JobScheduler(zkCenter(),configuration()).init();
    }

    /**
     * 註冊中心
     * @return
     */
    public static CoordinatorRegistryCenter zkCenter(){
        ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration("localhost:2181",
                "zcw-simple-job");
        CoordinatorRegistryCenter coordinatorRegistryCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);
        //註冊中心初始化
        coordinatorRegistryCenter.init();
        return coordinatorRegistryCenter;
    }

    /**
     * Job配置
     * @return
     */
    public static LiteJobConfiguration configuration(){
        //job核心配置
        JobCoreConfiguration jobCoreConfiguration = JobCoreConfiguration
                .newBuilder("mySimpleJob","0/10 * * * * ?",2)
                .build();
        //job類型配置
        JobTypeConfiguration jobTypeConfiguration = new SimpleJobConfiguration(jobCoreConfiguration,
                MySimpleJob.class.getCanonicalName());
        //job根的配置(LiteJobConfiguration)
        LiteJobConfiguration liteJobConfiguration = LiteJobConfiguration
                .newBuilder(jobTypeConfiguration)
                //啓動時都要覆蓋掉,註冊中心的數據
                .overwrite(true)
                .build();
        return liteJobConfiguration;
    }
}


  • 運行
    在這裏插入圖片描述
    6.複製代碼, 修改端口,模擬兩臺服務器

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

dataflow流式任務

  • 分爲數據抓取(fetchData)和數據處理(processData)

  • 流程
    1.定時任務根據規則觸發
    2.抓取數據
    3.處理數據
    4.處理完數據後,再次抓取
    5.若數據存在,繼續處理,若不存在,則本次任務結束
    6.等待任務規則,下次觸發

在這裏插入圖片描述

  • 應用場景:
    不間歇的數據處理(比如:第三方訂單的抓取)
  • Demo練習
    【實現DataflowJob接口】
    注意:DataFlowJob泛型
    泛型規定了抓取數據的返回類型

1.創建實體類


package com.zcw.model;

/**
 * @ClassName : Order
 * @Description :
 * @Author : Zhaocunwei
 * @Date: 2020-06-04 17:37
 */
public class Order {
    private Integer orderId;
    //0 未處理;1,已處理
    private Integer status;

    public Integer getOrderId() {
        return orderId;
    }

    public void setOrderId(Integer orderId) {
        this.orderId = orderId;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "Order{" +
                "orderId=" + orderId +
                ", status=" + status +
                '}';
    }
}


2.編寫接口

package com.zcw.job;

import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.dataflow.DataflowJob;
import com.sun.org.apache.xpath.internal.operations.Or;
import com.zcw.model.Order;

import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName : MyDataflowJob
 * @Description :
 * @Author : Zhaocunwei
 * @Date: 2020-06-04 17:36
 */
public class MyDataflowJob implements DataflowJob<Order> {

    private List<Order> orders = new ArrayList<>();
    {
        for(int i=0;i<100;i++){
            Order order = new Order();
            order.setOrderId(i+1);
            order.setStatus(0);
            orders.add(order);
        }
    }
    @Override
    public List<Order> fetchData(ShardingContext shardingContext) {
        //訂單號 % 分片總數 == 當前分片項
       List<Order> orderList  = orders.stream().filter(o->o.getStatus()==0)
                .filter(o->o.getOrderId()%shardingContext
                        .getShardingTotalCount() ==shardingContext.getShardingItem())
               .collect(Collectors.toList());
        List<Order> subList=null;
        if(orderList!=null && orderList.size()>0){
           subList =  orderList.subList(0,10);
       }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LocalTime time = LocalTime.now();
        System.out.println(time+",我是分片項:"+shardingContext.getShardingItem()+"," +
                "我抓取的數據是:"+subList);
        return subList;
    }

    @Override
    public void processData(ShardingContext shardingContext, List<Order> list) {
        list.forEach(o->o.setStatus(1));
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LocalTime time = LocalTime.now();
        System.out.println(time+",我是分片項:"+shardingContext.getShardingItem()+
                ",我正在處理數據");
    }
}


  • 修改啓動類

package com.zcw;

import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.JobTypeConfiguration;
import com.dangdang.ddframe.job.config.dataflow.DataflowJobConfiguration;
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.lite.internal.schedule.JobScheduleController;
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 com.zcw.job.MyDataflowJob;
import com.zcw.job.MySimpleJob;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) {
        System.out.println( "Hello World!" );
//        new JobScheduler(zkCenter(),configuration()).init();
        new JobScheduler(zkCenter(),configurationDataflow()).init();
    }

    /**
     * 註冊中心
     * @return
     */
    public static CoordinatorRegistryCenter zkCenter(){
        ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration("localhost:2181",
                "zcw-simple-job");
        CoordinatorRegistryCenter coordinatorRegistryCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);
        //註冊中心初始化
        coordinatorRegistryCenter.init();
        return coordinatorRegistryCenter;
    }

    /**
     * Job配置
     * @return
     */
    public static LiteJobConfiguration configuration(){
        //job核心配置
        JobCoreConfiguration jobCoreConfiguration = JobCoreConfiguration
                .newBuilder("mySimpleJob","0/10 * * * * ?",2)
                .build();
        //job類型配置
        JobTypeConfiguration jobTypeConfiguration = new SimpleJobConfiguration(jobCoreConfiguration,
                MySimpleJob.class.getCanonicalName());
        //job根的配置(LiteJobConfiguration)
        LiteJobConfiguration liteJobConfiguration = LiteJobConfiguration
                .newBuilder(jobTypeConfiguration)
                //啓動時都要覆蓋掉,註冊中心的數據
                .overwrite(true)
                .build();
        return liteJobConfiguration;
    }

    /**
     * Job配置
     * @return
     */
    public static LiteJobConfiguration configurationDataflow(){
        //job核心配置
        JobCoreConfiguration jobCoreConfiguration = JobCoreConfiguration
                .newBuilder("myDataFlowJob","0/10 * * * * ?",2)
                .build();
        //job類型配置
        JobTypeConfiguration jobTypeConfiguration = new DataflowJobConfiguration(
                jobCoreConfiguration,
                MyDataflowJob.class.getCanonicalName(),true);
        //job根的配置(LiteJobConfiguration)
        LiteJobConfiguration liteJobConfiguration = LiteJobConfiguration
                .newBuilder(jobTypeConfiguration)
                //啓動時都要覆蓋掉,註冊中心的數據
                .overwrite(true)
                .build();
        return liteJobConfiguration;
    }
}

  • 測試:
    在這裏插入圖片描述
    在這裏插入圖片描述

編寫腳本Script

在這裏插入圖片描述

echo 我是cmd腳本,我的作業信息是:%1

在這裏插入圖片描述

  • 在我們APP類裏面定義方法
    在這裏插入圖片描述
    在這裏插入圖片描述
 public static LiteJobConfiguration configurationScript(){
        //job核心配置
        JobCoreConfiguration jobCoreConfiguration = JobCoreConfiguration
                .newBuilder("myScriptJob","0/10 * * * * ?",2)
                .build();
        //job類型配置
        JobTypeConfiguration jobTypeConfiguration = new ScriptJobConfiguration(
                jobCoreConfiguration,
               "F:/test/test.cmd");
        //job根的配置(LiteJobConfiguration)
        LiteJobConfiguration liteJobConfiguration = LiteJobConfiguration
                .newBuilder(jobTypeConfiguration)
                //啓動時都要覆蓋掉,註冊中心的數據
                .overwrite(true)
                .build();
        return liteJobConfiguration;
    }

  • 運行
    在這裏插入圖片描述
  • 修改文件
    在這裏插入圖片描述
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章