任務(wù)調(diào)度是指基于給定的時間點,給定的時間間隔或者給定執(zhí)行次數(shù)自動的執(zhí)行任務(wù)。任務(wù)調(diào)度是是操作系統(tǒng)的重要組成部分,而對于實時的操作系統(tǒng),任務(wù)調(diào)度直接影響著操作系統(tǒng)的實時性能。任務(wù)調(diào)度涉及到多線程并發(fā)、運行時間規(guī)則定制及解析、線程池的維護等諸多方面的工作。
WEB服務(wù)器在接受請求時,會創(chuàng)建一個新的線程服務(wù)。但是資源有限,必須對資源進行控制,首先就是限制服務(wù)線程的最大數(shù)目,其次考慮以線程池共享服務(wù)的線程資源,降低頻繁創(chuàng)建、銷毀線程的消耗;然后任務(wù)調(diào)度信息的存儲包括運行次數(shù)、調(diào)度規(guī)則以及運行數(shù)據(jù)等。一個合適的任務(wù)調(diào)度框架對于項目的整體性能來說顯得尤為重要。
我們在實際的開發(fā)工作中,或多或少的都會用到任務(wù)調(diào)度這個功能。常見的分布式任務(wù)調(diào)度框架有:cronsun、Elastic-job、saturn、lts、TBSchedule、xxl-job等。
2.1cronsun
crontab是Linux系統(tǒng)里面最簡單易用的定時任務(wù)管理工具,在Linux上由crond來周期性的執(zhí)行指令列表,執(zhí)行的任務(wù)稱為cron job,多個任務(wù)就稱為crontab。crontab任務(wù)調(diào)度指令的基本格式為:
* * * * * command
分 時 日 月 周 命令
但是時間久了之后會發(fā)現(xiàn),crontab會存在一些問題:
大量的crontab分散在各臺服務(wù)器,帶來了很高的維護成本;
任務(wù)沒有按時執(zhí)行,過了很長的時間才能發(fā)現(xiàn),需要重試或者排查;
crontab分散在很多集群上,需要一臺一臺的去查看日志;
crontab存在單點問題,對于不能重復(fù)執(zhí)行的定時任務(wù)很傷腦;
……
因此非常需要一個集中管理定時任務(wù)的系統(tǒng),于是就有了cronsun。cronsun是一個分布式任務(wù)系統(tǒng),單個節(jié)點和Linux機器上的contab近似,是為了解決多臺Linux機器上crontab任務(wù)管理不方便的問題,同時提供了任務(wù)高可用的支持(當某個節(jié)點死機的時候可以自動調(diào)整到正常的節(jié)點執(zhí)行)。與此同時,它還支持界面管理機器上的任務(wù),支持任務(wù)失敗郵件提醒,安裝簡單,使用簡便,是替換crontab的一個不錯的選擇。
cronsun中主要有三個組件,都是通過etcd通訊的。cronnode負責(zé)節(jié)點的分組及節(jié)點的狀態(tài),cronweb是用來管理任務(wù)的、任務(wù)的執(zhí)行結(jié)果都可以在上面看。
cronsun的系統(tǒng)架構(gòu)如下圖所示,簡單的來說就是,所有的任務(wù)都會存儲在一個分布式etcd里,單個crond部署成一個服務(wù),也就是圖中所示的node.1、node.2、node.n等,然后再由web界面去管理。如果任務(wù)執(zhí)行失敗的話,會發(fā)送失敗的郵件,當單個節(jié)點死機的時候,也會自動調(diào)整到正常的節(jié)點去執(zhí)行任務(wù)。
cronsun是在管理后臺添加任務(wù)的,所以一旦管理后臺泄漏出去了,則存在一定的危險性,所以cronsun支持security.json的安全設(shè)置:
如以上設(shè)置開啟安全限制,則添加和執(zhí)行任務(wù)的時候只允許選擇配置里面指定的用戶來執(zhí)行腳本,并且腳本的擴展名要在配置的腳本的擴展名限制的列表里面。
2.2、Elastic-job
Elastic-job是當當開源的一款非常好用的作業(yè)框架,Elastic-job在2.x之后,出現(xiàn)了兩個相互獨立的產(chǎn)品線:Elastic-job-lite和Elastic-job-cloud。
2.2.1、Elastic-job-lite
Elastic-job-lite定位為輕量級無中心化的解決方案,使用jar包的形式提供分布式任務(wù)的協(xié)調(diào)服務(wù),外部依賴僅依賴于zookeeper。
Elastic-job-lite的架構(gòu)圖如下圖所示:
從上面的框架圖中可以看出,Elastic-job-lite框架使用zookeeper作為注冊中心,Elastic-job-lite框架通過監(jiān)聽感知zookeeper數(shù)據(jù)的變化,并做相應(yīng)的處理;運維平臺也僅是通過讀取zk數(shù)據(jù)來展現(xiàn)作業(yè)狀態(tài),或是更新zk數(shù)據(jù)修改全局配置。運維平臺和Elastic-job-lite沒有直接的關(guān)系,完全解耦合。Elastic-job-lite并不直接提供數(shù)據(jù)處理的功能,框架只會將分片項分配給各個正在運行中的服務(wù)器,分片項與真是數(shù)據(jù)的對應(yīng)關(guān)系需要開發(fā)者在應(yīng)用程序中自行處理。
Elastic-job-lite并無作業(yè)調(diào)度中心節(jié)點,而是基于部署作業(yè)框架的程序在到達相應(yīng)時間點時各自觸發(fā)調(diào)度。注冊中心僅用于作業(yè)注冊和監(jiān)控信息存儲,而主作業(yè)節(jié)點僅用于處理分片和清理的功能。
(1)注冊中心的數(shù)據(jù)結(jié)構(gòu)
我們先來了解一下該框架在zookeeper上的節(jié)點情況。首先注冊中心在命名的空間下創(chuàng)建作業(yè)名稱節(jié)點(作業(yè)名稱用來區(qū)分不同的作業(yè),一旦修改名稱,則認為是新的作業(yè)),作業(yè)名稱節(jié)點下又包含5個子節(jié)點:
config:保存作業(yè)的配置信息,以JSON格式存儲
sharding:保存作業(yè)的分片信息,它的子節(jié)點是分片項序號,從零開始,至分片總數(shù)減一
leader:該節(jié)點保存作業(yè)服務(wù)器主節(jié)點的信息,分為election、sharding和failover三個子節(jié)點,分別用于主節(jié)點的選舉、分片和失效轉(zhuǎn)移
instances:該節(jié)點保存的是作業(yè)運行實例的信息,子節(jié)點是當前作業(yè)運行實例的主鍵
servers:該節(jié)點保存作業(yè)服務(wù)器的信息,子節(jié)點是作業(yè)服務(wù)器的IP地址
(2)實現(xiàn)原理
第一臺服務(wù)器上線觸發(fā)主服務(wù)器選舉,主服務(wù)器一旦下線,則重新觸發(fā)選舉,選舉過程中阻塞,只有當主服務(wù)器選舉完成,才會去執(zhí)行其他的任務(wù);
某服務(wù)器上線時會自動將服務(wù)器的信息注冊到注冊中心,下線時會自動更新服務(wù)器的狀態(tài);
主節(jié)點選舉,服務(wù)器上下線,分片總數(shù)變更均更新重新分片標記;
定時任務(wù)觸發(fā)時,如需重新分片,則通過主服務(wù)器分片,分片過程中阻塞,分片結(jié)束后才可以執(zhí)行任務(wù)。如分片過程中主服務(wù)器下線,則先選舉主服務(wù)器在分片;
由上一項說明可知,為了維持作業(yè)運行時的穩(wěn)定性,運行過程中只會標記分片的狀態(tài),不會重新分片,分片僅可能發(fā)生在下次任務(wù)觸發(fā)前;
每次分片都會按照ip排序,保證分片結(jié)果不會產(chǎn)生較大的波動;
實現(xiàn)失效轉(zhuǎn)移功能,在某臺服務(wù)器執(zhí)行完畢后主動抓取未分配的分片,并且在某臺服務(wù)器下線后主動尋找可用的服務(wù)器執(zhí)行任務(wù)。
elastic底層的任務(wù)調(diào)度還是使用的quartz,通過zookeeper來動態(tài)給job節(jié)點分片。如果很大體量的用戶需要我們在特定的時間段內(nèi)計算完成,那么我們肯定是希望我們的任務(wù)可以通過集群達到水平的擴展,集群里的每個節(jié)點都處理部分的用戶,不管用戶的數(shù)量有多大,我們只需要增加機器就可以了。舉個例子:比如我們希望3臺機器跑job,我么將我們的任務(wù)分成3片,框架通過zk的協(xié)調(diào),最終會讓3臺機器分配到0,1,2的任務(wù)片,比如server0->0、server1->1、server2->2,當server0執(zhí)行時,可以只查詢id%3==0的用戶,server1可以只查詢id%3==1的用戶,server2可以只查詢id%3==2的用戶。
在以上的基礎(chǔ)上再增加一個server3,此時,server3分不到任何的分片,沒有分到任務(wù)分片的程序?qū)⒉粓?zhí)行。如果此時server2掛了,那么server2被分到的任務(wù)分片將會分配給server3,所以server3就會代替server2執(zhí)行。如果此時server3也掛了,那么框架也會自動的將server3的任務(wù)分片隨機分配到server0或者server1,那么就可能成:server0->0、server1->1,2。
這種特性稱之為彈性擴容。
2.2.2、Elastic-job-cloud
Elastic-job-cloud包含了Elastic-job-lite的全部功能,它是以私有云平臺的方式提供集資源、調(diào)度以及分片為一體的全量級解決方案,依賴于Mesos和Zookeeper,它額外提供了資源治理、應(yīng)用分發(fā)以及進程隔離等服務(wù)。他們兩個提供同一套API開發(fā)作業(yè),開發(fā)者僅需一次開發(fā),然后可根據(jù)需要以lite或cloud的方式部署。
2.3、saturn
Saturn(定時任務(wù)調(diào)度系統(tǒng))是唯品會自主研發(fā)的分布式的定時任務(wù)的調(diào)度平臺,它是基于Elastic-job版本1開發(fā)的。目標是取代傳統(tǒng)的Linux Cron/Spring Batch Job/Quartz的方式,做到全域統(tǒng)一配置、統(tǒng)一監(jiān)控、任務(wù)高可用以及分片。Saturn的任務(wù)可以使用多種語言開發(fā),比如python、Go、Shell、Java、Php等。
Saturn包括兩大部分,Saturn Console和Saturn Executor。Console是一個WEB UI,用來對作業(yè)/Executor的管理,統(tǒng)計報表展現(xiàn)等。他同時也是整個調(diào)度系統(tǒng)的大腦:將作業(yè)任務(wù)分配到各Executor。Executor是執(zhí)行任務(wù)的worker:按照作業(yè)配置的要求去執(zhí)行部署于Executor所在容器或物理機當中的作業(yè)腳本和代碼。Saturn高度依賴于zookeeper,每個executor及調(diào)度服務(wù)都會在zookeeper上進行注冊,確保調(diào)度程序能夠及時得到executor的狀態(tài)。
Saturn定時任務(wù)調(diào)度的最小單位是分片,即任務(wù)的一個執(zhí)行單元。Saturn的基本任務(wù)就是將任務(wù)分成多個分片,并將每個分片通過算法調(diào)度到對應(yīng)的executor上去執(zhí)行。
2.3.1、Staurn基本原理
Saturn的基本原理是將作業(yè)在邏輯上劃分為若干個分片,通過作業(yè)分片調(diào)度器將作業(yè)分片指派給特定的執(zhí)行節(jié)點。執(zhí)行節(jié)點通過quartz觸發(fā)執(zhí)行作業(yè)的具體實現(xiàn),在執(zhí)行的時候,會將分片序號和參數(shù)作為參數(shù)傳入。作業(yè)的實現(xiàn)邏輯需分析分片序號和分片參數(shù),并以此為依據(jù)來調(diào)用具體的實現(xiàn)(比如一個批量處理數(shù)據(jù)庫的作業(yè),可以劃分0號分片處理1-10號數(shù)據(jù)庫,1號分片可以處理11-20號數(shù)據(jù)庫)。
2.3.2、Saturn作業(yè)調(diào)度算法
(1)方案的設(shè)計
原理是給每個作業(yè)分片一個負載值和優(yōu)先執(zhí)行節(jié)點(prefer list),當需要重新分片時,參考作業(yè)優(yōu)先設(shè)定和執(zhí)行節(jié)點的負載值來進行域內(nèi)節(jié)點之間的資源分配,從而達到資源平衡。
(2)前置條件
A:每個分片都引入一個負載值(load),由用戶通過Saturn UI界面輸入
B:為每一個作業(yè)引入新的屬性prefer list(優(yōu)先列表,或者叫欲分配列表),由管理員通過ui界面編輯
C:作業(yè)引入啟用狀態(tài)(enabled/disabled),用戶通過UI界面改變這個狀態(tài);啟用狀態(tài)的作業(yè)會被節(jié)點執(zhí)行,且不可編輯、刪除,不可對prefer list進行調(diào)整,禁用狀態(tài)的作業(yè)不會被執(zhí)行
(3)實施步驟
第一步,摘?。坏诙?,放回(將這些作業(yè)分片按照負載值從大到小順序逐個分配給負載最小的執(zhí)行節(jié)點)。
(3.1)executor上線
摘?。?/p>
第一步,找出新上線節(jié)點的全部可執(zhí)行作業(yè)列表;對于每個作業(yè),判斷prefer list中是否包含了新上線的節(jié)點;如果是,則摘取其中全部的分片;這些已經(jīng)處理過的作業(yè)稱為預(yù)處理作業(yè);
第二步,從新上線節(jié)點的作業(yè)列表中減去預(yù)分配作業(yè),然后使用以下的方法依次摘?。?/p>
假如上線的executor為a,它能處理的作業(yè)類型為j1,j2(已減去預(yù)分配列表)。遍歷當前域下的executor列表,拿掉全部作業(yè)類型為j1,j2的分片,加上尚未分配的j1,j2作業(yè)分片列表,作為算法的待分配列表
在處理每個節(jié)點時,每拿掉一個作業(yè)分片后判斷被拿掉的負載(load)是否已經(jīng)超過了自身處理前總負載(load)的1/n(n為當前executor節(jié)點的總數(shù)量),如果超過,則本執(zhí)行節(jié)點摘取完成,繼續(xù)處理下一個執(zhí)行節(jié)點;如果不超過則繼續(xù)摘取,直到超過(大于等于)為止。
放回:
a.構(gòu)造需要添加的作業(yè)分片列表,我們起名為待分配列表,長度為n,待分配列表按照負載(load)從大到小排序,排序時需保證相同作業(yè)的所有分片時連續(xù)的
b.構(gòu)造每種作業(yè)類型的executor列表(如果有prefer list,且有存活,則該作業(yè)的executor列表就是prefer list),得到一個map<jobName,executorList>’
c.從待分配列表中依次取出第0到第n-1個作業(yè)分片jobi
d.從map中取出可運行jobi的executor列表listi
e.將jobi分配給listi中負載總和最小的executor
舉例如下:
(3.2)executor下線
摘?。喝〕鱿戮€的executor當前分配到的全部作業(yè)分片,作為算法的待分配列表
放回:使用平衡算法逐個處理待分配列表中的作業(yè)分片
(3.3)作業(yè)啟動
摘?。簭乃衑xecutor中摘取將被啟動作業(yè)的全部分片作為算法的待分配列表
放回:使用調(diào)整后的平衡算法放回
(3.4)作業(yè)停止
摘?。簩⒈煌V沟淖鳂I(yè)分片從各節(jié)點刪除
返回:無
注:Saturn架構(gòu)文檔請見https://github.com/vipshop/Saturn/wiki/Saturn架構(gòu)文檔
2.4、lts
LTS是一個輕量級分布式任務(wù)調(diào)度框架,主要用于解決分布式任務(wù)的調(diào)度問題,支持實時任務(wù)、定時任務(wù)和Cron任務(wù),有較好的伸縮性、擴展性以及健壯穩(wěn)定性。他參考hadoop的思想,主要有以下四個節(jié)點:
JobClient:主要負責(zé)提交任務(wù),并接收任務(wù)執(zhí)行的反饋結(jié)果
JobTracker:負責(zé)接收并分配任務(wù),任務(wù)調(diào)度
TaskTracker:負責(zé)執(zhí)行任務(wù),執(zhí)行完反饋給JobTracker
LTS-Admin:(管理后臺)主要負責(zé)節(jié)點管理,任務(wù)隊列管理,監(jiān)控管理等
其中JobClient、JobTracker、TaskTracker是無狀態(tài)的,可以部署多個并動態(tài)的進行刪減,來實現(xiàn)負載均衡,實現(xiàn)更大的負載量,并且框架采用FailStore策略使得LTS具有很好的容錯能力。
一個典型的定時任務(wù),大概的執(zhí)行流程如下:
添加任務(wù)以后在注冊中心進行注冊,zk集群會暴露各個節(jié)點的信息,進行master節(jié)點選舉等
JobClient將任務(wù)進行提交,如果成功的話將進行下一步;否則的話進入FailStore,重試
JobTracker接收并分配任務(wù),如果任務(wù)已經(jīng)存在,則結(jié)束;否則任務(wù)進入可執(zhí)行隊列ExecutableJobQueue,接著進入執(zhí)行中任務(wù)隊列ExecutingJobQueue,最后發(fā)送給TaskTracker進行執(zhí)行
TaskTracker執(zhí)行完畢后,將結(jié)果反饋給客戶端;如果反饋成功,則回到JobClient執(zhí)行下一個任務(wù);否則的話進入FeedbackJobQueue重試
2.5、quartz
Quartz是OpenSymphony開源組織在任務(wù)調(diào)度領(lǐng)域的一個開源項目,完全基于java實現(xiàn)。作為一個優(yōu)秀的開源框架,Quartz具有以下特點:強大的調(diào)度功能、靈活的應(yīng)用方式、分布式和集群能力,另外作為spring默認的調(diào)度框架,很容易實現(xiàn)與Spring集成,實現(xiàn)靈活可配置的調(diào)度功能。
Quartz的核心元素如下:
Scheduler:任務(wù)調(diào)度器,是實際執(zhí)行任務(wù)調(diào)度的控制器
Trigger;觸發(fā)器,用于定義任務(wù)調(diào)度的時間規(guī)則
Calendar:它是一些日歷特定時間的集合,一個Trigger可以包含多個Calendar,以便于排除或包含某些時間點
JobDetail:用來描述Job實現(xiàn)類及其他相關(guān)的靜態(tài)信息,如Job的名字、關(guān)聯(lián)監(jiān)聽器等信息
Job:是一個接口,只有一個方法void execute(JobExecutionContext context),開發(fā)者實現(xiàn)該接口定義運行任務(wù),JobExecutionContext類提供了調(diào)度上下文的各種信息
Quartz的單機版大家應(yīng)該都比較熟悉,它的集群方案是使用數(shù)據(jù)庫來實現(xiàn)的。集群架構(gòu)如下:
上圖3個節(jié)點在數(shù)據(jù)庫中都有同一份Job定義,如果某一個節(jié)點失效,那么Job會在其他節(jié)點上執(zhí)行。因為每個節(jié)點上的代碼都是一樣的,那么如何保證只有一臺機器上觸發(fā)呢?答案是使用了數(shù)據(jù)庫鎖。在quartz集群解決方案了有張scheduler_locks,采用了悲觀鎖的方式對triggers表進行了行加鎖,以保證任務(wù)同步的正確性。
簡單來說,quartz的分布式調(diào)度策略是以數(shù)據(jù)庫為邊界的一種異步策略。各個調(diào)度器都遵守一個基于數(shù)據(jù)庫鎖的操作規(guī)則從而保證了操作的唯一性,同時多個節(jié)點的異步運行保證了服務(wù)的可靠。但這種策略有自己的局限性:集群特性對于高CPU使用率的任務(wù)效果特別好,但是對于大量的短任務(wù),各個節(jié)點都會搶占數(shù)據(jù)庫鎖,這樣就出現(xiàn)大量的線程等待資源。Quartz的分布式只解決了任務(wù)高可用的問題,并沒有解決任務(wù)分片的問題,還是會有單機處理的極限。
2.6、TBSchedule
TBSchedule是一款非常優(yōu)秀的分布式調(diào)度框架,廣泛應(yīng)用于阿里巴巴、淘寶、支付寶、京東、汽車之家等很多互聯(lián)網(wǎng)企業(yè)的流程調(diào)度系統(tǒng)。TBSchedule在時間調(diào)度方面雖然沒有quartz強大,但是它支持分片的功能。和quartz不同的是,TBSchedule使用zk來實現(xiàn)任務(wù)調(diào)度的高可用和分片。純java開發(fā)。
TBSchedule項目實際上可以分為兩部分。1)schedule管理控制臺。負責(zé)控制、監(jiān)控任務(wù)執(zhí)行狀態(tài)。2)實際執(zhí)行job的客戶端程序。在實際使用時,需要先啟動zk,然后部署TBSchedule web界面的管理控制臺,最后啟動實際執(zhí)行job的客戶端程序。這里的zk并不實際控制任務(wù)調(diào)度,它只是負責(zé)與N臺執(zhí)行job任務(wù)的客戶端進行通訊,協(xié)調(diào)、管理、監(jiān)控這些機器的運行信息。實際分配任務(wù)的是管理控制臺,控制臺從zk獲取job的運行信息。TBSchedule通過控制ZNode的創(chuàng)建、修改、刪除來間接控制job的執(zhí)行,執(zhí)行任務(wù)的客戶端監(jiān)聽它們對應(yīng)ZNode的狀態(tài)更新事件,從而達到TBSchedule控制job執(zhí)行的目的。特點:
TBSchedule的分布式機制是通過靈活的Sharding方式實現(xiàn)的,比如可以按所有數(shù)據(jù)的ID按10取模分片、按月份分片等,根據(jù)不同的場景由客戶端配置分片規(guī)則。
TBSchedule的宿主服務(wù)器可以進行動態(tài)的擴容和資源回收,這個特點主要是因為它后端依賴的zooKeeper,這里的zooKeeper對于TBSchedule來說相當于NoSQL,用于存儲策略、任務(wù)、心跳等信息數(shù)據(jù),他的數(shù)據(jù)結(jié)構(gòu)類似于文件系統(tǒng)的目錄結(jié)構(gòu),他的節(jié)點有臨時節(jié)點、持久節(jié)點之分。一個新的服務(wù)器上線后,會在zk中創(chuàng)建一個代表當前服務(wù)器的一個唯一性路徑(臨時節(jié)點),并且新上線的服務(wù)器會和zk保持長連接,當通信斷開后,節(jié)點會自動刪除。
TBSchedule會定時掃描當前服務(wù)器的數(shù)量,重新進行任務(wù)分配。
TBSchedule不僅提供了服務(wù)端的高性能調(diào)度服務(wù),還提供了一個scheduleConsole war隨著宿主應(yīng)用的部署直接部署到服務(wù)器,可以通過web的方式對調(diào)度的任務(wù)、策略進行監(jiān)控管理,以及實時更新調(diào)整。
2.7、xxl-job
xxl-job是一個輕量級的分布式任務(wù)調(diào)度框架,其核心設(shè)計目標是開發(fā)迅速、學(xué)習(xí)簡單、輕量級、易擴展。
xxl-job的設(shè)計思想為:
(1)將調(diào)度行為抽象形成“調(diào)度中心”公共平臺,而平臺自身并不承擔業(yè)務(wù)邏輯,“調(diào)度中心”負責(zé)發(fā)起調(diào)度請求
(2)將任務(wù)抽象成分散的JobHandler,交由執(zhí)行器統(tǒng)一管理,執(zhí)行器負責(zé)接收調(diào)度請求并執(zhí)行對應(yīng)的JobHandler中業(yè)務(wù)邏輯
因此,“調(diào)度”和“任務(wù)”可以互相解偶,提高系統(tǒng)整體的穩(wěn)定性和擴展性。
xxl-job系統(tǒng)的組成分為:
(1)調(diào)度模塊(調(diào)度中心):負責(zé)管理調(diào)度信息,按照調(diào)度配置發(fā)出調(diào)度請求,自身不承擔業(yè)務(wù)代碼。調(diào)度系統(tǒng)與任務(wù)解耦,提高了系統(tǒng)可用性和穩(wěn)定性,同時調(diào)度系統(tǒng)性能不再受限于任務(wù)模塊;支持可視化、簡單且動態(tài)的管理調(diào)度信息,包括任務(wù)新建,更新,刪除,GLUE開發(fā)和任務(wù)報警等,所有上述操作都會實時生效,同時支持監(jiān)控調(diào)度結(jié)果以及執(zhí)行日志,支持執(zhí)行器Failover。
(2)執(zhí)行模塊(執(zhí)行器):負責(zé)接收調(diào)度請求并執(zhí)行任務(wù)邏輯。任務(wù)模塊專注于任務(wù)的執(zhí)行等操作,開發(fā)和維護更加簡單和高效;接收“調(diào)度中心”的執(zhí)行請求、終止請求和日志請求等。
Xxl-job的執(zhí)行流程:
首先準備一個將要執(zhí)行的任務(wù),任務(wù)開啟后到執(zhí)行器中注冊任務(wù)的信息,加載執(zhí)行器的配置文件,初始化執(zhí)行器的信息,然后執(zhí)行器start。在admin端配置任務(wù)信息,配置執(zhí)行器的信息。就可以控制任務(wù)的狀態(tài)了。
xxl-job的特性為:
簡單:支持通過web頁面對任務(wù)進行CRUD操作,操作簡單
動態(tài):支持動態(tài)修改任務(wù)狀態(tài)、暫停/恢復(fù)任務(wù),以及終止運行中的任務(wù),即時生效
調(diào)度中心HA(中心式):調(diào)度采用中心式設(shè)計,“調(diào)度中心”基于集群Quartz實現(xiàn)并支持集群部署,可保證調(diào)度中心HA
執(zhí)行器HA:任務(wù)分布式執(zhí)行,任務(wù)執(zhí)行器支持集群部署,可保證任務(wù)執(zhí)行HA
注冊中心:執(zhí)行器會周期性自動注冊任務(wù)并觸發(fā)執(zhí)行。同時,也支持手動錄入執(zhí)行器地址
彈性擴容縮容:一旦有新的執(zhí)行器機器上線或下線,下次調(diào)度時會重新分配任務(wù)
路由策略:執(zhí)行器集群部署時提供豐富的路由策略,包括:第一個、最后一個、輪詢、隨機、最不經(jīng)常使用、故障轉(zhuǎn)移等
故障轉(zhuǎn)移:任務(wù)路由策略選擇'故障轉(zhuǎn)移'情況下,如果執(zhí)行器集群中某一臺機器故障,將會自動Failover切換到一臺正常的執(zhí)行器發(fā)送調(diào)度請求。
阻塞處理策略:調(diào)度過于密集執(zhí)行器來不及處理時的處理策略,策略包括:單機串行、丟棄后續(xù)調(diào)度、覆蓋之前調(diào)度
任務(wù)超時控制:支持自定義任務(wù)超時時間,任務(wù)運行超時將會主動中斷任務(wù);
任務(wù)失敗重試:支持自定義任務(wù)失敗重試次數(shù),當任務(wù)失敗時將會按照預(yù)設(shè)的失敗重試次數(shù)主動進行重試;
失敗處理策略;調(diào)度失敗時的處理策略,默認提供失敗告警、失敗重試等策略;
分片廣播任務(wù):執(zhí)行器集群部署時,任務(wù)路由策略選擇'分片廣播'情況下,一次任務(wù)調(diào)度將會廣播觸發(fā)集群中所有執(zhí)行器執(zhí)行一次任務(wù),可根據(jù)分片參數(shù)開發(fā)分片任務(wù);
動態(tài)分片:分片廣播任務(wù)以執(zhí)行器為維度進行分片,支持動態(tài)擴容執(zhí)行器集群從而動態(tài)增加分片數(shù)量,協(xié)同進行業(yè)務(wù)處理;在進行大數(shù)據(jù)量業(yè)務(wù)操作時可顯著提升任務(wù)處理能力和速度。
事件觸發(fā):除了'Cron方式'和'任務(wù)依賴方式'觸發(fā)任務(wù)執(zhí)行之外,支持基于事件的觸發(fā)任務(wù)方式。調(diào)度中心提供觸發(fā)任務(wù)單次執(zhí)行的API服務(wù),可根據(jù)業(yè)務(wù)事件靈活觸發(fā)。
任務(wù)進度監(jiān)控:支持實時監(jiān)控任務(wù)進度;
Rolling實時日志:支持在線查看調(diào)度結(jié)果,并且支持以Rolling方式實時查看執(zhí)行器輸出的完整的執(zhí)行日志;
GLUE:提供Web IDE,支持在線開發(fā)任務(wù)邏輯代碼,動態(tài)發(fā)布,實時編譯生效,省略部署上線的過程。支持30個版本的歷史版本回溯。
腳本任務(wù):支持以GLUE模式開發(fā)和運行腳本任務(wù),包括Shell、Python、NodeJS等類型腳本;
任務(wù)依賴:支持配置子任務(wù)依賴,當父任務(wù)執(zhí)行結(jié)束且執(zhí)行成功后將會主動觸發(fā)一次子任務(wù)的執(zhí)行, 多個子任務(wù)用逗號分隔;
一致性:“調(diào)度中心”通過DB鎖保證集群分布式調(diào)度的一致性, 一次任務(wù)調(diào)度只會觸發(fā)一次執(zhí)行;
自定義任務(wù)參數(shù):支持在線配置調(diào)度任務(wù)入?yún)ⅲ磿r生效;
調(diào)度線程池:調(diào)度系統(tǒng)多線程觸發(fā)調(diào)度運行,確保調(diào)度精確執(zhí)行,不被堵塞;
數(shù)據(jù)加密:調(diào)度中心和執(zhí)行器之間的通訊進行數(shù)據(jù)加密,提升調(diào)度信息安全性;
郵件報警:任務(wù)失敗時支持郵件報警,支持配置多郵件地址群發(fā)報警郵件;
推送maven中央倉庫: 將會把最新穩(wěn)定版推送到maven中央倉庫, 方便用戶接入和使用;
運行報表:支持實時查看運行數(shù)據(jù),如任務(wù)數(shù)量、調(diào)度次數(shù)、執(zhí)行器數(shù)量等;以及調(diào)度報表,如調(diào)度日期分布圖,調(diào)度成功分布圖等;
全異步:系統(tǒng)底層實現(xiàn)全部異步化,針對密集調(diào)度進行流量削峰,理論上支持任意時長任務(wù)的運行;
國際化:調(diào)度中心支持國際化設(shè)置,提供中文、英文兩種可選語言,默認為中文;
xxl-job-lite的執(zhí)行器實際是一個ConcurrentHashMap容器。
1、Quartz:Java事實上的定時任務(wù)標準,但是關(guān)注點在于定時任務(wù)而非數(shù)據(jù),雖然實現(xiàn)了高可用,但是缺少分布式并行調(diào)度的功能,性能低。
2、TBSchedule:阿里早期開源的分布式任務(wù)調(diào)度系統(tǒng)。代碼略陳舊,使用的是Timer而不是線程池執(zhí)行任務(wù)調(diào)度。TBSchedule的作業(yè)類型比較單一,只能是獲取/處理數(shù)據(jù)一種模式,文檔缺失比較嚴重。
3、詳見分布式調(diào)度框架對比表格~
4.1、Elastic-job
1、環(huán)境準備:
jdk1.7+、zookeeper3.4.6+、maven3.0.4+
2、安裝zookeeper3.4.12并啟動
這里zookeeper占用了2181端口。
3、創(chuàng)建簡單任務(wù)
添加依賴:
寫一個簡單的任務(wù):
在項目入口處添加作業(yè)的配置和zk的配置:
運行,得到結(jié)果:
4、下載Elastic-job-lite源碼,使用maven進行打包。在elastic-job-lite/elastic-job-lite-console/target/elastic-job-lite-console-3.0.0.M1-SNAPSHOT/中,然后解壓,會有start.bat和start.sh兩個腳本,啟動。
瀏覽器中輸入localhost:8899,就可以管理任務(wù)了。
4.2、xxl-job-lite
1、調(diào)度數(shù)據(jù)庫初始化,tables_xxl-job.sql
2、下載源碼:包括調(diào)度中心+公共依賴+執(zhí)行器示例
3、配置部署“調(diào)度中心”:修改數(shù)據(jù)庫配置——將項目進行打包——將xxl-job-admin包部署到tomcat上
4、輸入localhost:8080/xxl-job-admin即可訪問調(diào)度中心
5、配置部署執(zhí)行器:xxl-job-executor-sample-springboot打成jar包直接運行,其他的打成war包部署在tomcat上。
6、寫一個任務(wù),運行,去執(zhí)行器上進行注冊,然后調(diào)度中心配置執(zhí)行器信息,添加任務(wù)
附錄
1、etcd
etcd是一個開源的、分布式的鍵值對數(shù)據(jù)存儲系統(tǒng),提供共享配置、服務(wù)的注冊和發(fā)現(xiàn)。etcd內(nèi)部采用raft協(xié)議作為一致性算法,是基于Go語言實現(xiàn)的。
2、zookeeper
zookeeper是一個開源的分布式協(xié)調(diào)服務(wù),它為分布式應(yīng)用提供了高效且可靠的分布式協(xié)調(diào)服務(wù),提供了諸如統(tǒng)一命名空間服務(wù)、配置服務(wù)和分布式鎖等分布式基礎(chǔ)服務(wù)。
3、分布式鎖
假如我們由三臺機器,每臺機器上都有一個進程。假設(shè)我們在第一臺機器上掛載了一個資源,三個進程都要來競爭這個資源。我們不希望這三個進程同時來訪問,那么就需要有一個協(xié)調(diào)器,來讓他們有序的對該資源進行訪問。這個協(xié)調(diào)器就是我們所說的那個鎖,比如說“進程1”在使用該資源的時候,就會先去獲得鎖,“進程1”就對該資源保持獨占,這樣其他的進程就無法訪問該資源?!斑M程1”用完該資源后就會將鎖釋放掉,讓其他的進程來獲得鎖。因此這個鎖機制就能保證我們的進程有序的訪問該資源。就稱作為“分布式鎖”,是分布式協(xié)調(diào)技術(shù)實現(xiàn)的核心內(nèi)容
4、分片
任務(wù)的分布式執(zhí)行,需要將一個任務(wù)拆分為多個獨立的任務(wù)項,然后由分布式的服務(wù)器分別執(zhí)行某一個或幾個分片項。
5、單點故障
通常分布式系統(tǒng)采用主從模式,就是一個主控機連接多個處理節(jié)點。主節(jié)點負責(zé)分發(fā)任務(wù),從節(jié)點負責(zé)處理任務(wù),當我們的主節(jié)點發(fā)生故障時,那么整個系統(tǒng)就癱瘓了,這就叫做單點故障。
傳統(tǒng)的解決辦法:
就是準備一個備用節(jié)點,這個備用節(jié)點定期給當前主節(jié)點發(fā)送ping包,主節(jié)點收到ping包后向備用節(jié)點發(fā)送回復(fù)Ack,當備用節(jié)點收到回復(fù)后就會認為主節(jié)點還活著,讓他繼續(xù)提供服務(wù)。
當主節(jié)點掛了,那么備用節(jié)點就收不到Ack回復(fù)了,然后備用節(jié)點就代替它成為了主節(jié)點。
但是存在一個安全隱患,那就是當發(fā)生網(wǎng)絡(luò)故障時,備用節(jié)點收不到主節(jié)點的回復(fù)Ack,他會認為主節(jié)點死了,它會代替主節(jié)點成為新的主節(jié)點。
zookeeper解決方案:
在引入了zookeeper后我們啟用了兩個主節(jié)點,A和B啟動后他們都會去Zookeeper去注冊一個節(jié)點,假設(shè)A注冊的節(jié)點為master-01,B注冊的節(jié)點為master-02,注冊完之后進行選舉,編號最小的節(jié)點將被選舉為主節(jié)點。
如果A掛了,它在zookeeper注冊的節(jié)點將會被自動刪除,Zookeeper感知到節(jié)點的變化,然后再次發(fā)出選舉,這時候B將獲勝成為新的主節(jié)點。如果A恢復(fù)了,它會去zookeeper再注冊一個節(jié)點,編號為master-03。這時zookeeper感知到節(jié)點的變化,會再次發(fā)起選舉,此時還是B勝出。那么B繼續(xù)擔任主節(jié)點,A則成為備用節(jié)點。
6、Mesos
——像用一臺電腦一樣使用整個數(shù)據(jù)中心
是Apache下的開源分布式資源管理框架,它被稱為分布式系統(tǒng)的內(nèi)核,是以與Linux內(nèi)核同樣的原則而創(chuàng)建的,不同點僅僅是在于抽象的層面。使用ZooKeeper實現(xiàn)Master和Slave的容錯。
7、FailStore策略
FailStrore,顧名思義就是Fail and Store,這個主要是用于失敗了存儲的,主要用于節(jié)點容錯,當遠程數(shù)據(jù)交互失敗后,存儲在本地,等待遠程通訊恢復(fù)后,再將數(shù)據(jù)進行提交。
聯(lián)系客服