[譯] 基于容器的(de)分布(bu)式系統(tong)設計(ji)模式
[譯] 基于容器的分布式系統設計模式
名(ming)稱:Design patterns for container-based distributed systems
作者:Brendan Burns, David Oppenheimer, Google
發布:HotCloud'16: Proceedings of the 8th USENIX Conference on Hot Topics in Cloud Computing, June 2016
譯者:sangmado
1 簡介
在(zai)(zai)(zai)20世(shi)紀(ji)80年代末(mo)期和90年代早期,面向(xiang)對象編(bian)程徹底改變(bian)了軟件(jian)的(de)(de)(de)開發方式(shi)(shi)(shi),使用(yong)模塊化的(de)(de)(de)組(zu)件(jian)進行應用(yong)程序構(gou)(gou)建(jian)變(bian)得更(geng)為普遍(bian)。時(shi)至今日(ri),我(wo)們看到分布式(shi)(shi)(shi)系統(tong)開發也(ye)在(zai)(zai)(zai)進行著(zhu)類似的(de)(de)(de)變(bian)革,基于(yu)容器化軟件(jian)組(zu)件(jian)構(gou)(gou)建(jian)的(de)(de)(de)微服務架(jia)構(gou)(gou)正(zheng)在(zai)(zai)(zai)變(bian)得越來越流行。容器,依賴其在(zai)(zai)(zai)容器化領域內創立的(de)(de)(de)多重優點,已經成為分布式(shi)(shi)(shi)系統(tong)構(gou)(gou)建(jian)的(de)(de)(de)基礎"對象"。隨著(zhu)架(jia)構(gou)(gou)風(feng)格的(de)(de)(de)成熟(shu),我(wo)們也(ye)看到了設(she)計模式(shi)(shi)(shi)的(de)(de)(de)涌現,就(jiu)像我(wo)們在(zai)(zai)(zai)面向(xiang)對象編(bian)程時(shi)一樣,出于(yu)對細(xi)(xi)粒度代碼(ma)細(xi)(xi)節的(de)(de)(de)封裝抽象,最終揭示了在(zai)(zai)(zai)各種應用(yong)程序和算(suan)法中(zhong)相通的(de)(de)(de)更(geng)高級的(de)(de)(de)設(she)計模式(shi)(shi)(shi)。
這(zhe)篇論文(wen)描述了(le)我們在基于容(rong)器(qi)構(gou)建的(de)分布(bu)式(shi)系統(tong)中識別出的(de)三種類型(xing)的(de)設計模(mo)(mo)(mo)式(shi):用(yong)(yong)于容(rong)器(qi)管理的(de)單容(rong)器(qi)模(mo)(mo)(mo)式(shi),多(duo)容(rong)器(qi)緊密協作的(de)單節點模(mo)(mo)(mo)式(shi),用(yong)(yong)于分布(bu)式(shi)算(suan)法的(de)多(duo)節點模(mo)(mo)(mo)式(shi)。就像面向對(dui)象設計模(mo)(mo)(mo)式(shi)一(yi)樣,這(zhe)些(xie)為(wei)分布(bu)式(shi)計算(suan)而生的(de)設計模(mo)(mo)(mo)式(shi)引入(ru)了(le)最佳實踐,簡化了(le)代碼開發(fa),并提(ti)升了(le)使用(yong)(yong)它(ta)們的(de)系統(tong)的(de)可靠(kao)性。
2 分布式系統設計模式
設(she)計模式(shi)的(de)涌現和文(wen)檔化,是在面向對象編程(cheng)被使(shi)用多年之(zhi)后(hou)才發(fa)生的(de)。這(zhe)些(xie)(xie)設(she)計模式(shi)將一些(xie)(xie)常規編程(cheng)問題的(de)解決方法進(jin)行(xing)了代碼化和規范化,而這(zhe)些(xie)(xie)編碼規約更進(jin)一步地(di)改善了行(xing)業的(de)編程(cheng)水平(ping),因為它使(shi)得(de)經驗不(bu)足的(de)程(cheng)序員也(ye)可以輸(shu)出高質量的(de)代碼。同時,可復用的(de)類庫機制(zhi)也(ye)使(shi)得(de)代碼越來越可靠,開(kai)發(fa)速度也(ye)比以往(wang)變得(de)更快。
現如(ru)今,分(fen)布(bu)式(shi)(shi)(shi)系(xi)統(tong)軟(ruan)件工程的(de)(de)(de)(de)最先進(jin)技術(shu),看起來更像(xiang)(xiang)是(shi)20世(shi)紀(ji)80年代早(zao)期編(bian)程的(de)(de)(de)(de)模(mo)(mo)樣(yang),而(er)不(bu)像(xiang)(xiang)是(shi)后期的(de)(de)(de)(de)面向對(dui)象軟(ruan)件開發(fa)。這其中的(de)(de)(de)(de)一(yi)個成功(gong)(gong)案例(li)就是(shi) MapReduce 模(mo)(mo)式(shi)(shi)(shi)。MapReduce 模(mo)(mo)式(shi)(shi)(shi)將大數據編(bian)程的(de)(de)(de)(de)力(li)量引入至廣闊的(de)(de)(de)(de)應(ying)用領域和開發(fa)者(zhe)群體,將正確的(de)(de)(de)(de)模(mo)(mo)式(shi)(shi)(shi)應(ying)用在(zai)合適的(de)(de)(de)(de)位置,極大地改進(jin)了分(fen)布(bu)式(shi)(shi)(shi)系(xi)統(tong)的(de)(de)(de)(de)質量、速度(du)和可(ke)訪問能力(li)。盡管如(ru)此,MapReduce 的(de)(de)(de)(de)成功(gong)(gong)仍(reng)然受到了單一(yi)編(bian)程語言(yan)的(de)(de)(de)(de)限制,截(jie)至目前 Apache Hadoop 生態系(xi)統(tong)仍(reng)主要是(shi)由 Java 語言(yan)編(bian)寫。所以,為分(fen)布(bu)式(shi)(shi)(shi)系(xi)統(tong)設計(ji)開發(fa)一(yi)套真正全面的(de)(de)(de)(de)模(mo)(mo)式(shi)(shi)(shi),需要一(yi)套非常(chang)通用的(de)(de)(de)(de)、與語言(yan)無關的(de)(de)(de)(de)工具來表(biao)述系(xi)統(tong)中的(de)(de)(de)(de)元(yuan)素。
萬(wan)幸的(de)(de)是,最近(jin)兩(liang)年(nian) Linux 容(rong)器技術興起并(bing)取(qu)得了(le)(le)廣泛的(de)(de)采(cai)用。容(rong)器與(yu)容(rong)器鏡像完(wan)美(mei)的(de)(de)滿足了(le)(le)開發(fa)分(fen)(fen)布(bu)式系統(tong)中模(mo)式的(de)(de)抽象(xiang)需求(qiu)。迄今(jin)為止,容(rong)器和容(rong)器鏡像已被廣泛的(de)(de)驗(yan)證,成為從開發(fa)至生產過程(cheng)(cheng)中交付(fu)軟(ruan)件的(de)(de)更(geng)好更(geng)可靠的(de)(de)方(fang)(fang)法(fa)。依(yi)靠緊密的(de)(de)封裝,依(yi)賴自治,原子(zi)部(bu)署(shu)(shu)與(yu)成敗標記(ji)等功能,其顯著地改(gai)進了(le)(le)老(lao)式的(de)(de)云(yun)與(yu)數據中心應(ying)用部(bu)署(shu)(shu)方(fang)(fang)式。然而,除了(le)(le)在部(bu)署(shu)(shu)工具(ju)方(fang)(fang)面(mian)(mian)表現(xian)出色,實際(ji)上(shang)容(rong)器還有巨大的(de)(de)潛力,我們(men)相(xiang)信(xin)(xin)它注(zhu)定可以成為類似對象(xiang)在面(mian)(mian)向對象(xiang)編程(cheng)(cheng)中的(de)(de)地位,并(bing)將推進分(fen)(fen)布(bu)式系統(tong)設計模(mo)式的(de)(de)發(fa)展。在接下來(lai)的(de)(de)章節中,將解釋為什么我們(men)相(xiang)信(xin)(xin)這是必然的(de)(de),并(bing)描述在未來(lai)的(de)(de)若干年(nian)中,已涌現(xian)出并(bing)常規化(hua)指(zhi)導(dao)分(fen)(fen)布(bu)式系統(tong)軟(ruan)件工程(cheng)(cheng)設計的(de)(de)設計模(mo)式。
3 單容器管理模式
容器為接口(kou)定義提供了天然的邊界(jie),就像對象的邊界(jie)一樣。容器不僅可以(yi)暴露應用(yong)級別的功能,也可以(yi)通過接口(kou)回調為管(guan)理系(xi)統服務。
傳統的(de)容(rong)器(qi)管(guan)(guan)(guan)理接(jie)口(kou)(kou)(kou)都是極其有(you)限(xian)的(de),一個容(rong)器(qi)一般僅暴(bao)露三個原(yuan)語:run(), pause(), stop()。盡管(guan)(guan)(guan)這些接(jie)口(kou)(kou)(kou)用途很大,但(dan)更(geng)(geng)豐(feng)富(fu)的(de)接(jie)口(kou)(kou)(kou)可(ke)以賦予系(xi)統開發和運維人員更(geng)(geng)多(duo)的(de)管(guan)(guan)(guan)理功(gong)能(neng)。同(tong)時,目前(qian)幾(ji)乎(hu)每種(zhong)現代編程(cheng)語言均(jun)支持基(ji)于(yu) HTTP 的(de) Web 服(fu)務(wu),而且支持類似 JSON 等的(de)通用數(shu)據格(ge)式,通過使(shi)用容(rong)器(qi)托管(guan)(guan)(guan) Web 服(fu)務(wu)器(qi)并指定端點,不僅可(ke)以暴(bao)露主要功(gong)能(neng),更(geng)(geng)使(shi)得定義基(ji)于(yu) HTTP 管(guan)(guan)(guan)理的(de) API 成(cheng)為可(ke)能(neng),
容器可以針對北向(xiang)暴露非(fei)常豐(feng)富的應(ying)用(yong)(yong)程序信(xin)息,比如應(ying)用(yong)(yong)特定(ding)的監控指標,開發者關注(zhu)的分析(xi)信(xin)息,組(zu)件(jian)配(pei)置信(xin)息和服務日志(zhi)等(deng)。具體的實(shi)現中,Kubernetes、Aurora、Marathon 等(deng)容器管理系統(tong)均(jun)允許用(yong)(yong)戶定(ding)義通過(guo)特定(ding)的端點來進(jin)行健康探測。
對(dui)(dui)于南向接(jie)口(kou),容器(qi)提(ti)(ti)供一種(zhong)機(ji)制來定義一個(ge)(ge)生(sheng)命周(zhou)期,使(shi)得(de)編寫被(bei)管(guan)(guan)理(li)系(xi)統(tong)(tong)管(guan)(guan)控(kong)的(de)軟件(jian)組件(jian)更(geng)加方(fang)便。例(li)如,一個(ge)(ge)集群管(guan)(guan)理(li)系(xi)統(tong)(tong)可(ke)以(yi)為任(ren)務分(fen)配(pei)優(you)(you)先(xian)級(ji),高(gao)優(you)(you)先(xian)級(ji)任(ren)務即(ji)使(shi)在(zai)(zai)集群超賣的(de)條(tiao)件(jian)下也(ye)可(ke)以(yi)被(bei)有保障的(de)執行(xing)。這(zhe)種(zhong)保障是通過剔除正(zheng)在(zai)(zai)運行(xing)的(de)低(di)(di)優(you)(you)先(xian)級(ji)任(ren)務進行(xing)強制實施(shi)的(de),而(er)那些低(di)(di)優(you)(you)先(xian)級(ji)任(ren)務則(ze)可(ke)在(zai)(zai)集群資源可(ke)用(yong)時(shi)(shi)再被(bei)執行(xing)。剔除機(ji)制可(ke)以(yi)簡單(dan)(dan)粗暴到直(zhi)接(jie)殺死(si)低(di)(di)優(you)(you)先(xian)級(ji)任(ren)務,但這(zhe)種(zhong)方(fang)式給開(kai)發(fa)者帶(dai)來了額外的(de)負擔,他(ta)們不得(de)不考(kao)慮代碼(ma)在(zai)(zai)任(ren)意時(shi)(shi)刻(ke)都能被(bei)殺死(si)的(de)場景。取而(er)代之(zhi)(zhi)的(de),若是在(zai)(zai)應(ying)(ying)用(yong)程序(xu)(xu)和(he)管(guan)(guan)理(li)系(xi)統(tong)(tong)之(zhi)(zhi)間(jian)構建(jian)一個(ge)(ge)生(sheng)命周(zhou)期機(ji)制,開(kai)發(fa)者通過依(yi)賴和(he)遵(zun)循(xun)契約,不僅系(xi)統(tong)(tong)開(kai)發(fa)變得(de)更(geng)簡單(dan)(dan),同(tong)時(shi)(shi)也(ye)可(ke)以(yi)讓應(ying)(ying)用(yong)程序(xu)(xu)變得(de)更(geng)具管(guan)(guan)理(li)性。例(li)如,Kubernetes 使(shi)用(yong) Docker 的(de) "優(you)(you)雅刪除" 功能來對(dui)(dui)容器(qi)進行(xing)提(ti)(ti)前(qian)預警,通過發(fa)送(song) SIGTERM 信(xin)號給即(ji)將被(bei)終結的(de)容器(qi),在(zai)(zai)應(ying)(ying)用(yong)程序(xu)(xu)設(she)定的(de)時(shi)(shi)間(jian)窗口(kou)之(zhi)(zhi)后再發(fa)送(song) SIGKILL 信(xin)號。這(zhe)樣則(ze)可(ke)讓應(ying)(ying)用(yong)程序(xu)(xu)在(zai)(zai)被(bei)終結前(qian)完成正(zheng)在(zai)(zai)執行(xing)的(de)操作,將業(ye)務狀(zhuang)(zhuang)態寫入磁(ci)盤等。想象下,我們可(ke)以(yi)提(ti)(ti)供一種(zhong)機(ji)制來支持(chi)狀(zhuang)(zhuang)態的(de)序(xu)(xu)列化和(he)狀(zhuang)(zhuang)態恢(hui)復,以(yi)便基于狀(zhuang)(zhuang)態的(de)分(fen)布式系(xi)統(tong)(tong)對(dui)(dui)狀(zhuang)(zhuang)態的(de)管(guan)(guan)理(li)更(geng)優(you)(you)雅。
再舉個復雜(za)生命周期(qi)的(de)(de)例(li)子,比如 Android 系統中的(de)(de) Activity 模型,它支持一(yi)(yi)(yi)系列(lie)的(de)(de)回(hui)(hui)調接口(kou)(kou)和一(yi)(yi)(yi)個用(yong)于定義(yi)(yi)系統該如何觸發(fa)這些回(hui)(hui)調的(de)(de)狀(zhuang)態(tai)機(ji)(ji)。如果沒有這些生命周期(qi)定義(yi)(yi),開(kai)發(fa)魯棒的(de)(de)、可靠(kao)的(de)(de) Android 應用(yong)程序將變得難上(shang)加難。而在基于容器(qi)的(de)(de)系統上(shang)下文中,通常(chang)會定義(yi)(yi)一(yi)(yi)(yi)系列(lie)的(de)(de)回(hui)(hui)調鉤子,以(yi)便(bian)在容器(qi)創建、啟動、終(zhong)止時(shi)進(jin)行(xing)調用(yong)。另一(yi)(yi)(yi)個關(guan)于南向接口(kou)(kou) API 的(de)(de)例(li)子是(shi)容器(qi)對 "自我復制" 機(ji)(ji)制的(de)(de)支持,以(yi)便(bian)對服務(wu)進(jin)行(xing)擴展。
4 單節點、多容器應用模式
除了單個容(rong)器(qi)(qi)的(de)接口之外,我們還可以看到跨容(rong)器(qi)(qi)設計(ji)模式的(de)涌現。之前我們已經(jing)確(que)定了幾(ji)個這(zhe)樣的(de)模式。這(zhe)些(xie)單節點模式由共(gong)生(sheng)容(rong)器(qi)(qi)組成,它們被共(gong)同調(diao)度到同一臺主機上。容(rong)器(qi)(qi)管理系統支持將(jiang)多個容(rong)器(qi)(qi)作為一個原子單元(yuan)進行協(xie)同調(diao)度,Kubernetes 將(jiang)此抽(chou)象(xiang)為 "Pods",而(er) Nomad 則將(jiang)其抽(chou)象(xiang)為 "task groups",這(zhe)也(ye)是(shi)本節中描述的(de)模式所必需的(de)特性(xing)。
4.1 邊車模式
邊(bian)車(che)(che)(che)模(mo)式是首個(ge)也是最(zui)常(chang)見(jian)(jian)的(de)(de)(de)多(duo)容(rong)器部署模(mo)式,邊(bian)車(che)(che)(che)擴(kuo)展(zhan)并增強了(le)主(zhu)容(rong)器。例(li)如,主(zhu)容(rong)器可(ke)能(neng)(neng)是一(yi)個(ge) Web 服務(wu)器,它可(ke)以與(yu)一(yi)個(ge)能(neng)(neng)夠從本(ben)地磁盤(pan)收集(ji) Web 服務(wu)器的(de)(de)(de)日(ri)志 "logsaver" 邊(bian)車(che)(che)(che)容(rong)器配合,并將(jiang)日(ri)志發送至存儲系統集(ji)群。圖(tu)1展(zhan)示了(le)邊(bian)車(che)(che)(che)模(mo)式的(de)(de)(de)一(yi)個(ge)示例(li)。另一(yi)個(ge)常(chang)見(jian)(jian)的(de)(de)(de)示例(li)是一(yi)個(ge)基(ji)于 Web 的(de)(de)(de)本(ben)地磁盤(pan)內(nei)(nei)容(rong)服務(wu)器,這(zhe)(zhe)些內(nei)(nei)容(rong)由邊(bian)車(che)(che)(che)容(rong)器填充,邊(bian)車(che)(che)(che)容(rong)器定期對 Git 倉庫、內(nei)(nei)容(rong)管理系統或其他數據源的(de)(de)(de)內(nei)(nei)容(rong)進行定期同(tong)步。這(zhe)(zhe)兩個(ge)例(li)子在(zai) Google 內(nei)(nei)部應(ying)用中都很(hen)常(chang)見(jian)(jian)。在(zai)同(tong)一(yi)機(ji)器上的(de)(de)(de)容(rong)器可(ke)以共享同(tong)一(yi)個(ge)本(ben)地磁盤(pan)卷,也使得邊(bian)車(che)(che)(che)機(ji)制成(cheng)為可(ke)能(neng)(neng)。

