久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

工作流系統(tǒng)的設(shè)計(jì)

 心不留意外塵 2016-08-27


幾年前曾經(jīng)寫過一點(diǎn)點(diǎn)對(duì)于緩存框架設(shè)計(jì)的體會(huì),,這大半年和工作流系統(tǒng)打交道頗為豐富,因此想總結(jié)一點(diǎn)關(guān)于工作流系統(tǒng)的設(shè)計(jì),。

首先,,明確工作流(workflow)系統(tǒng)的定義。維基百科上有極其簡單的介紹,。我記得以前在文章里面說過,,作為大公司里面的小team,為了做一些有趣的東西,,從而更好的招人,,通常有幾個(gè)眾人皆知的突破口:比如一個(gè)更符合業(yè)務(wù)需求的storage,再比如一個(gè)自定義的工作流系統(tǒng),。在Amazon內(nèi)部,,我接觸過好多個(gè)workflow,而且大多以Amazon SWF為原型(當(dāng)時(shí)學(xué)習(xí)的時(shí)候還寫了一點(diǎn)體會(huì),,link 1link 2),,于是宏觀上看,60%的東西是一樣的,,大同小異,;但是也有很多重要的元素大不相同,而它們被放到一起比較也是常事,。幾次折騰之后,,我也慢慢在思考,如何去設(shè)計(jì)一個(gè)工作流系統(tǒng),,其中都有哪些重要的需要考慮到的方面,。

Scalability

基本上隨便設(shè)計(jì)什么基礎(chǔ)設(shè)施,擴(kuò)展性都是重要的考慮內(nèi)容,。作為workflow來講,,基本上工作節(jié)點(diǎn)的水平擴(kuò)展是考量擴(kuò)展性的最重要標(biāo)志。既然工作節(jié)點(diǎn)可以水平擴(kuò)展,,那么這就意味著任務(wù)(task)必須是以pull的方式由工作節(jié)點(diǎn)主動(dòng)去獲取,,而不是由pull的方式從調(diào)度節(jié)點(diǎn)來分配(曾經(jīng)非常簡單地比較過pull和push,但其實(shí)二者差異遠(yuǎn)不止文中內(nèi)容之淺顯),。任務(wù)的分配上,,需要考慮這樣的事情:如果有多個(gè)工作節(jié)點(diǎn)嘗試來pull任務(wù),該分配給誰,?具體來說,,比如這樣的例子:如果每一個(gè)task節(jié)點(diǎn)允許同時(shí)執(zhí)行5個(gè)任務(wù),而現(xiàn)在可同時(shí)執(zhí)行的總?cè)蝿?wù)數(shù)只有5個(gè),,總共的task節(jié)點(diǎn)也有5個(gè),,最理想的狀態(tài)應(yīng)當(dāng)是這5個(gè)被均勻分配到這5個(gè)節(jié)點(diǎn)去,但是采用簡單的pull機(jī)制并不能保證這一點(diǎn),,有可能這5個(gè)任務(wù)全部跑到一臺(tái)機(jī)器上去了,,因?yàn)檫@并不超過一個(gè)節(jié)點(diǎn)可同時(shí)執(zhí)行任務(wù)數(shù)量的上限。

另一方面,,通常來講,,所有任務(wù)都應(yīng)當(dāng)是idempotent的,即可以重復(fù)提交執(zhí)行,,執(zhí)行若干次和執(zhí)行一次的結(jié)果是一樣的,。工作節(jié)點(diǎn)的任務(wù)執(zhí)行可以在任意一步發(fā)生錯(cuò)誤,隨著節(jié)點(diǎn)數(shù)量的增加,,這樣的錯(cuò)誤更多地成為一種常態(tài),,而不是“異常”,。工作節(jié)點(diǎn)的健康狀態(tài)需要由某種方式來維系和通知,,最典型和廉價(jià)有效的方式就是“心跳”,,我曾經(jīng)寫過一篇文章詳細(xì)介紹一種心跳系統(tǒng)的設(shè)計(jì),感興趣的話,,歡迎移步閱讀,。

