設(shè)計(jì)微服務(wù)架構(gòu)前應(yīng)該了解的5項(xiàng)指導(dǎo)原則
*** CTO 基于五個簡單的原則為精心設(shè)計(jì)的微服務(wù)提供建議。
對于從微服務(wù)開始的團(tuán)隊(duì)來說,***的挑戰(zhàn)之一就是堅(jiān)持金發(fā)女孩原則(該典故來自于童話《金發(fā)姑娘和三只熊》):不要太大,不要太小,不能太緊密耦合。之所以是挑戰(zhàn)的部分原因是會對究竟什么是設(shè)計(jì)良好的微服務(wù)感到疑惑。
數(shù)十位 CTO 通過采訪分享了他們的經(jīng)驗(yàn),這些對話說明了設(shè)計(jì)良好的微服務(wù)的五個特點(diǎn)。本文將幫助指導(dǎo)團(tuán)隊(duì)設(shè)計(jì)微服務(wù)。(有關(guān)詳細(xì)信息,請查看即將出版的書籍 Microservices for Startups,LCTT 譯注:已可免費(fèi)下載完整的電子版)。本文將簡要介紹微服務(wù)的邊界和主觀的 “規(guī)則”,以避免在深入了解五個特征之前就開始指導(dǎo)您的微服務(wù)設(shè)計(jì)。
微服務(wù)邊界
使用微服務(wù)開發(fā)新系統(tǒng)的核心優(yōu)勢之一是該體系結(jié)構(gòu)允許開發(fā)人員獨(dú)立構(gòu)建和修改各個組件,但在***限度地減少每個 API 之間的回調(diào)數(shù)量方面可能會出現(xiàn)問題。根據(jù) SparkPost 工程副總裁 Chris McFadden 所說,解決方案是應(yīng)用適當(dāng)?shù)姆?wù)邊界。
關(guān)于邊界,與有時難以理解和抽象的領(lǐng)域驅(qū)動設(shè)計(jì)(DDD,一種微服務(wù)框架)形成鮮明對比,本文重點(diǎn)介紹了和我們行業(yè)的一些*** CTO 一同建立的明確定義的微服務(wù)邊界的實(shí)用原則。
避免主觀的 “規(guī)則”
如果您閱讀了足夠多的關(guān)于設(shè)計(jì)和創(chuàng)建微服務(wù)的建議,您一定會遇到下面的一些 “規(guī)則”。 盡管將它們用作創(chuàng)建微服務(wù)的指南很有吸引力,但加入這些主觀規(guī)則并不是思考確定微服務(wù)的邊界的原則性方式。
“微服務(wù)應(yīng)該有 X 行代碼”
讓我們直說:微服務(wù)中有多少行代碼沒有限制。微服務(wù)不會因?yàn)槟鷮懥藥仔蓄~外的代碼而突然變成一個獨(dú)石應(yīng)用。關(guān)鍵是要確保服務(wù)中的代碼具有很高的內(nèi)聚性(稍后將對此進(jìn)行更多介紹)。
“將每個功能轉(zhuǎn)換為微服務(wù)”
如果函數(shù)基于三個輸入值計(jì)算某些內(nèi)容并返回結(jié)果,它是否是微服務(wù)的理想候選項(xiàng)?它是否應(yīng)該是單獨(dú)可部署應(yīng)用程序?這確實(shí)取決于該函數(shù)是什么以及它是如何服務(wù)于整個系統(tǒng)。將每個函數(shù)轉(zhuǎn)換為微服務(wù)在您的情景中可能根本沒有意義。
其他主觀規(guī)則包括不考慮整個情景的規(guī)則,例如團(tuán)隊(duì)的經(jīng)驗(yàn)、DevOps 能力、服務(wù)正在執(zhí)行的操作以及數(shù)據(jù)的可用性需求。
精心設(shè)計(jì)的服務(wù)的 5 個特點(diǎn)
如果您讀過關(guān)于微服務(wù)的文章,您無疑會遇到有關(guān)設(shè)計(jì)良好的服務(wù)的建議。簡單地說,高內(nèi)聚和低耦合。如果您不熟悉這些概念,有許多文章關(guān)于這些概念的文章。雖然它們提供了合理的建議,但這些概念是相當(dāng)抽象的?;谂c經(jīng)驗(yàn)豐富的 CTO 們的對話,下面是在創(chuàng)建設(shè)計(jì)良好的微服務(wù)時需要牢記的關(guān)鍵特征。
#1:不與其他服務(wù)共享數(shù)據(jù)庫表
在 SparkPost 的早期,Chris McFadden 和他的團(tuán)隊(duì)必須解決每個 SaaS 業(yè)務(wù)需要面對的問題:它們需要提供基本服務(wù),如身份驗(yàn)證、帳戶管理和計(jì)費(fèi)。
為了解決這個問題,他們創(chuàng)建了兩個微服務(wù):用戶 API 和帳戶 API。用戶 API 將處理用戶帳戶、API 密鑰和身份驗(yàn)證,而帳戶 API 將處理所有與計(jì)費(fèi)相關(guān)的邏輯。這是一個非常合乎邏輯的分離 —— 但沒過多久,他們發(fā)現(xiàn)了一個問題。
McFadden 解釋說,“我們有一個名為‘用戶 API’的服務(wù),還有一個名為‘帳戶 API’的服務(wù)。問題是,他們之間實(shí)際上有幾個來回的調(diào)用。因此,您會在帳戶服務(wù)中執(zhí)行一些操作,然后調(diào)用并終止于用戶服務(wù),反之亦然”
這兩個服務(wù)的耦合太緊密了。
在設(shè)計(jì)微服務(wù)時,如果您有多個服務(wù)引用同一個表,則它是一個危險的信號,因?yàn)檫@可能意味著您的數(shù)據(jù)庫是耦合的源頭。
這確實(shí)是關(guān)于服務(wù)與數(shù)據(jù)的關(guān)系,這正是 Swiftype SRE,Elastic 的負(fù)責(zé)人 Oleksiy Kovrin 告訴我。他說,“我們在開發(fā)新服務(wù)時使用的主要基本原則之一是,它們不應(yīng)跨越數(shù)據(jù)庫邊界。每個服務(wù)都應(yīng)依賴于自己的一組底層數(shù)據(jù)存儲。這使我們能夠集中訪問控制、審計(jì)日志記錄、緩存邏輯等。”
Kovrin 接著解釋說,如果數(shù)據(jù)庫表的某個子集“與數(shù)據(jù)集的其余部分沒有或很少連接,則這是一個強(qiáng)烈的信號,表明該組件可以被隔離到單獨(dú)的 API 或單獨(dú)的服務(wù)中”。
Lead Honestly 的聯(lián)合創(chuàng)始人 Darby Frey 與此的觀點(diǎn)相呼應(yīng):“每個服務(wù)都應(yīng)該有自己的表并且永遠(yuǎn)不應(yīng)該共享數(shù)據(jù)庫表。”
#2:數(shù)據(jù)庫表數(shù)量最小化
微服務(wù)的理想尺寸應(yīng)該足夠小,但不能太小。每個服務(wù)的數(shù)據(jù)庫表的數(shù)量也是如此。
Scaylr 的工程主管 Steven Czerwinski 在接受采訪時解釋說 Scaylr 的***選擇是“一個或兩個服務(wù)的數(shù)據(jù)庫表。”
SparkPost 的 Chris McFadden 表示同意:“我們有一個 suppression 微服務(wù),它處理、跟蹤數(shù)以百萬計(jì)和數(shù)十億圍繞 suppression 的條目,但它們都非常專注于圍繞 suppression,所以實(shí)際上只有一個或兩個表。其他服務(wù)也是如此,比如 webhooks。
#3:考慮有狀態(tài)和無狀態(tài)
在設(shè)計(jì)微服務(wù)時,您需要問問自己它是否需要訪問數(shù)據(jù)庫,或者它是否是處理 TB 級數(shù)據(jù) (如電子郵件或日志) 的無狀態(tài)服務(wù)。
Algolia 的 CTO Julien Lemoine 解釋說:“我們通過定義服務(wù)的輸入和輸出來定義服務(wù)的邊界。有時服務(wù)是網(wǎng)絡(luò) API,但它也可能是使用文件并在數(shù)據(jù)庫中生成記錄的進(jìn)程 (這就是我們的日志處理服務(wù))。”
事先要明確是否有狀態(tài),這將引導(dǎo)一個更好的服務(wù)設(shè)計(jì)。
#4:考慮數(shù)據(jù)可用性需求
在設(shè)計(jì)微服務(wù)時,請記住哪些服務(wù)將依賴于此新服務(wù),以及在該數(shù)據(jù)不可用時的整個系統(tǒng)的影響??紤]到這一點(diǎn),您可以正確地設(shè)計(jì)此服務(wù)的數(shù)據(jù)備份和恢復(fù)系統(tǒng)。
Steven Czerwinski 提到,在 Scaylr 由于關(guān)鍵客戶行空間映射數(shù)據(jù)的重要性,它將以不同的方式復(fù)制和分離。
相比之下,他補(bǔ)充說,“每個分片信息,都在自己的小分區(qū)里。如果部分客戶群體因?yàn)闆]有可用日志而停止服務(wù)那很糟糕,但它只影響 5% 的客戶,而不是100% 的客戶。”
#5:單一的真實(shí)來源
設(shè)計(jì)服務(wù),使其成為系統(tǒng)中某些內(nèi)容的唯一真實(shí)來源。
例如,當(dāng)您從電子商務(wù)網(wǎng)站訂購內(nèi)容時,則會生成訂單 ID,其他服務(wù)可以使用此訂單 ID 來查詢訂單服務(wù),以獲取有關(guān)訂單的完整信息。使用 發(fā)布/訂閱模式,在服務(wù)之間傳遞的數(shù)據(jù)應(yīng)該是訂單 ID ,而不是訂單本身的屬性信息。只有訂單服務(wù)具有訂單的完整信息,并且是給定訂單信息的唯一真實(shí)來源。
大型團(tuán)隊(duì)的注意事項(xiàng)
考慮到上面列出的五個注意事項(xiàng),較大的團(tuán)隊(duì)?wèi)?yīng)了解其組織結(jié)構(gòu)對微服務(wù)邊界的影響。
對于較大的組織,整個團(tuán)隊(duì)可以專門擁有服務(wù),在確定服務(wù)邊界時,組織性就會發(fā)揮作用。還有兩個需要考慮的因素:獨(dú)立的發(fā)布計(jì)劃和不同的正常運(yùn)行時間的重要性。
Cloud66. 的 CEO Khash Sajadi 說:“我們所看到的微服務(wù)最成功的實(shí)現(xiàn)要么基于類似領(lǐng)域驅(qū)動設(shè)計(jì)這樣的軟件設(shè)計(jì)原則 (如面向服務(wù)的體系結(jié)構(gòu)),要么基于反映組織方法的設(shè)計(jì)原則。”
“所以 (對于) 支付團(tuán)隊(duì)” Sajadi 說,“他們有支付服務(wù)或信用卡驗(yàn)證服務(wù),這就是他們向外界提供的服務(wù)。所以這不一定是關(guān)于軟件的。這主要是關(guān)于為外界提供更多服務(wù)的業(yè)務(wù)單位。”
雙披薩原理
Amazon 是一個擁有多個團(tuán)隊(duì)的大型組織的***示例。正如在一篇發(fā)表于 API Evangelist 的文章中所提到的,Jeff Bezos 向所有員工發(fā)布一項(xiàng)要求,告知他們公司內(nèi)的每個團(tuán)隊(duì)都必須通過 API 進(jìn)行溝通。任何不這樣做的人都會被解雇。
這樣,所有數(shù)據(jù)和功能都通過該接口公開。Bezos 還設(shè)法讓每個團(tuán)隊(duì)解耦,定義他們的資源,并通過 API 提供。Amazon 正在從頭建立一個系統(tǒng)。這使得公司內(nèi)的每一支團(tuán)隊(duì)都能成為彼此的合作伙伴。
我與 Iron.io 的 CTO Travis Reeder 談到了 Bezos 的內(nèi)部倡議。
“Jeff Bezos 規(guī)定所有團(tuán)隊(duì)都必須構(gòu)建 API 才能與其他團(tuán)隊(duì)進(jìn)行溝通,” Reeder 說。“他也是提出‘雙披薩’規(guī)則的人:一支團(tuán)隊(duì)不應(yīng)該比兩個比薩餅?zāi)莛B(yǎng)活的大。”
“我認(rèn)為這里也可以適用同樣的方法:無論一個小型團(tuán)隊(duì)是否能夠開發(fā)、管理和富有成效。如果它開始變得笨重或開始變慢,它可能變得太大了。” Reeder 告訴我。
***注意事項(xiàng): 您的服務(wù)是否具有合適的大小和正確的定義?
在微服務(wù)系統(tǒng)的測試和實(shí)施階段,有一些指標(biāo)需要記住。
指標(biāo) #1: 服務(wù)之間是否存在過度依賴?
如果兩個服務(wù)不斷地相互回調(diào),那么這就是強(qiáng)烈的耦合信號,也是它們可能更好地合并為一個服務(wù)的信號。
回到 Chris McFadden 的例子, 他有兩個 API 服務(wù),帳戶服務(wù)和用戶服務(wù)不斷地相互通信, McFadden 提出了一個合并服務(wù)的想法,并決定將其稱為 “賬戶用戶 API”。事實(shí)證明,這是一項(xiàng)富有成效的戰(zhàn)略。
“我們開始做的是消除這些內(nèi)部 API 之間調(diào)用的鏈接,” McFadden 告訴我。“這有助于簡化代碼。”
指標(biāo) #2: 設(shè)置服務(wù)的開銷是否超過了服務(wù)獨(dú)立的好處?
Darby Frey 解釋說,“每個應(yīng)用都需要將其日志聚合到某個位置,并需要進(jìn)行監(jiān)視。你需要設(shè)置它的警報。你需要有標(biāo)準(zhǔn)的操作程序,和在出現(xiàn)問題時的操作手冊。您必須管理 SSH 對它的訪問。只是為了讓一個應(yīng)用運(yùn)行起來,就有大量的基礎(chǔ)性工作必須存在。”
關(guān)鍵要點(diǎn)
設(shè)計(jì)微服務(wù)往往會讓人感覺更像是一門藝術(shù),而不是一門科學(xué)。對工程師來說,這可能并不順利。有很多一般性的建議,但有時可能有點(diǎn)太抽象了。讓我們回顧一下在設(shè)計(jì)下一組微服務(wù)時要注意的五個具體特征:
- 不與其他服務(wù)共享數(shù)據(jù)庫表
- 數(shù)據(jù)庫表數(shù)量最小化
- 考慮有狀態(tài)和無狀態(tài)
- 考慮數(shù)據(jù)可用性需求
- 單一的真實(shí)來源
下次設(shè)計(jì)一組微服務(wù)并確定服務(wù)邊界時,回顧這些原則應(yīng)該會使任務(wù)變得更容易。