當然(ran),盡管也(ye)可以將(jiang)邊車容(rong)器的功能(neng)構(gou)建到主容(rong)器中,但(dan)是使用獨(du)立容(rong)器有幾個(ge)好處(chu)。
- 首先,容器是資源計算和分配的單元,因此例如可以對一個 Web 服務器容器的 cgroup 進行配置,以便它對查詢提供一致的低延遲響應,而 logsaver 容器則可配置為當 Web 服務器不繁忙時再執行。
- 其次,容器是打包的單元,因此將業務服務和日志存儲分離到不同的容器中,可以很容易地將它們的開發職責劃分給兩個獨立的開發團隊,并允許對它們進行獨立測試,當然也可以一起測試。
- 第三,容器是可復用的單元,因此邊車容器可以與許多不同的主容器進行搭配(例如,一個日志存儲容器可以與產生日志的任何組件一起使用)。
- 第四,容器提供了一個失敗管控邊界,使整個系統能夠正常降級(例如,即使日志存儲程序發生故障,Web 服務器仍然可以繼續提供服務)。
- 最后,容器是部署單元,它允許對每個功能塊進行升級,并在必要時獨立地回滾。(當然也需要指出,這個好處也有一個缺點,即整個系統的測試矩陣必須考慮所有可能在生產中遇到的容器版本組合,這可能是巨大的,因為一組容器通常不能被原子性的整體升級。當然,雖然單體應用程序沒有這個問題,但組件化系統在某些方面更加容易測試,因為它們是由可以獨立測試的較小單元構建的。)
請注意(yi),以上五(wu)個優點適用于(yu)本文后續(xu)部分(fen)中描述的所有容器模(mo)式。
4.2 大使模式
我們觀察到的(de)下一個模式是大(da)使(shi)模式。大(da)使(shi)容(rong)器(qi)代理了與主容(rong)器(qi)之(zhi)間的(de)通信。例如,開發(fa)人員可能(neng)將使(shi)用(yong) memcache 協議(yi)的(de)應(ying)(ying)用(yong)程(cheng)(cheng)序(xu)與 twemproxy 大(da)使(shi)進(jin)行(xing)搭配。應(ying)(ying)用(yong)程(cheng)(cheng)序(xu)認(ren)為它只是與本地主機上的(de)單個 memcache 進(jin)行(xing)交互,但實際上 twemproxy 則將分片請求轉發(fa)至在其他地方安(an)裝的(de)分布式 memcache 集群節點上。
這個容(rong)器模式(shi)在三方面對程(cheng)序員的(de)開發過(guo)程(cheng)進(jin)行了簡化:他(ta)們(men)只需要思(si)考(kao)和編(bian)寫應用(yong)程(cheng)序連接到一(yi)個在本地(di)主(zhu)機上的(de)服務器,他(ta)們(men)可以通過(guo)在本地(di)機器上運行一(yi)個真正的(de) memcache 實例(li)而非大使來對應用(yong)程(cheng)序進(jin)行獨立測(ce)試,他(ta)們(men)可以在其他(ta)應用(yong)程(cheng)序中(zhong)復用(yong) twemproxy 大使,甚(shen)至可以是不同的(de)編(bian)程(cheng)語言。因為同一(yi)機器上的(de)容(rong)器共享相同的(de)本地(di)主(zhu)機網絡接口(kou),方使得大使模式(shi)成(cheng)為可能。圖(tu)2展示(shi)了此模式(shi)的(de)一(yi)個示(shi)例(li)。