功能性解耦

  • 資源管理和任務(wù)管理解耦。這一點(diǎn)我只在少數(shù)workflow里面見到,。任務(wù)管理幾乎是所有workflow都具備的,,但是單獨(dú)的資源管理則不是。舉例來說,,我可以寫一個(gè)task去執(zhí)行EMR上的任務(wù),,你也可以寫一個(gè)task去EMR上執(zhí)行,EMR的執(zhí)行管理邏輯,,可以以代碼的方式被我們共用——但是這種架構(gòu)下,,你的task和我的task很難安全高效地共享同一個(gè)EMR資源,無論是資源的創(chuàng)建,、銷毀,,狀態(tài)的查詢,還是throttling,,都變得很麻煩,。類似的例子還有,數(shù)據(jù)庫的共享,,打印機(jī)的共享,,甚至另外一個(gè)工作流系統(tǒng)的共享。當(dāng)有開銷較大的資源,,我們經(jīng)常需要workflow層面被統(tǒng)一管理起來,,管理一份或者幾份資源,但是共享給數(shù)量眾多的task,。
  • 業(yè)務(wù)邏輯和調(diào)度邏輯解耦,。這基本上在所有workflow里面都具備,調(diào)度邏輯是業(yè)務(wù)無關(guān)的,,也是相對(duì)來說“死”的東西,,管理工作流的狀態(tài),和每個(gè)task的成功失敗,。但是業(yè)務(wù)邏輯則是組成workflow和其中的task“活生生”的血肉,。我還沒有見過哪個(gè)workflow把業(yè)務(wù)代碼和調(diào)度邏輯寫到一起。
  • 狀態(tài)查詢和調(diào)度系統(tǒng)的解耦,。一個(gè)完善的工作流系統(tǒng),,調(diào)度只能是其中核心的一個(gè)方面,如果沒有一個(gè)好的狀態(tài)查詢系統(tǒng),維護(hù)的工作量將是巨大的,。而這二者,,必須解耦開。舉例來說,,工作流和任務(wù)執(zhí)行的狀態(tài),,必然是持久化在某種存儲(chǔ)介質(zhì)中,,比如關(guān)系數(shù)據(jù)庫,,比如NoSQL的數(shù)據(jù)庫,比如磁盤日志文件等等,。這個(gè)時(shí)候,,調(diào)度系統(tǒng)可以說是這些信息寫入存儲(chǔ)系統(tǒng)的最主要來源,而這些信息的讀取,,則可能從調(diào)度系統(tǒng)讀取,,也可能從狀態(tài)查詢系統(tǒng)讀取。這個(gè)存儲(chǔ)的格式或者說schema,,必須相對(duì)穩(wěn)定,。這個(gè)存儲(chǔ)的一致性和可用性,將是整個(gè)系統(tǒng)一致性和可用性的核心組成部分,。
  • 決策系統(tǒng)和執(zhí)行系統(tǒng)解耦,。決策系統(tǒng)用于決定某個(gè)任務(wù)是否滿足條件并開始該執(zhí)行,它是整個(gè)工作流系統(tǒng)的大腦,;執(zhí)行系統(tǒng)則是具體的一個(gè)個(gè)任務(wù),,它是整個(gè)工作流系統(tǒng)的骨肉。
  • 事件系統(tǒng)和監(jiān)聽系統(tǒng)解耦,。涉及這個(gè)的工作流只占少數(shù),。很多工作流系統(tǒng)都有內(nèi)部的事件系統(tǒng),比如某個(gè)task分配給某個(gè)節(jié)點(diǎn)了,,某個(gè)task執(zhí)行失敗了等等,,但是這樣事件的監(jiān)聽系統(tǒng),卻沒有獨(dú)立出來,,導(dǎo)致后續(xù)針對(duì)特殊事件要執(zhí)行特定邏輯變得困難,。

同步與異步任務(wù)

