用Kong突破單一數(shù)據(jù)庫
譯文【51CTO.com快譯】您一定對RESTful API并不陌生吧。它為客戶端應(yīng)用提供了一種能夠滿足業(yè)務(wù)需求的、訪問數(shù)據(jù)資源的簡單方式。事實上,Angular、React和Vue等都是依賴RESTful API的Javascript框架,它們引領(lǐng)著Web應(yīng)用的市場。
從效果上說,此類RESTful服務(wù)類型的API和前端Javascript框架模式的配合,激發(fā)了許多組織從單一(monolithic)或過時的應(yīng)用程序,遷移到新項目中的愿望。當(dāng)然,凡事都有利與弊,RESTful API在助推敏捷迭代式開發(fā)的同時,也帶來了一個問題:在傳統(tǒng)的應(yīng)用設(shè)計中,我們雖然可以使用多個RESTful API和Javascript框架的組件化客戶端,但是也使用著單一的數(shù)據(jù)庫。這種設(shè)計的結(jié)果往往會導(dǎo)致數(shù)據(jù)所有權(quán)的沖突、高于預(yù)期的數(shù)據(jù)庫連接數(shù)、以及對大型數(shù)據(jù)庫過高的支持與維護(hù)成本。
下圖展示了多個服務(wù)競爭來自單個數(shù)據(jù)庫資源的情況:
而且,此類現(xiàn)象在開發(fā)領(lǐng)域十分常見。大家會傾向于將單個數(shù)據(jù)庫作用并服務(wù)于整個微服務(wù)的集合。
微服務(wù)應(yīng)該從數(shù)據(jù)庫開始
在大多數(shù)編程語言中,我們通??梢允褂脝蝹€的文件,去創(chuàng)建功能齊全的應(yīng)用程序。例如在Java中,一切都可以被放置在同一個類的文件中,并且由簡單的main()方法實現(xiàn)統(tǒng)領(lǐng)和調(diào)用:
- Java
- public class SingleClassApplication {
- public static void main(String[] args) {
- // Start doing something really cool here
- }
- }
但是,這種方法并不利于多個開發(fā)人員通過協(xié)作的方式貢獻(xiàn)代碼。就應(yīng)用程序的各個方面而言,我們需要關(guān)注“所有權(quán)”(或系統(tǒng)記錄)的概念。如果不止一項服務(wù)或功能對賬戶等組件存在著交叉所有權(quán)的話,那么我們的業(yè)務(wù)規(guī)則可能會在不同的場景下出現(xiàn)混亂的局面。例如,在RESTful API聲明對于某個給定對象的所有權(quán)時,就可能發(fā)生類似的情況。而且,當(dāng)我們采取RESTful API的設(shè)計模式時,這些概念都需要被轉(zhuǎn)化到數(shù)據(jù)庫的層面上。對此,我們需要遵從如下規(guī)則:
將單個RESTful API視為某個應(yīng)用在給定方面的記錄系統(tǒng)(system of record),以便相應(yīng)的數(shù)據(jù)層僅專注和使用應(yīng)用在該方面的數(shù)據(jù)存儲。
下圖展示了遵循該規(guī)則的微服務(wù)設(shè)計:
據(jù)此,那些為了滿足客戶需求,而對給定服務(wù)采取的擴(kuò)展,不會對任何其他的服務(wù)產(chǎn)生影響。這便是優(yōu)秀的、針對微服務(wù)的數(shù)據(jù)庫設(shè)計實踐。
數(shù)據(jù)庫的各種約束
在開發(fā)過程中,我力推將給定的微服務(wù)與專用數(shù)據(jù)庫相隔離。這能夠保證相關(guān)組件的數(shù)量和大小,能夠與用戶需求相匹配,同時避免具有不同需求水平的元素產(chǎn)生額外的成本。
數(shù)據(jù)庫管理員往往會發(fā)現(xiàn),當(dāng)應(yīng)用程序的所有元素都駐留在單個數(shù)據(jù)庫中時,各種約束和關(guān)系能夠很好地在單個數(shù)據(jù)庫的設(shè)計模式中發(fā)揮作用。例如,如果有與客戶相關(guān)聯(lián)的訂單在排隊等待刪除的話,那么單一數(shù)據(jù)庫的設(shè)計就會阻止刪除某個客戶的請求,畢竟該用戶的訂單尚未“結(jié)清”。
雖然這絕對是擁有單個數(shù)據(jù)庫的好處,但在選擇為所有微服務(wù)使用單個數(shù)據(jù)庫之前,您需要考慮如下幾點(diǎn):
- 將使用單個數(shù)據(jù)庫可能獲得的長期價值,與擴(kuò)展單個大型數(shù)據(jù)庫的相關(guān)成本進(jìn)行比較,以了解未來擴(kuò)展和支持單一數(shù)據(jù)庫設(shè)計的預(yù)期成本。
- 在API層強(qiáng)制實施各類約束的利與弊。請記住,由于單個微服務(wù)將被視為給定數(shù)據(jù)庫的所有者,因此在業(yè)務(wù)邏輯上可能會出現(xiàn)上述提到的,不允許刪除帶有活躍訂單的客戶的情況。
- 對于事件驅(qū)動(或基于消息)的設(shè)計而言,某個微服務(wù)如何處理請求,取決于來自另一個微服務(wù)的響應(yīng)情況。雖然這與單個應(yīng)用程序+單個數(shù)據(jù)庫的設(shè)計有著相似之處,但需要在隔離和控制時,具有一定的擴(kuò)展和分配專用處理算力的能力。
當(dāng)然,做為一種良好的開發(fā)習(xí)慣,即使是數(shù)據(jù)庫僅支持某個專用的服務(wù)實例,我們也應(yīng)該實施和強(qiáng)制執(zhí)行對應(yīng)的約束關(guān)系。
公共元素應(yīng)該被抽象出來
如果規(guī)劃不當(dāng),采用真正的微服務(wù)設(shè)計也可能會產(chǎn)生副作用。例如在微服務(wù)中,包括認(rèn)證、緩存、日志記錄、監(jiān)控、以及安全在內(nèi)的各個公共組件元素,可能會與服務(wù)層相重復(fù)。
如上圖所示,在軟件開發(fā)的生命周期中,人們往往會用不同的語言,去重復(fù)相同的軟件模式。對此,我們需要通過在應(yīng)用程序棧的公共級別、或不同級別,抽象和處理某些元素,來盡可能地避免DRY(不要重復(fù)自己)。在此,我推薦使用Kong的情況,進(jìn)而提供分布式的微服務(wù)抽象層。
將Kong置于理想的設(shè)計中心
Kong Gateway(允許開發(fā)者將服務(wù)層API的復(fù)雜性,降低到專注于滿足業(yè)務(wù)需求和功能集合的各個端點(diǎn)(或 URI)處。由網(wǎng)關(guān)處理的諸如:身份驗證、日志記錄和安全性等重復(fù)性組件,可以被Kong Gateway從服務(wù)層的設(shè)計中移出。
如下圖所示,每個RESTful微服務(wù)都維護(hù)著一個專用的數(shù)據(jù)庫實例,并且抽象出了各個重復(fù)的組件。這里所展示的便是一組以目的為驅(qū)動(purpose-driven)的微服務(wù):
開發(fā)人員可以通過使用各種常見的企業(yè)集成模式(enterprise integration patterns)的消息傳遞層來,去處理服務(wù)間的通信,其中包括:
- 命令消息- 調(diào)用另一個服務(wù)來執(zhí)行后臺操作
- 文檔消息- 從另一個服務(wù)處請求信息
- 事件消息- 向偵聽給定主題的任何一方,廣播信息
- 請求-回復(fù)- 向另一個服務(wù)發(fā)出請求,并偵聽響應(yīng)
這樣的設(shè)計會給我們的應(yīng)用開發(fā)帶來如下好處:
- 如果Node.js服務(wù)的使用率高于預(yù)期的話,則可以通過擴(kuò)展,來低成本地實現(xiàn)服務(wù)與專用數(shù)據(jù)庫的相互隔離。
- 如果任何服務(wù)發(fā)現(xiàn)了數(shù)據(jù)存儲模式從SQL更改為NoSQL,則可以在不更改RESTful API的URI的前提下,部署新的設(shè)計,而不會對任何其他服務(wù)產(chǎn)生影響。
- 任何抽象層組件的更改(例如,使用新的日志記錄方法)都可以在Kong Gateway層進(jìn)行,而不會影響到底層服務(wù)。
小結(jié)
開發(fā)人員往往利用包和類,來對他們的程序代碼進(jìn)行分組,以實現(xiàn)可支持性和可維護(hù)性。在這些類中,定義方法和函數(shù)的規(guī)則是,每個代碼塊應(yīng)當(dāng)小且易于理解。這也正是“微服務(wù)”的“微”字的體現(xiàn)。其實不只是微服務(wù),程序員也需要讓數(shù)據(jù)庫持續(xù)以微小、高效、以及目標(biāo)驅(qū)動的方式進(jìn)行擴(kuò)展。
通過上述討論可知,Kong真正為微服務(wù)的設(shè)計提供了可擴(kuò)展、且易于采用的核心方式。而Kong Gateway則允許開發(fā)人員引入通用組件,并駐留在分布式微服務(wù)的抽象層,以實現(xiàn)DRY。
原文標(biāo)題:Breaking Up a Monolithic Database with Kong,作者:John Vester
【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請注明原文譯者和出處為51CTO.com】