4.3 適配器模式
我們(men)(men)觀(guan)察到(dao)的(de)(de)(de)(de)(de)(de)最后一(yi)(yi)(yi)個單節點模式(shi)(shi)是適配(pei)器模式(shi)(shi)。與(yu)簡(jian)化(hua)外(wai)部世(shi)界呈現(xian)視(shi)圖(tu)的(de)(de)(de)(de)(de)(de)大使(shi)模式(shi)(shi)相(xiang)反,適配(pei)器模式(shi)(shi)則(ze)是通(tong)過(guo)(guo)簡(jian)化(hua)的(de)(de)(de)(de)(de)(de)、同質(zhi)化(hua)的(de)(de)(de)(de)(de)(de)外(wai)部世(shi)界視(shi)圖(tu)來進行呈現(xian)。其通(tong)過(guo)(guo)標(biao)(biao)準化(hua)輸出和跨多個容器的(de)(de)(de)(de)(de)(de)接(jie)(jie)口(kou)來實現(xian)這一(yi)(yi)(yi)點。適配(pei)器模式(shi)(shi)的(de)(de)(de)(de)(de)(de)一(yi)(yi)(yi)個典型案(an)例(li)(li),就是通(tong)過(guo)(guo)適配(pei)器模式(shi)(shi)來確保系統(tong)中的(de)(de)(de)(de)(de)(de)所有(you)容器都具有(you)相(xiang)同的(de)(de)(de)(de)(de)(de)監(jian)控接(jie)(jie)口(kou)。現(xian)今的(de)(de)(de)(de)(de)(de)應(ying)用(yong)(yong)(yong)(yong)程(cheng)(cheng)序(xu)(xu)(xu)使(shi)用(yong)(yong)(yong)(yong)各種各樣的(de)(de)(de)(de)(de)(de)方法來輸出它(ta)們(men)(men)的(de)(de)(de)(de)(de)(de)指標(biao)(biao)(例(li)(li)如(ru) JMX、statsd 等)。但是,如(ru)果所有(you)應(ying)用(yong)(yong)(yong)(yong)程(cheng)(cheng)序(xu)(xu)(xu)都提(ti)(ti)供一(yi)(yi)(yi)致的(de)(de)(de)(de)(de)(de)監(jian)控接(jie)(jie)口(kou),則(ze)使(shi)用(yong)(yong)(yong)(yong)一(yi)(yi)(yi)個監(jian)控工(gong)具就可(ke)以更容易的(de)(de)(de)(de)(de)(de)收集、聚(ju)合(he)和展示來自(zi)異構應(ying)用(yong)(yong)(yong)(yong)程(cheng)(cheng)序(xu)(xu)(xu)的(de)(de)(de)(de)(de)(de)指標(biao)(biao)。在(zai)(zai) Google,我們(men)(men)通(tong)過(guo)(guo)代(dai)碼(ma)規(gui)約實現(xian)了這一(yi)(yi)(yi)點,但這只有(you)在(zai)(zai)您從頭(tou)構建(jian)軟(ruan)件時才(cai)有(you)可(ke)能(neng)實現(xian)。那(nei)些遺(yi)留(liu)的(de)(de)(de)(de)(de)(de)應(ying)用(yong)(yong)(yong)(yong)程(cheng)(cheng)序(xu)(xu)(xu)和開源應(ying)用(yong)(yong)(yong)(yong)程(cheng)(cheng)序(xu)(xu)(xu),可(ke)以通(tong)過(guo)(guo)適配(pei)器模式(shi)(shi)提(ti)(ti)供統(tong)一(yi)(yi)(yi)的(de)(de)(de)(de)(de)(de)接(jie)(jie)口(kou),而不需要修(xiu)改原(yuan)始應(ying)用(yong)(yong)(yong)(yong)程(cheng)(cheng)序(xu)(xu)(xu)。主(zhu)容器可(ke)以通(tong)過(guo)(guo)本(ben)地主(zhu)機或共享的(de)(de)(de)(de)(de)(de)本(ben)地卷與(yu)適配(pei)器進行通(tong)信(xin)。如(ru)圖(tu)3所示。請注意(yi),盡管一(yi)(yi)(yi)些現(xian)有(you)的(de)(de)(de)(de)(de)(de)監(jian)控解決方案(an)也(ye)能(neng)夠與(yu)多種類型的(de)(de)(de)(de)(de)(de)后端進行通(tong)信(xin),那(nei)是因為它(ta)們(men)(men)在(zai)(zai)監(jian)控系統(tong)本(ben)身中使(shi)用(yong)(yong)(yong)(yong)特定于(yu)應(ying)用(yong)(yong)(yong)(yong)程(cheng)(cheng)序(xu)(xu)(xu)的(de)(de)(de)(de)(de)(de)代(dai)碼(ma),這顯然(ran)不太符(fu)合(he)關注點分離模式(shi)(shi)。