事實(shí)上,當(dāng)考慮到了獨(dú)立的資源管理功能,,異步和同步任務(wù)的劃分就變得自然而然,。

  • 有很多任務(wù)是需要在當(dāng)前的工作節(jié)點(diǎn)上執(zhí)行的。比如需要在工作節(jié)點(diǎn)上下載一個(gè)文件,,然后經(jīng)過處理以后寫到數(shù)據(jù)庫里去,,這些任務(wù)消耗大量的內(nèi)存和CPU,需要分配獨(dú)立的專屬的線程去完成,是同步任務(wù),。
  • 還有一些任務(wù),,工作節(jié)點(diǎn)并非實(shí)際的工作執(zhí)行者,而是針對(duì)某一個(gè)資源系統(tǒng)的客戶端,,只負(fù)責(zé)提交任務(wù)到該系統(tǒng)內(nèi),,并且負(fù)責(zé)管理和監(jiān)控。比如打印任務(wù),,向打印機(jī)提交打印請(qǐng)求,,然后只需要不斷地向打印機(jī)查詢?nèi)蝿?wù)的狀態(tài),以及根據(jù)需要作出刪除任務(wù)和重新提交等操作即可,。這些任務(wù)通常不需要長期占有線程,,一個(gè)線程可以在一個(gè)周期內(nèi)處理多個(gè)任務(wù)。它們是異步任務(wù),。另外,,舉一個(gè)特例,工作流的嵌套,,即工作流調(diào)用子工作流,,那么對(duì)于子工作流狀態(tài)的查詢這個(gè)行為來說,必然是異步任務(wù),。異步任務(wù)就涉及到事件的通知和監(jiān)聽機(jī)制,,后文有提到。

分布式鎖

在某些情況下,,分布式鎖變成一個(gè)必選項(xiàng),。比如前面提到的資源管理。有許多資源是要求操作是獨(dú)占的,,換言之,,不支持兩個(gè)操作并發(fā)調(diào)用,期間可能出現(xiàn)不可以預(yù)料的問題,;另一方面,,一個(gè)節(jié)點(diǎn)在對(duì)資源進(jìn)行操作時(shí),它需要和別的節(jié)點(diǎn)進(jìn)行協(xié)作,,從而兩個(gè)工作節(jié)點(diǎn)的操作是有序和正確的,,不至于發(fā)生沖突。

舉個(gè)例子來說,,工作節(jié)點(diǎn)A要查詢當(dāng)前EMR的狀態(tài),,如果已經(jīng)空閑10分鐘,就要執(zhí)行操作結(jié)束掉這個(gè)EMR資源,;而工作節(jié)點(diǎn)B則查詢?cè)揈MR的狀態(tài),,如果沒有被結(jié)束掉,就要往上面提交新的計(jì)算任務(wù)。這時(shí)候,,如果沒有分布式鎖的協(xié)作,,問題就來了,可能B節(jié)點(diǎn)先查詢發(fā)現(xiàn)EMR狀態(tài)還活著,,就這這一瞬間,,A節(jié)點(diǎn)結(jié)束了它,可是B不知道,,接著提交了一個(gè)計(jì)算任務(wù)到這個(gè)已經(jīng)結(jié)束了的(死了的)EMR資源上,,于是這個(gè)提交的計(jì)算任務(wù)必然執(zhí)行失敗了。

有很多分布式鎖的實(shí)現(xiàn)方式,,簡單的有強(qiáng)一致性的存儲(chǔ)系統(tǒng),,當(dāng)然也有更高效的實(shí)現(xiàn),比如一些專門的分布式鎖系統(tǒng),。

功能的可擴(kuò)展性

之前講到了性能架構(gòu)上的可擴(kuò)展性,在功能層面亦然,。

  • 自定義任務(wù),。這是幾乎所有工作流系統(tǒng)都會(huì)考慮的事情,這也是業(yè)務(wù)邏輯和調(diào)度邏輯解耦的必然,。因?yàn)楣ぷ髁飨到y(tǒng)設(shè)計(jì)的時(shí)候,,必然沒法預(yù)知所有的任務(wù)類型,用戶是可以定義自己的執(zhí)行邏輯的,。
  • 自定義資源,。有了資源管理,就有自定義資源的必要,。
  • 自定義事件監(jiān)聽,。事件管理通常在工作流系統(tǒng)中是很容易被忽視的內(nèi)容,比如我希望在某一個(gè)task超時(shí)的時(shí)候發(fā)送一個(gè)特殊的消息通知我,,這就需要給這個(gè)事件監(jiān)聽提供擴(kuò)展的可能性,。
  • 運(yùn)行時(shí)的工作流任務(wù)執(zhí)行條件。通常workflow都會(huì)有一個(gè)定義如何執(zhí)行的文件(meta file),,但是有一些執(zhí)行的參數(shù)和條件,,是在運(yùn)行時(shí)才能夠確定的,甚至依賴于上一步執(zhí)行的結(jié)果,,或者需要執(zhí)行一些邏輯才能得到,。

