Elastic-Job分佈式調度

1、首先,咱們來看一個問題:

使用quartz或者spring-task實現任務調度在集羣環境下有什麼問題?

答:html

一、不敢輕易跟着應用服務多節點部署,可能會重複屢次執行而引起系統邏輯的錯誤web

二、quartz的集羣基於數據庫的狀態標記,涉及的表多達十多張,節點數量的增長並不能給咱們的每次執行效率帶來提高,即不能實現水平擴展。算法

2、一個好的任務調度解決方案應該能知足如下幾點:

一、一致性(保證定時任務單獨執行)spring

二、高可用性 (當前定時任務因外部緣由執行失敗後有替代方案)sql

三、定時任務分佈式處理(並行處理)數據庫

而這些問題已經有前輩都考慮到了,提供了不少的解決方案apache

TBSchedule:由淘寶開源的分佈式調度解決方案,目前好像沒有維護了,文檔較少api

Elastic-Job:由噹噹網開源的分佈式調度解決方案,文檔豐富友好,上手簡單瀏覽器

Elastic-Job官網地址:http://elasticjob.io/index_zh.html安全

3、Elastic-Job介紹

Elastic-Job是一個分佈式調度解決方案,由兩個相互獨立的子項目Elastic-Job-Lite和Elastic-Job-Cloud組成。

Elastic-Job-Lite定位爲輕量級無中心化解決方案,使用jar包的形式提供分佈式任務的協調服務。

Elastic-Job-Cloud使用Mesos + Docker(TBD)的解決方案,額外提供資源治理、應用分發以及進程隔離等服務,Elastic-Job-Lite和Elastic-Job-Cloud提供同一套API開發做業,開發者僅需一次開發,便可根據須要以Lite或Cloud的方式部署

4、Elastic-Job-Lite優點及特色:

  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。在不丟失分片項的狀況下,最大限度的利用現有資源提升吞吐量。

  4. 運維平臺:提供web控制檯用於管理做業

輸入圖片說明

5、簡單使用:

請先安裝3.4.6版本以上的zookeeper

一、maven添加jar依賴

<!-- elastic-job start -->
<dependency>
	<groupId>com.dangdang</groupId>
	<artifactId>elastic-job-lite-core</artifactId>
	<version>2.0.0</version>
</dependency>
<dependency>
	<groupId>com.dangdang</groupId>
	<artifactId>elastic-job-lite-spring</artifactId>
	<version>2.0.0</version>
</dependency>
<!-- elastic-job end -->

<!-- zookeeper -->
<dependency>
	<groupId>org.apache.zookeeper</groupId>
	<artifactId>zookeeper</artifactId>
	<version>3.4.9</version>
</dependency>

二、elastic-job與spring整合配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:reg="http://www.dangdang.com/schema/ddframe/reg"
       xmlns:job="http://www.dangdang.com/schema/ddframe/job"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.dangdang.com/schema/ddframe/reg
                        http://www.dangdang.com/schema/ddframe/reg/reg.xsd
                        http://www.dangdang.com/schema/ddframe/job
                        http://www.dangdang.com/schema/ddframe/job/job.xsd">
    <!--配置做業註冊中心 -->
    <reg:zookeeper id="regCenter" server-lists="172.18.7.133:2181" namespace="dd-job"
                   base-sleep-time-milliseconds="1000" max-sleep-time-milliseconds="3000" max-retries="3" />

    <!-- 配置做業-->
    <job:simple id="mySimpleJob" class="com.muheda.sipm.task.TestTask" registry-center-ref="regCenter"
                sharding-total-count="1" cron="0 0/5 * * * ?" overwrite="true" failover="true"/>
</beans>

server-lists:zookeeper地址

sharding-total-count爲分片數量,設置爲1的時候,做業只會被分配到第一臺機器進行處理;官網建議此值應爲物理機的倍數

①分片策略:

1)、基於平均分配算法的分片策略,也是默認的分片策略; 若是分片不能整除,則不能整除的多餘分片將依次追加到序號小的服務器

2)、根據做業名的哈希值奇偶數決定IP升降序算法的分片策略

3)、根據做業名的哈希值對服務器列表進行輪轉的分片策略

②分片後臺處理:

若是咱們的數據庫只有一個,而物理機設置有多臺集羣,怎麼使用分片查詢功能?這裏有一個處理辦法是,第三步中的定時任務業務類中能夠經過shardingContext.getShardingTotalCount()和shardingContext.getShardingItem()取到總的分片數量和當前分片編號,咱們在執行業務查詢的時候能夠在sql後面這樣處理:

shardingContext.getShardingItem() = Id%shardingContext.getShardingTotalCount()

三、定時任務業務類:

package com.muheda.sipm.task;

import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import org.apache.log4j.Logger;

/**
 * @Author: Sorin
 * @Descriptions:
 * @Date: Created in 2018/2/1
 */
public class TestTask implements SimpleJob {

    private static Logger logger = Logger.getLogger(SimpleJob.class);

    @Override
    public void execute(ShardingContext shardingContext) {
        logger.info(String.format("ShardingItem: %s | Thread: %s | %s",
                shardingContext.getShardingItem(), Thread.currentThread().getId(), "SIMPLE"));
        logger.info("定時任務測試");
    }
}

四、使用不依賴與Spring的方式:

LoadElasticJob在項目啓動後加載一次,裏面加載job

@Component
public class LoadElasticJob implements InitializingBean {

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

    static int initBoolean = 0;

    @Override
    public void afterPropertiesSet() throws Exception {
        if(initBoolean==0){
            init();
        }
        initBoolean++;
    }

    public void init(){
        logger.info("定時任務開始啓動!");
        CoordinatorRegistryCenter regCenter = ElasticJobUtils.setUpRegistryCenter();
        // 店鋪統計定時任務
        ElasticJobUtils.jobShopStat(regCenter);
        logger.info("定時任務啓動成功!");
    }
}

ElasticJobUtils中定義具體的job屬性,至關於以前的xml中的bean.業務類是同樣的,這裏就不貼出來了

public class ElasticJobUtils {

    private static final String ZOOKEEPER_URL = PropertiesUtil.getValue("ZOOKEEPER_URL");
    private static final String JOB_NAMESPACE = PropertiesUtil.getValue("JOB_NAMESPACE");

    public static CoordinatorRegistryCenter setUpRegistryCenter() {
        ZookeeperConfiguration zkConfig = new ZookeeperConfiguration(ZOOKEEPER_URL, JOB_NAMESPACE);
        CoordinatorRegistryCenter result = new ZookeeperRegistryCenter(zkConfig);
        result.init();
        return result;
    }

    /**
     * @Descripton: 店鋪統計定時任務
     * @Author: Sorin
     * @param regCenter
     * @param jobEventConfig
     * @Date: 2018/3/19
     */
    public static void jobShopStat(final CoordinatorRegistryCenter regCenter){
        JobCoreConfiguration coreConfig = JobCoreConfiguration.newBuilder(PropertiesUtil.getValue("job_shop_stat"), PropertiesUtil.getValue("core_shop_stat"), 1).build();
        SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(coreConfig, StatManageAction.class.getCanonicalName());
        new JobScheduler(regCenter, LiteJobConfiguration.newBuilder(simpleJobConfig).build()).init();
    }
}

6、運維平臺

解壓縮elastic-job-lite-console-${version}.tar.gz並執行bin\start.sh。 打開瀏覽器訪問 http://localhost:8899/ 便可訪問控制檯

參考https://www.cnblogs.com/2nao/p/8250663.html

相關文章
相關標籤/搜索