5 多節點應用模式
除了在一臺機器上互相(xiang)協(xie)作的(de)(de)(de)(de)容(rong)器外,模塊化的(de)(de)(de)(de)容(rong)器使得(de)構建協(xie)調的(de)(de)(de)(de)多節點(dian)分(fen)布式應(ying)用(yong)程序變得(de)更(geng)加(jia)容(rong)易。接下來,我們(men)將描述其中的(de)(de)(de)(de)三(san)種分(fen)布式系(xi)統(tong)模式。與前一節中的(de)(de)(de)(de)模式類似(si),這些模式也需要系(xi)統(tong)對 Pod 抽象的(de)(de)(de)(de)支持。
5.1 領導者選舉模式
分(fen)布式(shi)系統(tong)中最常見(jian)的(de)問題之(zhi)一(yi)就是領(ling)(ling)(ling)導(dao)者選(xuan)舉(ju)(ju)。通常實(shi)(shi)例副本(ben)用(yong)于在(zai)一(yi)個(ge)組(zu)件的(de)多個(ge)相同(tong)實(shi)(shi)例之(zhi)間共享負載(zai),但應(ying)用(yong)程序(xu)副本(ben)的(de)另一(yi)個(ge)更復雜的(de)使用(yong)場景是需(xu)要將一(yi)個(ge) "領(ling)(ling)(ling)導(dao)者" 副本(ben)與其他副本(ben)區分(fen)開來(lai)。如果當前領(ling)(ling)(ling)導(dao)者副本(ben)故障了,則其他的(de)副本(ben)需(xu)要迅速的(de)進(jin)行(xing)取代。系統(tong)甚至(zhi)可以(yi)并行(xing)地進(jin)行(xing)領(ling)(ling)(ling)導(dao)者選(xuan)舉(ju)(ju),例如,多個(ge)分(fen)片均(jun)需(xu)要確定(ding)領(ling)(ling)(ling)導(dao)者。
有許多類庫(ku)可以(yi)(yi)進行(xing)領(ling)(ling)導(dao)(dao)(dao)者(zhe)選(xuan)(xuan)(xuan)舉(ju),它們通(tong)常(chang)很復(fu)雜,也難以(yi)(yi)正確理解和(he)使(shi)用(yong)(yong)。此外,它們還(huan)受(shou)到使(shi)用(yong)(yong)特定編(bian)程語言實現帶來的(de)(de)(de)限制。一種(zhong)替代的(de)(de)(de)方案(an)就是將領(ling)(ling)導(dao)(dao)(dao)者(zhe)選(xuan)(xuan)(xuan)舉(ju)機制從應(ying)用(yong)(yong)程序中(zhong)剝離至領(ling)(ling)導(dao)(dao)(dao)者(zhe)選(xuan)(xuan)(xuan)舉(ju)專(zhuan)屬容(rong)器(qi)(qi)中(zhong)。提供一組領(ling)(ling)導(dao)(dao)(dao)者(zhe)選(xuan)(xuan)(xuan)舉(ju)容(rong)器(qi)(qi),它們中(zhong)的(de)(de)(de)每個(ge)容(rong)器(qi)(qi)都(dou)與需(xu)要(yao)進行(xing)領(ling)(ling)導(dao)(dao)(dao)者(zhe)選(xuan)(xuan)(xuan)舉(ju)的(de)(de)(de)應(ying)用(yong)(yong)程序共同(tong)調度,則可在這些領(ling)(ling)導(dao)(dao)(dao)者(zhe)選(xuan)(xuan)(xuan)舉(ju)容(rong)器(qi)(qi)之間(jian)執(zhi)行(xing)選(xuan)(xuan)(xuan)舉(ju)。同(tong)時,它們可以(yi)(yi)在 localhost 上(shang)為需(xu)要(yao)進行(xing)領(ling)(ling)導(dao)(dao)(dao)者(zhe)選(xuan)(xuan)(xuan)舉(ju)的(de)(de)(de)應(ying)用(yong)(yong)程序容(rong)器(qi)(qi)提供一個(ge)簡化(hua)的(de)(de)(de) HTTP API (例如,becomeLeader、renewLeadership 等)。這些領(ling)(ling)導(dao)(dao)(dao)者(zhe)選(xuan)(xuan)(xuan)舉(ju)容(rong)器(qi)(qi)可以(yi)(yi)由這個(ge)復(fu)雜領(ling)(ling)域(yu)的(de)(de)(de)專(zhuan)家進行(xing)構建,然后不管應(ying)用(yong)(yong)程序開(kai)發人(ren)員選(xuan)(xuan)(xuan)擇何種(zhong)編(bian)程語言,都(dou)可以(yi)(yi)復(fu)用(yong)(yong)其簡化(hua)的(de)(de)(de)接(jie)口。這種(zhong)方式代表了軟件工(gong)程中(zhong)最(zui)好(hao)的(de)(de)(de)抽象和(he)封(feng)裝過程。
5.2 工作隊列模式
盡管工作隊列模式,也(ye)包括領(ling)導者選(xuan)舉模式,已(yi)經是被研(yan)究得很深入的(de)課題,并且有許多框架(jia)(jia)也(ye)實現了它(ta)們(men),但這(zhe)些分布式系(xi)(xi)統(tong)設計模式仍然是可以在(zai)面向容器(qi)的(de)系(xi)(xi)統(tong)架(jia)(jia)構(gou)中(zhong)獲(huo)益(yi)。在(zai)以往的(de)系(xi)(xi)統(tong)中(zhong),應用程序框架(jia)(jia)限制了項目的(de)單一開(kai)發語(yu)言環(huan)境(jing)(如 Python 中(zhong)的(de) Celery),或者任務(wu)分發和二進制執(zhi)行已(yi)與實現者脫離(如 Condor)。
容器針對 run() 和 mount() 接口的實現,使得實現一個通用的工作隊列框架變得簡單直接,可以將任意的處理代碼打包成一個容器,與任意數據,構建成一個完整的工作隊列系統。
開發人(ren)員只(zhi)需要構建一個(ge)容(rong)器(qi),可以從(cong)文件系統接收(shou)一個(ge)數據文件,并將(jiang)其轉換為一個(ge)輸出文件;這個(ge)容(rong)器(qi)還可以作(zuo)為工作(zuo)隊(dui)列(lie)的一個(ge)階段來使用(yong)。所有其他的涉及(ji)開發一個(ge)完整的工作(zuo)隊(dui)列(lie)的工作(zuo)均可由通(tong)用(yong)工作(zuo)隊(dui)列(lie)進(jin)行(xing)處理,并可在(zai)任(ren)意時(shi)刻(ke)進(jin)行(xing)復(fu)用(yong)。用(yong)戶代碼集成到這個(ge)工作(zuo)隊(dui)列(lie)共享框架的方式如圖(tu)4所示。