可用性和可靠性

大多數(shù)workflow,都采用了去中心節(jié)點(diǎn)的設(shè)計(jì),,保證不存在任何單點(diǎn)故障問題,。所有的子系統(tǒng)都是。也保證在業(yè)務(wù)壓力增加的情況下,標(biāo)志著可用性的latency在預(yù)期范圍之內(nèi),。其它的內(nèi)容不展開,,介紹這方面的文章到處都是。

生命周期管理

這里既指workflow一次執(zhí)行的生命周期管理,,也指單個(gè)task的生命周期管理,。

談?wù)撨@些必然涉及到這樣幾個(gè)問題:

  • workflow definition和workflow的分離,task definition和task execution的分離,。其中definition定義執(zhí)行的邏輯,,而execution才真正和執(zhí)行的環(huán)境、時(shí)間,、參數(shù)等等相關(guān),。邏輯通常可以只有一份(但這也不一定,,要看workflow是否支持多版本,,后文有提到),但是execution隨著重試的發(fā)生,,會(huì)保存多份,。
  • workflow重試時(shí),參數(shù)變化的處理,。有些參數(shù)的變化,,是不會(huì)影響已完成任務(wù)的,但是有的參數(shù)則不是,。
  • workflow重試時(shí),,對(duì)于已完成任務(wù)的處理。有的情況我們希望已完成任務(wù)也要重新執(zhí)行,,而又的情況我們則希望這些已完成任務(wù)被跳過,。
  • task的重試次數(shù),以及重試時(shí)back off的策略,。比如第一次重試需要等5分鐘,,第二次重試需要等10分鐘,最多重試2次,。
  • 如何禮貌地結(jié)束工作節(jié)點(diǎn)上的任務(wù)執(zhí)行,。在很多情況下我們不得不中斷并結(jié)束某個(gè)節(jié)點(diǎn)上的任務(wù)執(zhí)行,比如這個(gè)工作節(jié)點(diǎn)需要重啟,,這并不能算作業(yè)務(wù)代碼導(dǎo)致的任務(wù)執(zhí)行失敗,,而更像是一種“resource termination”。這種情況下,,任務(wù)通常需要被分配到另外活著的節(jié)點(diǎn)去,,而這里有牽涉到這個(gè)reallocation的策略,,前面已經(jīng)提到過。
  • 任務(wù)的權(quán)重,?;蛘呓凶鰞?yōu)先級(jí),這項(xiàng)功能我只在少數(shù)workflow中看到,。在考慮到資源分配時(shí),,某些更重要任務(wù)可具備更高優(yōu)先級(jí),而無關(guān)緊要的任務(wù)失敗甚至可以不影響workflow的狀態(tài),。

任務(wù)DAG的設(shè)計(jì)和表達(dá)

這是workflow執(zhí)行的流程圖,,也是所有task之間依賴關(guān)系的表述。我見過多種表達(dá)方式的,,有XML的,,也有JSON的,還有一些不知名的自己定義的格式的,。有些workflow的定義可以以一個(gè)圖形化工具來協(xié)助完成這個(gè)流程圖,。這個(gè)DSL的設(shè)計(jì),一定程度上決定了workflow的使用是不是能夠易于理解,。另外提一句,,這里提到的這個(gè)可選的圖形化工具,畢竟只是一個(gè)輔助,,它不是workflow的核心(你可以說這個(gè)DSL是核心的一部分,但這個(gè)幫助完成的工具顯然不是)——我見過一個(gè)團(tuán)隊(duì),,workflow整體設(shè)計(jì)得不怎么樣,,跑起來一堆問題,但是這個(gè)工具花了大量的時(shí)間精力去修繕,,本末倒置,。

另外,workflow的狀態(tài)和執(zhí)行情況,,還有對(duì)其的歸檔和管理,,也需要一個(gè)整合工具來協(xié)助。這方面幾乎所有workflow都具備,,通常都是網(wǎng)頁工具,,以及命令行工具。

輸入輸出的管理

