不久前,我終于決定深入到微服務(wù)的世界了。我確實(shí)花了相當(dāng)長(zhǎng)的時(shí)間尋找使用這種架構(gòu)模式的機(jī)會(huì),并最終找到了。在經(jīng)過(guò)三個(gè)月的嘗試和學(xué)習(xí),其中大部分都是自學(xué)(困難的方式),我相信是時(shí)候分享一些經(jīng)驗(yàn)了。
他從講述一些核心的系統(tǒng)設(shè)計(jì)方面開始,其中包括API管理(gateway)。他引入了“服務(wù)總線”的概念,而沒有真的定義它。他還討論了存儲(chǔ)服務(wù)的添加:
[...] 為了在只讀數(shù)據(jù)庫(kù)(這里就是CQRS一類的東西)中存儲(chǔ)對(duì)象,你很可能需要訂閱所有類型的事件,像UserCreated和InvoicePaid等等。然后你需要與特定的(微)服務(wù)通信獲取數(shù)據(jù),然后將它存入數(shù)據(jù)庫(kù)中。在這種場(chǎng)景下,你的API需要負(fù)責(zé)訂閱事件、映射數(shù)據(jù)和保存數(shù)據(jù)到數(shù)據(jù)庫(kù)。這有問(wèn)題嗎? 多數(shù)情況下當(dāng)然沒有。但是,我更傾向于下述解決方案。它將API和微服務(wù)完全分離。這樣,就出現(xiàn)了所謂的存儲(chǔ)服務(wù),由它來(lái)訂閱事件,從(微)服務(wù)獲取數(shù)據(jù)等等。存儲(chǔ)服務(wù)知道怎樣扁平化數(shù)據(jù)。API只需要給存儲(chǔ)服務(wù)發(fā)送HTTP請(qǐng)求來(lái)獲取數(shù)據(jù)。它并不需要關(guān)心數(shù)據(jù)是從哪里來(lái)的,是內(nèi)部的數(shù)據(jù)庫(kù),還是緩存,還是處于天涯海角的某個(gè)服務(wù)。
最后在給出他的經(jīng)驗(yàn)和教訓(xùn)(他稱為“小貼士和竅門”)之前, 他用對(duì)服務(wù)的定義總結(jié)了設(shè)計(jì)方面。服務(wù)的部分定義包括:
每個(gè)(微)服務(wù)處理自己的領(lǐng)域模型、倉(cāng)庫(kù)、業(yè)務(wù)邏輯等等。整個(gè)基礎(chǔ)服務(wù)唯一共有的是服務(wù)總線和一套命令和事件集合。
那么回到小貼士和竅門。我們這里只包含其中一部分。對(duì)那些認(rèn)為微服務(wù)的大小重要的人,首先是“讓服務(wù)盡量小”。
創(chuàng)建多個(gè)小型的專注于單一領(lǐng)域的微服務(wù)比創(chuàng)建少量臃腫的執(zhí)行完全不同任務(wù)、在相同的范圍內(nèi)管理不相干職責(zé)的微服務(wù)要好。最常見的例子有:創(chuàng)建/驗(yàn)證用戶賬戶、 發(fā)送消息、管理產(chǎn)品、處理支付等等。每個(gè)領(lǐng)域納入到單獨(dú)的有獨(dú)特實(shí)體的服務(wù)中。
從別人對(duì)微服務(wù)、事件溯源和CQRS的說(shuō)法展開,Piotr認(rèn)為CQRS至關(guān)重要:
遵循CQRS,你需要做的全部事情是發(fā)送無(wú)返回值的命令和執(zhí)行冪等的查詢。如果你遵循這一模式,你會(huì)很快發(fā)現(xiàn)擴(kuò)展應(yīng)用程序簡(jiǎn)單多了,只需要分離讀寫操作。
接下來(lái)回到數(shù)據(jù)。為服務(wù)選擇數(shù)據(jù)庫(kù)的方式至關(guān)重要。這再次和其他人討論的相似:
每個(gè)服務(wù)(不是單個(gè)服務(wù)實(shí)例,因?yàn)槟憧赡苡性S多同一服務(wù)的實(shí)例運(yùn)行在不同的節(jié)點(diǎn)上)都應(yīng)該有自己的數(shù)據(jù)庫(kù)。這樣你不僅能消除單點(diǎn)故障(整個(gè)系統(tǒng)使用單一的龐大數(shù)據(jù)庫(kù)) ,最重要的是還能自由選擇最適合特定任務(wù)的數(shù)據(jù)庫(kù)。你可能想使用SQL執(zhí)行嚴(yán)重依賴事務(wù)的金融操作,或者使用NoSQL數(shù)據(jù)庫(kù)存儲(chǔ)數(shù)十億JSON文檔。
Piotr提到了其它一些事情,如請(qǐng)求追蹤(他舉例說(shuō)明了在他的學(xué)習(xí)之旅中的實(shí)現(xiàn)方法 )、使用異步消息方法(使用HTTP)、確保新服務(wù)易于部署(可能隱晦地引用到持續(xù)集成和持續(xù)部署)以及編寫端到端測(cè)試。最后提到的是“包含故障恢復(fù)、服務(wù)發(fā)現(xiàn)和其它一些有用的機(jī)制"。
任何時(shí)候出錯(cuò)了,你可能希望保證整個(gè)系統(tǒng)不會(huì)崩潰或者至少其中一部分不會(huì)崩潰。確保你引入了重試機(jī)制(比如Polly)、服務(wù)發(fā)現(xiàn)工具,如Consul以及集中保存證書,比如使用Vault、Azure Key Vault或者我的開源項(xiàng)目Lockbox。
Piotr討論的大部分和過(guò)去這些年別人說(shuō)的非常相似,所以在使用微服務(wù)開發(fā)時(shí)我們很可能正趨向一個(gè)關(guān)于方法有效還是無(wú)效的共識(shí)。但是需要注意的是,盡管Piotr討論了他的一些經(jīng)驗(yàn)和教訓(xùn),但是沒有任何關(guān)于他開發(fā)的應(yīng)用程序表現(xiàn)如何的說(shuō)明(負(fù)載下擴(kuò)展、恢復(fù)能力等等)??赡芎笃跁?huì)有,我們拭目以待。