5.3 分散/收集模式
最后(hou)一個(ge)(ge)我們(men)要著(zhu)重介紹的(de)(de)分布(bu)式(shi)系(xi)(xi)統(tong)涉及模(mo)式(shi)是分散(san)/收集(ji)(ji)模(mo)式(shi)。給定一個(ge)(ge)系(xi)(xi)統(tong),一個(ge)(ge)外部客(ke)戶端向"根(gen)"或"父"節點發送一個(ge)(ge)初始請(qing)(qing)求(qiu),這(zhe)(zhe)(zhe)個(ge)(ge)"根(gen)"節點將請(qing)(qing)求(qiu)分發給大(da)(da)量服(fu)務器(qi)以執(zhi)行并行計(ji)(ji)算,每個(ge)(ge)服(fu)務器(qi)分片均返(fan)回部分數(shu)據(ju),然后(hou)"根(gen)"節點再(zai)將這(zhe)(zhe)(zhe)些數(shu)據(ju)收集(ji)(ji)到(dao)原(yuan)始請(qing)(qing)求(qiu)的(de)(de)單個(ge)(ge)響(xiang)應中。這(zhe)(zhe)(zhe)種設計(ji)(ji)模(mo)式(shi)在搜索引擎(qing)中很常(chang)見。開發這(zhe)(zhe)(zhe)樣一個(ge)(ge)分布(bu)式(shi)系(xi)(xi)統(tong)需要大(da)(da)量的(de)(de)樣板(ban)代(dai)碼(ma):分散(san)請(qing)(qing)求(qiu)、收集(ji)(ji)響(xiang)應、與(yu)客(ke)戶端交互(hu)等,而這(zhe)(zhe)(zhe)些代(dai)碼(ma)在面向對象編程(cheng)中是完全通用的(de)(de),重復的(de)(de)。通過容器(qi)化的(de)(de)方案來進行重構(gou),當客(ke)戶端發起請(qing)(qing)求(qiu)至"根(gen)"容器(qi)時,按照開發人員(yuan)的(de)(de)設計(ji)(ji),請(qing)(qing)求(qiu)被扇出至葉子容器(qi)集(ji)(ji)群中,開發人員(yuan)再(zai)指定一個(ge)(ge)容器(qi)負責結(jie)果集(ji)(ji)的(de)(de)收集(ji)(ji)和聚合。
具體(ti)的(de)(de)說(shuo),實現(xian)分散/收(shou)集系統(tong),用戶需(xu)要(yao)提(ti)(ti)供(gong)兩類容(rong)(rong)(rong)(rong)器(qi)(qi)(qi)。首先,一類容(rong)(rong)(rong)(rong)器(qi)(qi)(qi)實現(xian)葉子節(jie)點計算,這個(ge)(ge)容(rong)(rong)(rong)(rong)器(qi)(qi)(qi)執(zhi)行部分計算并(bing)返回相應的(de)(de)結果(guo)。第二(er)種容(rong)(rong)(rong)(rong)器(qi)(qi)(qi)是合并(bing)容(rong)(rong)(rong)(rong)器(qi)(qi)(qi),這個(ge)(ge)容(rong)(rong)(rong)(rong)器(qi)(qi)(qi)需(xu)要(yao)匯(hui)總所有葉子容(rong)(rong)(rong)(rong)器(qi)(qi)(qi)的(de)(de)計算結果(guo),并(bing)組(zu)織成一個(ge)(ge)單(dan)一的(de)(de)響(xiang)應后輸(shu)出。很容(rong)(rong)(rong)(rong)易(yi)看出用戶可(ke)以實現(xian)任(ren)意深度的(de)(de)分散/收(shou)集系統(tong),只需(xu)提(ti)(ti)供(gong)已實現(xian)這些相對簡單(dan)的(de)(de)接口(kou)的(de)(de)容(rong)(rong)(rong)(rong)器(qi)(qi)(qi)即可(ke)。這樣(yang)一個(ge)(ge)系統(tong)如圖5所示(shi)。