這也是一個(gè)nice-to-have的東西,,對(duì)于每一個(gè)task,,都存在input和output,它們可以完全交給用戶自己來實(shí)現(xiàn),,比如用戶把它們存儲(chǔ)到文件里面,,或者寫到數(shù)據(jù)庫里面,,而workflow根本不管,每個(gè)task內(nèi)部自己去讀取相應(yīng)的用戶文件即可,。但是更好的方法是,,對(duì)于一些常用和簡單的input、output,,是可以隨著execution一起持久化到workflow和task的狀態(tài)里面去的,。這樣也便于workflow的definition里面,放置一些根據(jù)前一步task執(zhí)行結(jié)果來決策后續(xù)執(zhí)行的表達(dá)式,。

另外,,還有一個(gè)稍微冷門的use case,就是input和output的管理,。通常workflow是重復(fù)執(zhí)行的,,而每次執(zhí)行的input和output的數(shù)據(jù)規(guī)模往往是很多人關(guān)心的內(nèi)容。關(guān)于這部分,,我還沒有見到任何一個(gè)workflow提供這樣的功能,。許多用戶自己寫工具和腳本來獲取這樣的信息。

獨(dú)立的metrics和日志系統(tǒng)

對(duì)于metrics,,核心的內(nèi)容也無非節(jié)點(diǎn)的健康狀況,、CPU、內(nèi)存,,task執(zhí)行時(shí)間分布,,失敗率等等幾項(xiàng)。有些情況下用戶還希望自行擴(kuò)展,。

關(guān)于日志,,則主要指的是歸檔和合并。歸檔,,指的是歷史日志不丟失,,或者在一定時(shí)間內(nèi)不丟失,過期日志可以被覆寫,,從而不引起磁盤容量的問題,;而合并,指的是日志能被以更統(tǒng)一的視角進(jìn)行查詢和瀏覽,,出了問題不至于到每臺(tái)機(jī)器上去手動(dòng)查找,。缺少這個(gè)功能,有時(shí)候會(huì)很麻煩,。在工作中我遇到過一個(gè)資源被異常終止的問題,,為了找到那個(gè)終止資源的節(jié)點(diǎn),我查閱了幾十個(gè)節(jié)點(diǎn)的日志,,痛苦不堪,。

版本控制和平滑部署

把這兩個(gè)放一起是因?yàn)?,代碼升級(jí)是不可避免且經(jīng)常要發(fā)生的。為了保證平滑部署,,顯然通常情況下,,節(jié)點(diǎn)上的代碼不能同時(shí)更新,需要一部分一部分進(jìn)行,。比如,,先終止50%的節(jié)點(diǎn),部署代碼后,,激活并確保成功,,再進(jìn)行剩下那50%的節(jié)點(diǎn)。但是在這期間存在新老代碼并存的問題,,這通常會(huì)帶來很多奇形怪狀的問題,。對(duì)于這種問題,我見過這樣兩個(gè)解決方式:

  • 一個(gè)是全部節(jié)點(diǎn)同時(shí)部署,,這種情況下所有節(jié)點(diǎn)全部失活,,有可能出現(xiàn)因?yàn)檫@個(gè)失活導(dǎo)致的task超時(shí),甚至導(dǎo)致workflow執(zhí)行失敗,。但是workflow的生命周期由單獨(dú)的調(diào)度系統(tǒng)管理,,因此除去超時(shí)外多數(shù)情況不受影響。
  • 還有一種是一部分一部分部署,,最平滑,,但是這種情況下需要管理多版本共存問題,也對(duì)代碼質(zhì)量提出了新的要求——向后兼容,。

無論選用哪一種,,這種方式實(shí)現(xiàn)起來相對(duì)簡單,但是也有不少問題,,比如這種情況下,外部資源怎么處理,?例如在外部EMR資源上執(zhí)行Spark任務(wù),,但是已經(jīng)有老代碼被放到EMR上去執(zhí)行了,這時(shí)候工作節(jié)點(diǎn)更新,,這些EMR上正在執(zhí)行的任務(wù)怎樣處理,?是作廢還是保留,如果保留的話這些執(zhí)行可還是依仗著老代碼的,,其結(jié)果的后續(xù)處理是否會(huì)和剛部署的新代碼產(chǎn)生沖突,。再比如對(duì)于workflow有定義上的改變(比如DAG的改變),對(duì)于現(xiàn)有的execution,,應(yīng)當(dāng)怎樣處理,,是更新還是保持原樣(通常都是保持原樣,,因?yàn)楦聨淼膹?fù)雜問題非常多)。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多