Elastic-Job是一個分布式調(diào)度解決方案,由兩個相互獨(dú)立的子項(xiàng)目Elastic-Job-Lite和Elastic-Job-Cloud組成锭弊。
Elastic-Job-Lite定位為輕量級無中心化解決方案,使用jar包的形式提供分布式任務(wù)的協(xié)調(diào)服務(wù)策严,外部僅依賴Zookeeper;Elastic-Job-Cloud采用自研Mesos Framework的解決方案,額外提供資源治理辽幌、應(yīng)用分發(fā)以及進(jìn)程隔離等功能。
筆者項(xiàng)目中采用的Lite版本街立,所以以下是梳理Elastic-Job-Lite的內(nèi)容:
一. 整體架構(gòu)圖
二. 功能列表
-
分布式調(diào)度協(xié)調(diào)
Elastic-Job-Lite并無作業(yè)調(diào)度中心節(jié)點(diǎn)舶衬,而是基于部署作業(yè)框架的程序在到達(dá)相應(yīng)時間點(diǎn)時各自觸發(fā)調(diào)度埠通。
注冊中心僅用于作業(yè)注冊和監(jiān)控信息存儲赎离。而主作業(yè)節(jié)點(diǎn)僅用于處理分片和清理等功能。
-
彈性擴(kuò)容縮容
運(yùn)行中的作業(yè)服務(wù)器崩潰端辱,或新增加n臺作業(yè)服務(wù)器梁剔,作業(yè)框架將在下次作業(yè)執(zhí)行前重新分片虽画,不影響當(dāng)前作業(yè)執(zhí)行。
-
失效轉(zhuǎn)移
Elastic-Job-Lite提供最安全的方式執(zhí)行作業(yè)荣病。將分片總數(shù)設(shè)置為1码撰,并使用多于1臺的服務(wù)器執(zhí)行作業(yè),作業(yè)將會以1主n從的方式執(zhí)行个盆。
一旦執(zhí)行作業(yè)的服務(wù)器崩潰脖岛,等待執(zhí)行的服務(wù)器將會在下次作業(yè)啟動時替補(bǔ)執(zhí)行。開啟失效轉(zhuǎn)移功能效果更好颊亮,可以保證在本次作業(yè)執(zhí)行時崩潰柴梆,備機(jī)立即啟動替補(bǔ)執(zhí)行。
-
錯過執(zhí)行作業(yè)重觸發(fā)
自動記錄錯過執(zhí)行的作業(yè)终惑,并在上次作業(yè)完成后自動觸發(fā)绍在。
-
作業(yè)分片一致性,保證同一分片在分布式環(huán)境中僅一個執(zhí)行實(shí)例
-
自診斷并修復(fù)分布式不穩(wěn)定造成的問題
-
支持并行調(diào)度
-
支持作業(yè)生命周期操作
-
豐富的作業(yè)類型
Elastic-Job提供Simple雹有、Dataflow和Script 3種作業(yè)類型偿渡。
-
Spring整合以及命名空間提供
支持spring容器,自定義命名空間霸奕,支持占位符溜宽。
-
運(yùn)維平臺
提供運(yùn)維界面,可以管理作業(yè)和注冊中心质帅。
三. 作業(yè)類型:
Elastic-Job提供Simple坑质、Dataflow和Script 3種作業(yè)類型。 方法參數(shù)shardingContext包含作業(yè)配置临梗、片和運(yùn)行時信息涡扼。可通過getShardingTotalCount(), getShardingItem()等方法分別獲取分片總數(shù)盟庞,運(yùn)行在本作業(yè)服務(wù)器的分片序列號等吃沪。
a. Simple類型作業(yè)
意為簡單實(shí)現(xiàn),未經(jīng)任何封裝的類型什猖。需實(shí)現(xiàn)SimpleJob接口票彪。該接口僅提供單一方法用于覆蓋,此方法將定時執(zhí)行不狮。與Quartz原生接口相似降铸,但提供了彈性擴(kuò)縮容和分片等功能。
b. Dataflow類型作業(yè)
Dataflow類型用于處理數(shù)據(jù)流摇零,需實(shí)現(xiàn)DataflowJob接口推掸。該接口提供2個方法可供覆蓋,分別用于抓取(fetchData)和處理(processData)數(shù)據(jù)。
c. Script類型作業(yè)
Script類型作業(yè)意為腳本類型作業(yè)谅畅,支持shell登渣,python,perl等所有類型腳本毡泻。只需通過控制臺或代碼配置scriptCommandLine即可胜茧,無需編碼。執(zhí)行腳本路徑可包含參數(shù)仇味,參數(shù)傳遞完畢后呻顽,作業(yè)框架會自動追加最后一個參數(shù)為作業(yè)運(yùn)行時信息。
四. 原理:
第一臺服務(wù)器上線觸發(fā)主服務(wù)器選舉丹墨。主服務(wù)器一旦下線芬位,則重新觸發(fā)選舉,選舉過程中阻塞带到,只有主服務(wù)器選舉完成昧碉,才會執(zhí)行其他任務(wù)。
某作業(yè)服務(wù)器上線時會自動將服務(wù)器信息注冊到注冊中心揽惹,下線時會自動更新服務(wù)器狀態(tài)被饿。
主節(jié)點(diǎn)選舉,服務(wù)器上下線搪搏,分片總數(shù)變更均更新重新分片標(biāo)記狭握。
定時任務(wù)觸發(fā)時,如需重新分片疯溺,則通過主服務(wù)器分片论颅,分片過程中阻塞,分片結(jié)束后才可執(zhí)行任務(wù)囱嫩。如分片過程中主服務(wù)器下線恃疯,則先選舉主服務(wù)器,再分片墨闲。
通過上一項(xiàng)說明可知今妄,為了維持作業(yè)運(yùn)行時的穩(wěn)定性,運(yùn)行過程中只會標(biāo)記分片狀態(tài)鸳碧,不會重新分片盾鳞。分片僅可能發(fā)生在下次任務(wù)觸發(fā)前。
每次分片都會按服務(wù)器IP排序瞻离,保證分片結(jié)果不會產(chǎn)生較大波動腾仅。
實(shí)現(xiàn)失效轉(zhuǎn)移功能,在某臺服務(wù)器執(zhí)行完畢后主動抓取未分配的分片套利,并且在某臺服務(wù)器下線后主動尋找可用的服務(wù)器執(zhí)行任務(wù)推励。
服務(wù)啟動流程:
作業(yè)執(zhí)行流程:
五. Elastic-Job有何使用限制
?作業(yè)啟動成功后修改作業(yè)名稱視為新作業(yè)鹤耍,原作業(yè)廢棄。
?同一臺作業(yè)服務(wù)器可以運(yùn)行多個相同的作業(yè)實(shí)例吹艇,但每個作業(yè)實(shí)例必須使用不同的JobInstanceId,因?yàn)樽鳂I(yè)運(yùn)行時是按照IP和JobInstanceId注冊和管理的昂拂。JobInstanceId可在作業(yè)配置中設(shè)置受神。
?一旦有服務(wù)器波動,或者修改分片項(xiàng)格侯,將會觸發(fā)重新分片鼻听;觸發(fā)重新分片將會導(dǎo)致運(yùn)行中的流式處理的作業(yè)在執(zhí)行完本次作業(yè)后不再繼續(xù)執(zhí)行,等待分片結(jié)束后再恢復(fù)正常联四。
?開啟monitorExecution才能實(shí)現(xiàn)分布式作業(yè)冪等性(即不會在多個作業(yè)服務(wù)器運(yùn)行同一個分片)的功能撑碴,但monitorExecution對短時間內(nèi)執(zhí)行的作業(yè)(如每5秒一觸發(fā))性能影響較大,建議關(guān)閉并自行實(shí)現(xiàn)冪等性朝墩。
六. Simple類型作業(yè)應(yīng)用示例
1.引入Maven依賴:
<!-- 引入elastic-job-lite核心模塊 -->
<dependency>
<groupId>io.elasticjob</groupId>
<artifactId>elastic-job-lite-core</artifactId>
<version>${latest.release.version}</version>
</dependency>
<!-- 使用springframework自定義命名空間時引入 -->
<dependency>
<groupId>io.elasticjob</groupId>
<artifactId>elastic-job-lite-spring</artifactId>
<version>${latest.release.version}</version>
</dependency>
2.作業(yè)開發(fā):
public class MyElasticJob implements SimpleJob {
@Override
public void execute(ShardingContext context) {
switch (context.getShardingItem()) {
case 0:
// do something by sharding item 0
break;
case 1:
// do something by sharding item 1
break;
case 2:
// do something by sharding item 2
break;
// case n: ...
}
}
}
3.作業(yè)配置:
<?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 ">
<!--配置作業(yè)注冊中心 -->
<reg:zookeeper id="regCenter" server-lists="yourhost:2181" namespace="dd-job" base-sleep-time-milliseconds="1000" max-sleep-time-milliseconds="3000" max-retries="3" />
<!-- 配置作業(yè)-->
<job:simple id="oneOffElasticJob" class="xxx.MyElasticJob" registry-center-ref="regCenter" cron="0/10 * * * * ?" sharding-total-count="3" sharding-item-parameters="0=A,1=B,2=C" />
</beans>
4.作業(yè)啟動:
Spring啟動方式: 將配置Spring命名空間的xml通過Spring啟動醉拓,作業(yè)將自動加載。
5.配置屬性詳細(xì)說明:
可查看官方配置文檔:http://elasticjob.io/docs/elastic-job-lite/02-guide/config-manual/
更多詳細(xì)內(nèi)容可以查看elasticjob開發(fā)指導(dǎo)文檔:http://elasticjob.io/docs/elastic-job-lite/02-guide