6 相關工作
早期(qi)的(de)(de)(de)(de)(de)面向服務(wu)的(de)(de)(de)(de)(de) SOA 架構與基(ji)于(yu)(yu)容(rong)器(qi)的(de)(de)(de)(de)(de)分布式(shi)(shi)(shi)系(xi)統架構有許多相(xiang)通(tong)(tong)的(de)(de)(de)(de)(de)特(te)征。例如,兩者(zhe)都強調可重用的(de)(de)(de)(de)(de)組(zu)(zu)件(jian)(jian)(jian)需要(yao)通(tong)(tong)過定義良好的(de)(de)(de)(de)(de)接口(kou)基(ji)于(yu)(yu)網絡進行通(tong)(tong)信。另一方面,與我們(men)所描(miao)(miao)述的(de)(de)(de)(de)(de)多容(rong)器(qi)模式(shi)(shi)(shi)相(xiang)比,SOA 系(xi)統中(zhong)的(de)(de)(de)(de)(de)組(zu)(zu)件(jian)(jian)(jian)往往粒度(du)更(geng)大,耦(ou)合更(geng)松(song)散。此外,SOA 中(zhong)的(de)(de)(de)(de)(de)組(zu)(zu)件(jian)(jian)(jian)通(tong)(tong)常實現具體(ti)的(de)(de)(de)(de)(de)業務(wu),而我們(men)在這里(li)所關(guan)注的(de)(de)(de)(de)(de)組(zu)(zu)件(jian)(jian)(jian)更(geng)傾向于(yu)(yu)通(tong)(tong)過通(tong)(tong)用類庫來簡化分布式(shi)(shi)(shi)系(xi)統的(de)(de)(de)(de)(de)構建。近期(qi)涌現出的(de)(de)(de)(de)(de) "微(wei)服務(wu)" 一詞,也可以(yi)描(miao)(miao)述我們(men)在本(ben)文(wen)中(zhong)討論的(de)(de)(de)(de)(de)組(zu)(zu)件(jian)(jian)(jian)類型。
網絡(luo)組(zu)件的標(biao)準化管(guan)理(li)(li)接口(kou)概念至少可以追(zhui)溯到 SNMP 時代,而 SNMP 主要關(guan)注于硬(ying)件組(zu)件的管(guan)理(li)(li),還沒(mei)有(you)(you)出(chu)現(xian)負責管(guan)理(li)(li)基于微(wei)服(fu)務或容(rong)器的系(xi)統(tong)的標(biao)準。但這并沒(mei)有(you)(you)阻礙多種多樣(yang)的容(rong)器管(guan)理(li)(li)系(xi)統(tong)的發展,比如 Aurora、ECS、Docker Swarm、Kubernetes、Marathon 和 Nomad 等。
我們在第5節中提(ti)到(dao)的所(suo)有分布式(shi)系統(tong)設計模(mo)式(shi)都有很長(chang)的歷史。你可以在 Github 上找到(dao)許多(duo)領導者選舉模(mo)式(shi)的實(shi)現,盡管它們看起來像(xiang)是類庫而(er)不是獨立的組(zu)件(jian)。也(ye)有許多(duo)流(liu)行的工作隊列(lie)實(shi)現,包括 Celery 和 Amazon SQS。分散/收集模(mo)式(shi)已(yi)被識別為一種企業級系統(tong)集成模(mo)式(shi)。
7 結論
正如(ru)面(mian)(mian)向(xiang)(xiang)對(dui)象(xiang)(xiang)(xiang)(xiang)編(bian)程(cheng)(cheng)引出(chu)了(le)(le)面(mian)(mian)向(xiang)(xiang)對(dui)象(xiang)(xiang)(xiang)(xiang)"設計(ji)模(mo)式(shi)"和(he)代碼范(fan)式(shi),我們(men)也看到基(ji)于(yu)容(rong)器(qi)的(de)(de)(de)架(jia)構(gou)也引出(chu)了(le)(le)基(ji)于(yu)容(rong)器(qi)的(de)(de)(de)分(fen)布式(shi)系(xi)統(tong)(tong)設計(ji)模(mo)式(shi)。在(zai)本文中(zhong),我們(men)識(shi)別了(le)(le)三種(zhong)類型(xing)的(de)(de)(de)模(mo)式(shi):用(yong)于(yu)系(xi)統(tong)(tong)管(guan)理的(de)(de)(de)單容(rong)器(qi)模(mo)式(shi)、用(yong)于(yu)容(rong)器(qi)間緊(jin)密協作(zuo)的(de)(de)(de)單節點(dian)模(mo)式(shi)和(he)用(yong)于(yu)分(fen)布式(shi)算法的(de)(de)(de)多(duo)節點(dian)模(mo)式(shi)。在(zai)這些模(mo)式(shi)中(zhong),容(rong)器(qi)提供了(le)(le)許多(duo)與面(mian)(mian)向(xiang)(xiang)對(dui)象(xiang)(xiang)(xiang)(xiang)系(xi)統(tong)(tong)中(zhong)的(de)(de)(de)"對(dui)象(xiang)(xiang)(xiang)(xiang)"相(xiang)同(tong)的(de)(de)(de)益處(chu),例(li)如(ru)可以(yi)方便地(di)(di)在(zai)多(duo)個團(tuan)隊之間劃分(fen)應(ying)用(yong)實現,在(zai)新的(de)(de)(de)上下文中(zhong)復用(yong)組件等。此外,它(ta)(ta)們(men)還為分(fen)布式(shi)系(xi)統(tong)(tong)提供了(le)(le)一(yi)些獨特的(de)(de)(de)好處(chu),比如(ru)可以(yi)獨立地(di)(di)升級組件,可以(yi)用(yong)多(duo)種(zhong)語言編(bian)寫組件,還可以(yi)讓整個系(xi)統(tong)(tong)優雅地(di)(di)降級。我們(men)相(xiang)信,容(rong)器(qi)模(mo)式(shi)將會持(chi)續不斷(duan)的(de)(de)(de)擴充,在(zai)未來(lai)的(de)(de)(de)幾年里,就像面(mian)(mian)向(xiang)(xiang)對(dui)象(xiang)(xiang)(xiang)(xiang)編(bian)程(cheng)(cheng)在(zai)幾十年前所做的(de)(de)(de)那樣,通過對(dui)分(fen)布式(shi)系(xi)統(tong)(tong)開發(fa)的(de)(de)(de)標準化和(he)規(gui)范(fan)化,它(ta)(ta)們(men)將帶來(lai)分(fen)布式(shi)系(xi)統(tong)(tong)編(bian)程(cheng)(cheng)的(de)(de)(de)革命性變化。
8 鳴謝
想(xiang)法不會憑空(kong)出現在我們的腦海里,本文的工作受到了(le) Brian Grant、Tim Hockin、Joe Beda 和 Craig McLuckie 深深地影響。
參考文獻
- [1] Docker Engine //www.docker.com
- [2] rkt: a security-minded standards-based container engine //coreos.com/rkt/
- [3] Erich Gamma, John Vlissides, Ralph Johnson, Richard Helm, Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, Massachusetts, 1994.
- [4] Jeffrey Dean, Sanjay Ghemawat, MapReduce: Simplified Data Processing on Large Clusters, Sixth Symposium on Operating System Design and Implementation, San Francisco, CA 2004.
- [5] Apache Hadoop, //hadoop.apache.org
- [6] Kubernetes, //kubernetes.io
- [7] Apache Aurora, //aurora.apache.org.
- [8] Marathon: A cluster-wide init and control system for services, //mesosphere.github.io/marathon/
- [9] Managing the Activity Lifecycle, //developer.android.com/training/basics/activitylifecycle/index.html
- [10] Brendan Burns, The Distributed System ToolKit: Patterns for Composite Containers, //blog.kubernetes.io/2015/06/the-distributedsystem-toolkit-patterns.html
- [11] Nomad by Hashicorp, //www.nomadproject.io/
- [12] Gregor Hohpe, Enterprise Integration Patterns, Addison-Wesley, Massachusetts, 2004.
- [13] Celery: Distributed Task Queue, //www.celeryproject.org/
- [14] Amazon Simple Queue Service, //aws.amazon.com/sqs/
- [15] //www.kernel.org/doc/Documentation/cgroupv1/cgroups.txt
- [16] Service Oriented Architecture, //en.wikipedia.org/wiki/Serviceorientedarchitecture
- [17] Amazon EC2 Container Service, //aws.amazon.com/ecs/
- [18] Docker Swarm //docker.com/swarm
- [19] J. Case, M. Fedor, M. Schoffstall, J. Davin, A Simple Network Management Protocol (SNMP), //www.ietf.org/rfc/rfc1157.txt, 1990.
- [20] R. G. Gallager, P. A. Humblet, P. M. Spira, A distributed algorithm for minimum-weight spanning trees, ACM Transactions on Programming Languages and Systems, January, 1983.
- [21] M.J. Litzkow, M. Livny, M. W. Mutka, Condor: a hunter of idle workstations, IEEE Distributed Computing Systems, 1988.
- [22] //linuxcontainers.org/
原文地址:
聲明:本篇文章《[譯] Design patterns for container-based distributed systems》為翻譯文章,由譯者發布自博客園個人技術博客,未經作者本人同意禁止以任何的形式轉載,任何自動的或人為的爬蟲轉載行為均為耍流氓。
