?微服務(wù)?分布式系統(tǒng)?服務(wù)網(wǎng)?模式?
自從幾十年前分布式系統(tǒng)被首次提出询微,我們了解到分布式系統(tǒng)能夠?qū)崿F(xiàn)在這之前我們甚至沒(méi)有想到過(guò)的用例,但它們也會(huì)引入各種新問(wèn)題缅刽。
當(dāng)這些系統(tǒng)很少且簡(jiǎn)單時(shí)围橡,工程師通過(guò)盡量少遠(yuǎn)程交互來(lái)應(yīng)對(duì)分布式帶來(lái)的復(fù)雜性。處理分布式最安全的方法是盡可能地避免它战坤,即使這意味著跨各種系統(tǒng)的重復(fù)邏輯和冗余數(shù)據(jù)。
但是残拐,行業(yè)各種需求途茫,從一些較大的中央計(jì)算機(jī)到成百上千的小型服務(wù),一直在推動(dòng)我們往前溪食。在這個(gè)新世界中囊卜,我們必須開(kāi)始擺脫困境,應(yīng)對(duì)新挑戰(zhàn)和開(kāi)放性問(wèn)題错沃,首先是以個(gè)案方式完成臨時(shí)解決方案栅组,然后再采用更復(fù)雜的方法。隨著我們更多地了解問(wèn)題域并設(shè)計(jì)出更好的解決方案枢析,我們開(kāi)始將一些最常見(jiàn)的需求納入模式笑窜,庫(kù),和最終納入平臺(tái)登疗。
我們剛開(kāi)始聯(lián)網(wǎng)計(jì)算機(jī)時(shí)發(fā)生了什么
關(guān)于兩臺(tái)或兩臺(tái)以上的計(jì)算機(jī)相互通信排截,人們首先設(shè)想到如下圖:
服務(wù)與另一個(gè)服務(wù)通信以實(shí)現(xiàn)用戶的某個(gè)目標(biāo)。上述是一個(gè)簡(jiǎn)化視圖辐益,沒(méi)有包括諸如字節(jié)編解碼断傲、線路上發(fā)送和接收的電信號(hào)等層。盡管如此智政,如上抽象視圖仍能滿足我們?nèi)缦碌挠懻撊险帧W屛覀儗⒕W(wǎng)絡(luò)堆棧作為一個(gè)獨(dú)立的組件來(lái)顯示以添加更多細(xì)節(jié):
自20世紀(jì)50年代以來(lái),上述模型的多種變體沿用至今续捂。最初垦垂,計(jì)算機(jī)少且貴宦搬,因此兩個(gè)節(jié)點(diǎn)間的連接都經(jīng)過(guò)精心設(shè)計(jì)和維護(hù)。隨著計(jì)算機(jī)變得越來(lái)越便宜和越來(lái)越流行劫拗,節(jié)點(diǎn)間的連接及其上傳輸?shù)臄?shù)據(jù)量急劇增加间校。隨著人們?cè)絹?lái)越依賴網(wǎng)絡(luò)系統(tǒng),工程師需要確保他們構(gòu)建的軟件符合用戶的服務(wù)質(zhì)量要求页慷。
為了達(dá)到理想的質(zhì)量水平憔足,還有許多問(wèn)題亟需解決。機(jī)器怎么發(fā)現(xiàn)彼此酒繁,同一條線路如何處理多個(gè)連接滓彰,機(jī)器間未直連時(shí)如何相互通信,如何在網(wǎng)絡(luò)上路由數(shù)據(jù)包州袒、加密流量等揭绑。
我們以上述問(wèn)題中的流量控制為例。流量控制是防止一臺(tái)上游服務(wù)器發(fā)送的數(shù)據(jù)包超出下游服務(wù)器可處理極限的一種機(jī)制郎哭。這種機(jī)制是非常必要的他匪,在網(wǎng)絡(luò)系統(tǒng)中,至少有兩臺(tái)不同的彰居、獨(dú)立且彼此間互不了解的計(jì)算機(jī)诚纸,計(jì)算機(jī)A以給定的速率向計(jì)算機(jī)B發(fā)送字節(jié)撰筷,但B不能保證以穩(wěn)定且足夠快的速度處理接收到的字節(jié)陈惰,因?yàn)锽可能并行運(yùn)行著其他任務(wù),或數(shù)據(jù)包無(wú)序到達(dá)毕籽,B阻塞等待最先應(yīng)到的數(shù)據(jù)包抬闯。這意味著B(niǎo)不僅可能達(dá)不到A期望的性能,甚至可能比那更糟关筒,過(guò)載使得B必須將所有接收到的數(shù)據(jù)包進(jìn)行排隊(duì)處理溶握。
有一段時(shí)間,人們期望構(gòu)建網(wǎng)絡(luò)服務(wù)或應(yīng)用程序的開(kāi)發(fā)人員會(huì)在他們編寫(xiě)的代碼中處理上面提到的問(wèn)題蒸播,在流量控制示例中睡榆,意味著應(yīng)用程序本身必須包含邏輯以確保不會(huì)發(fā)送過(guò)多的包至下游服務(wù)。業(yè)務(wù)代碼包含大量網(wǎng)絡(luò)處理相關(guān)邏輯袍榆。在我們的抽象圖中胀屿,它將是這樣的:
幸運(yùn)的是,技術(shù)迅速發(fā)展包雀,很快就有標(biāo)準(zhǔn)協(xié)議如TCP/IP將流控制和許多其他問(wèn)題納入網(wǎng)絡(luò)堆棧本身宿崭。這意味著相關(guān)邏輯從應(yīng)用程序下沉到操作系統(tǒng)提供的底層網(wǎng)絡(luò)層:
這種模式非常成功。即便需要高性能和高可靠才写,也只有非常少的組織無(wú)法僅使用商用操作系統(tǒng)自帶的TCP/IP堆棧來(lái)驅(qū)動(dòng)業(yè)務(wù)發(fā)展葡兑。
當(dāng)我們第一次開(kāi)始使用微服務(wù)時(shí)發(fā)生了什么
多年來(lái)奖蔓,計(jì)算機(jī)變得更加便宜和無(wú)所不在,上述網(wǎng)絡(luò)堆棧模型已經(jīng)被證明是構(gòu)建可靠連接系統(tǒng)事實(shí)上的工具集讹堤。隨著越來(lái)越多節(jié)點(diǎn)和穩(wěn)定的連接吆鹤,業(yè)界使用了多種類(lèi)型的網(wǎng)絡(luò)系統(tǒng),從細(xì)粒度的分布式agents蜕劝、對(duì)象到由重量級(jí)分布式組件組成的面向服務(wù)的體系結(jié)構(gòu)檀头。
這種極端分布式帶來(lái)了許多有趣的高級(jí)用例和好處,但也帶來(lái)了一些挑戰(zhàn)岖沛,其中一些挑戰(zhàn)是全新的暑始,但剩下的只是我們?cè)谠季W(wǎng)絡(luò)時(shí)所遇到的挑戰(zhàn)的更高級(jí)的版本而已。
在90年代婴削,Peter Deutsch和他在Sun Microsystems的工程師同事一起編寫(xiě)了“分布式計(jì)算的8個(gè)謬誤”廊镜,其中列出了人們?cè)谑褂梅植际较到y(tǒng)時(shí)所做的一些錯(cuò)誤假設(shè),Pete的觀點(diǎn)是唉俗,在更原始的網(wǎng)絡(luò)架構(gòu)或理論模型中嗤朴,這些假設(shè)可能是真的,但它們?cè)诂F(xiàn)代世界中并不成立:
- 網(wǎng)絡(luò)可靠
- 延遲為零
- 帶寬是無(wú)限的
- 網(wǎng)絡(luò)是安全的
- 拓?fù)洳粫?huì)改變
- 有一個(gè)管理員
- 運(yùn)輸成本為零
- 網(wǎng)絡(luò)是同質(zhì)的
將上述列表作為“謬誤”意味著工程師不能忽視這些問(wèn)題虫溜,他們必須明確地處理它們雹姊。
更加分布式的系統(tǒng)即微服務(wù)架構(gòu)-在可操作性方面引入了新的需求-使事情進(jìn)一步復(fù)雜化。我們之前詳細(xì)討論了其中一些衡楞,如下簡(jiǎn)要列出其中一些必須處理的內(nèi)容:
- 快速獲取計(jì)算資源
- 基本監(jiān)控
- 快速部署
- 輕松獲取存儲(chǔ)資源
- 輕松接入邊緣網(wǎng)關(guān)
- 認(rèn)證/授權(quán)
- 標(biāo)準(zhǔn)化的RPC
因此吱雏,雖然幾十年前開(kāi)發(fā)的TCP/IP堆棧和通用網(wǎng)絡(luò)模型仍然是計(jì)算機(jī)間相互通信的強(qiáng)大工具,但更復(fù)雜的架構(gòu)引入了另一層需求瘾境,在這種架構(gòu)下開(kāi)發(fā)人員必須實(shí)現(xiàn)這些需求歧杏。
例如,服務(wù)發(fā)現(xiàn)和斷路器迷守,這兩種技術(shù)用于解決上面提到的彈性和分布挑戰(zhàn)犬绒。
歷史往往會(huì)重演,第一批基于微服務(wù)架構(gòu)構(gòu)建系統(tǒng)的組織遵循的策略兑凿,與前幾代構(gòu)建網(wǎng)絡(luò)通信的策略非常相似凯力。即意味著處理上述需求的責(zé)任由編寫(xiě)服務(wù)的工程師負(fù)責(zé)。
服務(wù)發(fā)現(xiàn)礼华,是一個(gè)自動(dòng)查找服務(wù)實(shí)例的進(jìn)程咐鹤,該服務(wù)實(shí)例能響應(yīng)給定請(qǐng)求,例如卓嫂,Teams
服務(wù)需要查找一個(gè)帶environment=production
屬性的Players
服務(wù)實(shí)例慷暂,您將調(diào)用一些服務(wù)發(fā)現(xiàn)進(jìn)程,該進(jìn)程將返回部署運(yùn)行了相應(yīng)實(shí)例的服務(wù)器的列表。對(duì)于更加單體的結(jié)構(gòu)行瑞,通常使用DNS奸腺、負(fù)載平衡器(如nginx、F5)和一些約定的端口號(hào)(例如血久,所有服務(wù)將其HTTP服務(wù)器綁定到端口8080)實(shí)現(xiàn)這個(gè)簡(jiǎn)單任務(wù)突照。在更加分布式的環(huán)境中,這個(gè)任務(wù)變得更加復(fù)雜氧吐,前一種方式讹蘑,服務(wù)可以盲目信任DNS服務(wù)器查找到其所依賴的服務(wù),而現(xiàn)在必須處理client-side負(fù)載平衡筑舅、多套不同運(yùn)行環(huán)境(例如座慰,分段與生產(chǎn))、地理位置分散的服務(wù)器等翠拣。以前只需一行代碼來(lái)解析主機(jī)名版仔,現(xiàn)在服務(wù)需要多行樣板代碼來(lái)處理更加分散所引入的各種極端情況。
斷路器是Michael Nygard在他的書(shū)Release It中編目的一種模式误墓。我喜歡Martin Fowler對(duì)斷路器模式的總結(jié):
斷路器背后的基本思想非常簡(jiǎn)單蛮粮。將受保護(hù)的函數(shù)調(diào)用包裝在斷路器對(duì)象中,該對(duì)象監(jiān)視故障谜慌。一旦故障達(dá)到某個(gè)閾值然想,斷路器就會(huì)跳閘,并且所有對(duì)斷路器的進(jìn)一步調(diào)用都會(huì)直接返回錯(cuò)誤欣范,而不會(huì)對(duì)受保護(hù)函數(shù)進(jìn)行調(diào)用变泄。通常,如果斷路器跳閘了熙卡,您還需要某種監(jiān)控告警杖刷。
這些簡(jiǎn)單的設(shè)備可以提升服務(wù)間交互的可靠性励饵。然而驳癌,隨著分布式水平的提升,它們往往變得更加復(fù)雜役听。系統(tǒng)中出現(xiàn)問(wèn)題的可能性隨著分布呈指數(shù)級(jí)增長(zhǎng)颓鲜,因此即使是“斷路器跳閘時(shí)某種監(jiān)視器告警”等簡(jiǎn)單的事情也不一定是直截了當(dāng)?shù)摹R粋€(gè)組件中的一個(gè)故障可以在許多客戶端和客戶端的客戶端間產(chǎn)生一系列影響典予,同時(shí)觸發(fā)數(shù)千個(gè)電路跳閘甜滨。過(guò)去只需幾行代碼的東西現(xiàn)在需要大量的樣板代碼來(lái)處理。
實(shí)際上瘤袖,上面提到的服務(wù)發(fā)現(xiàn)和斷路器很難被正確實(shí)現(xiàn)衣摩,所以像Twitter的Finagle和Facebook的Proxygen這樣的大型復(fù)雜類(lèi)庫(kù)變得非常流行,用以避免在每個(gè)服務(wù)中重寫(xiě)相同邏輯捂敌。
大多數(shù)開(kāi)發(fā)微服務(wù)架構(gòu)服務(wù)的組織如Netflix艾扮,Twitter和SoundCloud既琴,遵從如上描述的模型。隨著他們系統(tǒng)中服務(wù)數(shù)量的增長(zhǎng)泡嘴,他們也發(fā)現(xiàn)了這種方式的缺點(diǎn)甫恩。
- 最大的挑戰(zhàn)可能是,即使使用像Finagle這樣的類(lèi)庫(kù)酌予,組織仍然需要其工程團(tuán)隊(duì)投入時(shí)間來(lái)構(gòu)建膠水代碼以粘合類(lèi)庫(kù)與現(xiàn)有生態(tài)系統(tǒng)磺箕。根據(jù)我在SoundCloud和DigitalOcean的經(jīng)驗(yàn),估計(jì)在一個(gè)100至250個(gè)工程師的組織中抛虫,若要遵循這一策略松靡,需要抽取1/10的員工專(zhuān)門(mén)用于構(gòu)建這些工具。有時(shí)這種成本是明確的建椰,根據(jù)專(zhuān)門(mén)構(gòu)建工具的工程師人數(shù)即可評(píng)估击困,但花費(fèi)在產(chǎn)品上的時(shí)間更多是不可見(jiàn)的。
- 第二個(gè)問(wèn)題是上述模型限制了用于微服務(wù)的工具广凸、運(yùn)行時(shí)和開(kāi)發(fā)語(yǔ)言阅茶。微服務(wù)的類(lèi)庫(kù)通常是針對(duì)特定平臺(tái)編寫(xiě)的,無(wú)論是針對(duì)編程語(yǔ)言還是針對(duì)一個(gè)運(yùn)行時(shí)如JVM谅海。如果組織使用的是非類(lèi)庫(kù)支持的平臺(tái)脸哀,則通常需要將相關(guān)代碼移植到新平臺(tái),這消耗了工程寶貴的時(shí)間扭吁。工程師不再只需聚焦核心業(yè)務(wù)和產(chǎn)品撞蜂,而需同時(shí)構(gòu)建工具和基礎(chǔ)架構(gòu)。這就是為什么像SoundCloud和DigitalOcean這樣的中型組織決定其內(nèi)部服務(wù)只支持Scala或Go其中之一個(gè)平臺(tái)侥袜。
- 上述模型最后一個(gè)值得討論的問(wèn)題是治理蝌诡。類(lèi)庫(kù)模型可能會(huì)抽象實(shí)現(xiàn)微服務(wù)架構(gòu)所需特性,但它本身仍然是一個(gè)需要維護(hù)的組件枫吧。確保成千上萬(wàn)的服務(wù)實(shí)例使用相同或至少兼容的庫(kù)版本并非易事浦旱,每次更新都意味著集成、測(cè)試和重新部署所有服務(wù) - 即使服務(wù)本身沒(méi)有任何更改九杂。
下一個(gè)邏輯步驟
與我們?cè)诰W(wǎng)絡(luò)堆棧中看到的類(lèi)似颁湖,將大規(guī)模分布式服務(wù)所需的通用功能提取到底層平臺(tái)是非常有必要的。
人們使用更高級(jí)別的協(xié)議(如HTTP)編寫(xiě)非常復(fù)雜的應(yīng)用程序和服務(wù)例隆,而不用考慮TCP如何控制其網(wǎng)絡(luò)上的數(shù)據(jù)包甥捺。在微服務(wù)開(kāi)發(fā)中,希望也能這樣镀层,從事服務(wù)開(kāi)發(fā)的工程師可以只專(zhuān)注于他們的業(yè)務(wù)邏輯镰禾,而不浪費(fèi)時(shí)間編寫(xiě)自己的服務(wù)基礎(chǔ)架構(gòu)代碼或管理跨服務(wù)的庫(kù)和框架。
將這個(gè)想法融入我們的圖表中,我們最終可能會(huì)遇到以下情況:
遺憾的是吴侦,更改網(wǎng)絡(luò)堆棧以添加此層是一項(xiàng)不可行的任務(wù)谷饿。許多從業(yè)者采用的解決方案是將其作為一組代理實(shí)現(xiàn),服務(wù)不直連到它的下游依賴項(xiàng)妈倔,而是將所有流量都通過(guò)一小塊軟件透明地傳遞出去博投,以此添加所需的功能。
在這個(gè)里提出sidecars概念盯蝴,sidecars是一個(gè)輔助進(jìn)程毅哗,與服務(wù)一起運(yùn)行并為其提供額外的功能。2013年捧挺,Airbnb撰寫(xiě)了關(guān)于Synapse和Nerve的文章虑绵,他們開(kāi)源實(shí)現(xiàn)的sidecars。一年后闽烙,Netflix推出了Prana翅睛,這是一款專(zhuān)用于非JVM應(yīng)用程序連接NetflixOSS生態(tài)系統(tǒng)中的sidecars。在SoundCloud黑竞,我們構(gòu)建了sidecars捕发,使我們的Ruby遺留系統(tǒng)能夠使用我們?yōu)镴VM微服務(wù)構(gòu)建的基礎(chǔ)架構(gòu)。
雖然有如上幾種開(kāi)源代理實(shí)現(xiàn)很魂,但它們往往設(shè)計(jì)用于特定的基礎(chǔ)架構(gòu)組件扎酷。例如,當(dāng)涉及到服務(wù)發(fā)現(xiàn)時(shí)遏匆,Airbnb的Nerve&Synapse假設(shè)服務(wù)注冊(cè)在Zookeeper中法挨,而對(duì)于Prana,應(yīng)該使用Netflix的Eureka服務(wù)注冊(cè)表幅聘。
隨著微服務(wù)架構(gòu)的日益普及凡纳,我們最近看到了新的代理浪潮,其靈活性足以適應(yīng)不同的基礎(chǔ)架構(gòu)組件和偏好帝蒿。這個(gè)領(lǐng)域的第一個(gè)廣為人知的系統(tǒng)是Linkerd荐糜,由Buoyant根據(jù)他們的工程師在Twitter的微服務(wù)平臺(tái)上的先前工作創(chuàng)建。很快陵叽,Lyft的工程團(tuán)隊(duì)宣布Envoy遵循類(lèi)似的原則狞尔。
服務(wù)網(wǎng)格
在這種模型中丛版,每個(gè)服務(wù)都將有配套代理sidecar巩掺。服務(wù)僅通過(guò)sidecar代理相互通信,我們最終得到類(lèi)似于下圖的部署:
Buoyant首席執(zhí)行官威廉·摩根(William Morgan)觀察到proxy之間的互聯(lián)形成了一個(gè)網(wǎng)狀網(wǎng)絡(luò)页畦。在2017年初胖替,William為這個(gè)平臺(tái)寫(xiě)了一個(gè)定義,稱之為Service Mesh:
服務(wù)網(wǎng)格是用于處理服務(wù)到服務(wù)通信的專(zhuān)用基礎(chǔ)設(shè)施層。負(fù)責(zé)復(fù)雜服務(wù)拓?fù)渲蟹?wù)(包括云原生應(yīng)用)間請(qǐng)求的可靠傳遞独令。實(shí)際上端朵,服務(wù)網(wǎng)格通常實(shí)現(xiàn)為一組輕量級(jí)網(wǎng)絡(luò)代理,這些代理與應(yīng)用程序代碼一起部署燃箭,而無(wú)需知道應(yīng)用程序冲呢。
可能他關(guān)于服務(wù)網(wǎng)格的定義中最重要的方面是,不再將代理視為孤立的組件招狸,并承認(rèn)它們形成的網(wǎng)絡(luò)本身就是有價(jià)值的東西敬拓。
隨著越來(lái)越多的組織將其微服務(wù)部署遷移到更復(fù)雜的運(yùn)行時(shí)如Kubernetes和Mesos,這些組織已經(jīng)開(kāi)始使用這些平臺(tái)所提供的工具來(lái)正確實(shí)現(xiàn)網(wǎng)狀網(wǎng)絡(luò)理念裙戏。模式由一組獨(dú)立且孤立地工作的的proxy節(jié)點(diǎn)乘凸,轉(zhuǎn)向適當(dāng)?shù)摹⒂悬c(diǎn)集中式的累榜、帶控制平面的模式营勤。
。
查看我們的鳥(niǎo)瞰圖壹罚,我們看到實(shí)際的服務(wù)流量仍然直接從proxy流向proxy葛作,但控制平面知道每個(gè)proxy實(shí)例〔荩控制平面使proxy能夠?qū)崿F(xiàn)訪問(wèn)控制和度量收集等操作:
最近宣布的Istio項(xiàng)目是此類(lèi)系統(tǒng)最突出的例子进鸠。
現(xiàn)在要完全理解服務(wù)網(wǎng)格在大規(guī)模系統(tǒng)中的影響還為時(shí)尚早。這種方法的兩個(gè)好處對(duì)我來(lái)說(shuō)已經(jīng)很明顯了形病。首先客年,不必編寫(xiě)代碼對(duì)接微服務(wù)架構(gòu)基礎(chǔ)代碼,即可讓許多小型組織享受以前只有大型企業(yè)可用的功能漠吻,從而創(chuàng)建各種有趣的用例量瓜。第二個(gè)是這個(gè)架構(gòu)可能讓我們最終實(shí)現(xiàn)使用最佳工具/語(yǔ)言的夢(mèng)想,而不必?fù)?dān)心每個(gè)平臺(tái)的庫(kù)和模式的可用性途乃。
致謝
Monica Farrell绍傲,Rodrigo Kumpera,Etel Sverdlov耍共,Dave Worth烫饼,Mauricio Linhares,Daniel Bryant试读,Fabio Kung和Carlos Villela對(duì)本文的草稿進(jìn)行了反饋杠纵。
修訂記錄
· 2017年3月3日 - 首次發(fā)布
· 2017年8月5日 - 合并反饋
翻譯自:https://philcalcado.com/2017/08/03/pattern_service_mesh.html