分布式任務編排調度框架設計


運維焦油坑

隨着互聯網+和去IOE浪潮的推進,傳統行業X86服務器的數量逐漸增多。服務器數量劇增帶來的直接后果就是運維復雜度的增加。原本一個人可以輕松維護十幾台甚至幾十台服務器:寫幾個常用的監控和配置下發腳本、或者利用cronTab制作幾個定時任務就可以搞定。當服務器的數量由幾十上升到幾百,幾千時,量變就引起了質變;而且隨着應用數量的增多,需要同時對多個應用進行快速高效的備份或者持續部署等非常復雜的操作。傳統的運維思路已經很難滿足現實的需求了。這個時候,再牛掰的運維人員也會像焦油坑中的巨獸一樣舉步維艱。而本文將會給大家分享一種跳出運維焦油坑的實現思路。

工欲善其事

說到運維工具,大家都能信手拈來:Ansible,Pupet,Chef,Saltstack等等。每一種工具都給運維人員提供了很大的幫助,讓他們從繁瑣的運維任務中得到減負。因為本文主要介紹的是分布式任務調度框架,所以這里就不對這幾種運維工具的優劣進行過多地比較。就像標題中所說的,我們只要選一種運維工具,再加上一個穩定高效的任務調度框架,那么就可以輕松面對千萬台服務器的運維操作了。這里我們選擇的是Ansible。主要原因他是Agentless的。對於不喜歡在生產服務器上安裝各種插件的運維工程師來說是個不錯的選擇。

整體結構圖

本文主要跟大家分享的是分布式任務編排與調度框架設計。整個平台就有這么幾個關鍵點:分布式、任務編排、任務調度。

所謂分布式,就是平台是分布式部署的,各個節點之間可以無狀態和水平擴展;所謂任務編排,就是平台可以支撐多任務步驟,多步驟明細的復雜任務的編排和解析;所謂任務調度,就是平台可以對單一運維操作進行最優切分和調度,從而保證對大量服務器進行運維操作快速高效地完成。

有圖有真相。接下來給出整個平台的整體結構圖:



整體結構圖

通過圖上我們可以看到,整個平台依靠Zookeeper作為服務的注冊和管理中心;依托RabbitMQ進行服務模塊之間消息的傳遞;采用MySQL作為基礎數據的存儲。

運行全過程

接下來我們就各個模塊所提供的服務和模塊之間的交互流程跟大家具體描述。

Web模塊是平台的臉面,用來提供任務編排,任務執行進度等信息的展示。在啟動之初Web從Zookeeper上獲取可調用的Server的信息並緩存起來。同時,在Server有任何變化時(下線和上線),會接到通知來實時更新緩存。從而保證尋找Server服務時能夠更加快速和高效。

Server模塊是整個平台的核心,主要負責復雜任務編排的解析處理、復雜任務執行流程拆分和調度下發。Server啟動之初會向Zookeeper進行服務注冊,用來告知其他模塊,我已啟動,可以干活了;與此同時,它還會從服務中心那里獲取其他信息:比如還有幾個和他一樣的兄弟跟他並肩戰斗?還有幾個手下(Scheduler)可以用來執行任務?Server就像一台告訴運轉的引擎,隨時准備處理各種任務。

Scheduler模塊主要用於接受Server發過來的任務並進行更加細化拆分和下發。在模塊啟動之初,跟Server一樣進行自身服務的注冊和關注服務的獲取和緩存,比如,獲取真正可以干活的小弟(Worker)的信息。在面對大量服務器的時候就可以把目標機器進行拆分,讓每個Worker都能均衡的獲取和執行任務,加快任務執行速度。比如:Server發過來一個任務,要你備份一千台服務器的某個目錄。怎么做?一個個串行做嗎?開玩笑!單這一個任務就夠你執行半天。所以,關鍵時候還是要並發的把任務分配給多個Worker。然后再進行任務結果的收集就可以了。從某種角度講,Scheduler只能算是一個小組長,負責分配任務,收集結果。還是比較清閑的。

Worker模塊的主要負責具體任務的執行,是整個平台中最苦逼的一個模塊。它只能接受任務參數,任勞任怨的利用Ansible去目標機器執行任務,然后把任務的處理結果發送到MQ中。其實,worker也會有自己的小算盤。打個比方,Scheduler接受到的一千台服務器備份任務,假設平台有10個worker,那么每個worker將會分到100台服務器的備份任務。Worker會傻傻的一個一個執行嗎?當然不會!worker內部也會並發的去多個目標服務器上去執行備份任務,然后進行結果的回收。

核心技術點

啰嗦了那么多,相信大家對平台的整體運轉過程有了大致了解。接下來我們就這幾個核心技術點進行重點描述:

分布式:分布式的目標就是為了實現高可用,高吞吐量。上面說到的幾個模塊全部實現了分布式部署,各自的特點體現如下:

Web層,我們在前端采用了Nginx進行請求負載。利用了Redis進行Session信息的存儲。用來實現解決web層的高可用問題。

Server層自身就像一個獨立的任務編排調度引擎,可以獨立對外提供服務,多個server模塊之間可以依賴服務中心感知彼此的存在,在某個server掛掉的時候可以快速的把其中的任務轉移到其他的server模塊來執行。

Scheduler,Worker和Server一樣,同樣可以分布式部署並支持水平無限擴展。

任務編排:我們拿一個應用部署的過程來舉例:我們要發布一個javaweb應用到2台機器上。那么我們要做哪些操作呢?首先,我們要把負載下掉,web服務器(以Tomcat為例)停掉;其次,我們要把一些緩存數據,不用的日志數據清理掉;第三步,我們要把應用包從軟件倉庫拷貝到目標機器的指定路徑;第四步,我們要把web服務器啟動;最后一步,把應用的負載進行更新。這樣一個由五個操作步驟的復雜任務是如何進行編排的呢?我們將這個復雜任務定義了三個對象:Task, step, job。Task就是整個的復雜任務,step呢就是我們說的這五個步驟。Job就是每個步驟具體要做的事情。在任務編排的時候我們會把這三類對象數據和關聯關系數據存放到數據庫中。那么上面的這個例子對應出來的任務數據大體下如下:

task:

    step-1

        job-1-1

        job-1-2

    step-2

        job-2-1

    step-3

        job-3-1

    step-4

        job-4-1

    step-5

        job-5-1

在任務執行的時候我們采用的思路是:步驟(Step)之間串行執行,Step內部的Job並行執行。步驟之間串行執行是因為前后兩個任務之間存在依賴關系,如果沒有依賴關系的任務可以放到同一個步驟來執行。這樣就會提高整體任務的執行效率。整個復雜任務的解析執行過程如下:


任務執行過程

首先,Task Engine拿到整個任務數據,先會進行數據校驗。在格式正確的情況下依次執行各個步驟(Step),在單個Step中獲取具體執行的job列表,並對每個job的任務參數封裝成一個任務線程,丟到線程池中去執行。

其次,線程執行時會將具體的任務發送到Scheduler中,然后等待MQ中的job處理結果,Scheduler在接受到任務之后會根據目標機器和worker的數量以及單個worker的處理能力經驗值來計算出此次job需要調用worker的最優次數。然后將任務下發到具體的worker中來執行。同時,告知worker任務結果發送到MQ中的消息隊列。同時監聽MQ中該隊列的消息,接收到消息之后處理並回傳到server中的任務線程中。

最后,worker在接受到任務參數和結果隊列信息之后,會根據目標機器數量進行再次調度,然后收集任務處理結果並發送到scheduler執行的消息隊列中去。這樣,server接收到該step的所有job執行結果之后會繼續執行下一步驟中的各個job。最終把整個復雜任務處理完成。整個過程的數據流圖如下圖所示:


調度整體框架

任務調度:整個平台的任務調度分為三個層面的調度:首先是server和scheduler之間的調度。他們的調度方式包括pull和push兩種模式,即server會定時向scheduler推送任務消息,同時scheduler在執行完任務之后也會向server詢問是否有其他可執行的任務;其次是scheduler和worker之間的調度。我們這幾假設目標機器有M台,worker數量有W個,每個worker處理任務的經驗值是C個。我們的整體算法流程偽代碼如下:

if (targets>Worker * C){

    String[] targetArray = splitTarget(C)

    for(String target : targetArray){

        createRequest(target)--->worker

    }

}else{

    C = [targets/Worker]

    String[] targetArray = splitTarget(C)

    for(String target : targetArray){

        createRequest(target)--->worker

    }

}

當然,這個調度算法非常簡單,我們可以根據單個worker的實時負載情況進行復雜調度算法的增強,以及對於失敗任務的補償機制的增強處理都是在scheduler和worker之間可以調度優化的地方。

最后是worker內部的調度,worker會根據自身處理能力的大小,將多個目標機器進行再次分割,然后並發執行任務。從而提高整個平台的任務處理能力。

寫在最后

本文主要跟大家分享了一種分布式任務編排調度平台的設計思路,重點介紹了平台的三個重要特點:分布式,任務編排,和任務調度以及平台后續的優化方向:

一,任務編排處理過程中增加條件判斷邏輯;

二,scheduler和worker之間調度算法優化。

三,任務執行過程中中斷和人機交互的增強。

我們目前正在基於這個思路進行相關功能的落地。如果大家有其他的見解或者文中有哪些描述不合理的地方。歡迎批評指正。我們的目標就是構建出一個穩定高效的運維任務調度平台,幫助運維人員盡快爬出運維的焦油坑。

博雲原創 作者:丁明威


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com