小型系統如何“微服務”開發

猿天地發表於2019-01-07

提到 “微服務”,我相信網上各種“微服務”的演變案例都會給人一種 “因大而分” 的前提錯覺,這可能會導致許多的 “小白” 產生沒有機會接觸 “大專案” 而對 “微服務” 可望而不可及也。

當然,這種錯覺的產生可能更多來源自於各種 “微技術” 的 “層出不窮” 所以“眼花繚亂”,例如Spring Cloud。雖然 “大專案” 機會不多,但也阻止不了 “釘子們” 透過教程把微技術跑一遍來裝飾自己可以 “微” 起來的自信。

小型系統如何“微服務”開發

“微”只是一種正常思維邏輯

想當年,入行如趕集,同樣作為小白,能把SSH框架跑一遍竟然能給自己帶來無比強大的工作自信。誰沒個“資本”年齡,只可惜自身的“浮躁”逼退了當年追求“本質”的淡定和沉穩。

在網網際網路嶄露頭角的年代,系統的焦點可能不在於“單體”應用的“橫向分佈”,更多在於對整體業務的“豎向分層”。

無論橫分還是豎分,“分”的本質其實就是因為“重”。“分而治之”應該算是人類最基本的思維邏輯。

只不過“分”的具體實現還得歸咎於站在我們對立面的是什麼問題。

網際網路是把“業務”從線下往線上遷移的主要推力,在這個網際網路初始發展階段,需要體現的可能是線上業務的完整性,因此業務的厚度成為了瓶頸,所以對業務邏輯層次的垂直劃分可能是當時的關鍵解。

隨著移動網際網路的普及,“線上業務”已經成為主流,業務的“厚重”已經積累到了另外一種層次,單純的“豎向分層”已經無法滿足厚重業務的積累和支撐。

業務橫向分解成為了突破口。大量“分散式”方案油然而生,包括“微服務”。

從許多“大而微”的初始現象來看,確實很容易把“大”和“微”聯絡在一起,這也是“大”企業走在時代前沿面對“不確定性機會”所“創造”的現象。

歷史可以很輕易地給人一種“知其所行”的大局視野,但時代演員卻很容易被侷限當前。

我個人覺得“微服務”的本質就是一種正常的思維,是一種基本解決問題的思路。

“微服務”並非新招式,跟二十六種常用物件導向設計模式一樣,隨著時代經驗的積累會成為我們解決問題的“基準招式”。

因此也可以大概推測,未來的發展離不開“微服務”思維模式的導向,例如專案或組織的管理模式都可能會發生變化,或者說已經在悄悄地改變。

如果說“微服務”確實像我分析的是一種思維模式,那就不會有大專案和小專案之分了。

小型系統如何“微服務”開發

“微服務”模式小案例

在工作過程中,大專案畢竟少數,小專案才是考驗技術人“接地氣”的表現所在。有一天,我接到了一個小規模的“話費充值系統”需求,沒有太多複雜功能和邏輯的描述,就是一個能讓使用者在上面自助充值的系統。剩下的理解,靠的就是自身工作經驗的功力了。面對這樣的需求,我首先想到的就是這個關鍵業務流程:

小型系統如何“微服務”開發

這個流程說簡單可以簡單,說複雜可以“媲美”電商系統,例如“充值金額”相當於商品,“充值”相當於購物,“訂單”跑不掉,“充值話費”類比物流。各種電商該有的“邊界問題”幾乎都要考慮,規模雖小,但五臟都得要有。至於“五臟”有哪些,這得根據業務的邊界範圍去劃分“業務領域”了,先來根據自己的經驗嘗試一把:

小型系統如何“微服務”開發

這種業務劃分方式多少跟電商系統有點類似,直接呈現的是業務模型。根據“微服務”思維,每個領域都是一個獨立的服務個體單元,每個服務“物件”又有自己的“屬性”和“行為”:

小型系統如何“微服務”開發

每個服務的屬性有“服務標識”、“服務名稱”等,當然服務有自身的各種行為(更多以API體現),各種系統外部動作都是透過服務之間的“合作”來完成:

小型系統如何“微服務”開發

使用者檢視充值金額:接查詢商品服務(“充值10元到賬12元”,“充值100元到賬106元”,......);

使用者發起話費充值:訂單服務接收請求→訂單服務查詢商品資訊(商品ID)→訂單服務向支付服務下支付訂單→訂單服務向充值服務下充值訂單→訂單服務自身下商品訂單;

使用者支付:支付閘道器(外圍)接受請求→回撥支付服務通知支付結果→支付服務更新支付訂單狀態→支付服務向充值服務發起充值→充值服務向充值閘道器(外圍)發起充值並更改充值訂單狀態;

訂單對賬:定時支付閘道器對賬、定時充值訂單對賬:

小型系統如何“微服務”開發

從以上流程可以看出,每個服務都有自己專注的“職能”,每個應用業務流程有需要1或N個服務的互動才能完成,每個服務都有自己獨立的“資料來源”,互不干擾。由於系統的初期規模預期比較小,可能每天就那麼數百筆訂單甚至可能更少,如果我們每個服務都需要“物理隔離”,未免有點大題小做。因此,專案初期我們按“單體”模式實施:

小型系統如何“微服務”開發

所謂的“單體”,即把所有服務程式碼結合一個“專案”打包釋出,也就是一個“普通”的專案並且共用一個資料庫,但每個服務的表名都有服務的標識(約定),例如商品服務的相關表名以“KW_GOODS_XXX”命名,訂單服務的相關表名以“KW_ORDER_XXX”命名,支付服務的相關表名以“KW_PAYMENT_XXX”命名,充值服務的相關表名以“KW_RECHARGE_XXX”命名,對賬服務的相關表名以“KW_ACCOUNT_XXX”命名,服務之間決不能跨越服務運算元據庫表,必須按照“業務流程設計”呼叫,所以“單體”只是體現在物理實施層面,邏輯層面始終保持著“微服務”的分散式特性,保留了各種不用修改一行程式碼即可靈活擴充套件的可能性:

小型系統如何“微服務”開發

可能有人會問,“單體”模式的服務呼叫怎麼調?“分散式”模式又是怎麼調?怎麼確保擴充套件時服務程式碼呼叫層面的不變?用的是什麼技術?這篇隨筆就先不談太多的技術,服務的呼叫過程我大概透過虛擬碼圖術一下:

小型系統如何“微服務”開發

服務之間協作的“透明化”關鍵在於把“微服務”靈活特性所導致的“變化”打包封裝起來,就是以上虛擬碼的DiscoveryClient呼叫代理。DiscoveryClient在技術框架內維護了所有服務的資訊(Service Data Cache Container),而服務資訊的載入方式是服務解耦的關鍵所在。

首先,框架透過本地掃描的方式把所有本地服務資訊掃描並載入至“服務容器”(本地掃描LocalService)。其次,框架會檢測本地的“服務資訊”配置檔案並載入至容器(靜態解析)。

最後,框架會根據配置前兩步所載入的服務資訊判斷是否存在“發現中心服務”並動態地週期性向“發現中心”更新服務資訊(動態解析)。因此,無論是單體應用部署還是分散式應用部署,對服務呼叫是透明的,保留了整個系統的靈活擴充套件性。到這裡,整個系統的設計基本完,完整的系統架構圖如下所示:

小型系統如何“微服務”開發

以上系統在無任何優惠的正常執行下,確實只能算得上小規模,一臺伺服器的單體部署模式足以支撐,但在每月會員日所推出“充100元送10元”商品的時候,單體應用就顯得有點力力不從心了,商品服務訪問量的增加(看得人多了)已經影響到了其它服務的穩定性,並且考慮對賬的穩定性(以免充值不到賬引起投訴),決定把商品服務和對賬服務獨立(程式)部署。透過加入閘道器(Nginx)進行服務分發(服務解耦):

小型系統如何“微服務”開發

在運營過程中,公司為了“流量經營”,不惜下血本推出“充100元送50元”的商品,系統再一次受到嚴峻的考驗,為了業務質量,不得不把所有服務獨立(程式)部署,增加支撐力度:

小型系統如何“微服務”開發

不知道是不是老闆喝多了還是運營短路了,竟然提個“充值100元送100元”的商品,並明天上線,系統峰值支撐併發量的預測已經超出了我的想象力,我能做的只有這樣了:

小型系統如何“微服務”開發

系統從業務規模來看確實存在大小之分,但從設計思想層面,系統是沒有大小之分。以上“戲路”都是以服務為單元進行靈活擴充套件,其實業務的最小力度是服務的具體行為—API,每個API都是服務的一個獨立行為,例如查詢、變更等,完全符合“命令查詢職責分離(CQRS)模式”的設計,按服務這種API粒度進行橫向分解同樣可行,例如“支付服務”存在支付訂單查詢API、支付訂單下單API、支付結果通知接收API,我們可以透過讀寫特性把查詢API和變更類API進行分離,同樣可以以面向“消費物件”的角度進行分解:

小型系統如何“微服務”開發

如果某些業務存在服務鏈複雜的話(例如商品訂單),還可以自定義“編排服務”解耦“基礎服務”的複雜度:

小型系統如何“微服務”開發


學習總結

如果細心點可以從以上案例發現,我的整個專案開發過程跟傳統的可能會有點區別,什麼區別呢?

這裡沒有突出太多的實體物件設計或者表結構設計,更沒有突出所謂的“三層結構”設計,而是直接從業務角度觸發劃分“業務物件”,而我們的服務呈現的是根據業務領域劃分的“物件”描述,與傳統按“資料實體”劃分的設計模式還是有一定的區別,從需求設計到軟體設計和開發都是“業務模型”最原始和最直觀的呈現,保證了業務準確性並減少了變更的風險成本,同還大大地降低了專案的溝通成本。這種思想有一個更加專業的術語叫“領域驅動設計”。

我深知自己距離所謂的“微服務”或者“領域驅動設計”還有一大段距離,並且以上案例還可能存在諸多的細節問題,但這種類似的思想確實是我自身從業務中摸爬滾打併逐步思考和沉澱而形成的設計習慣。

不是別人說什麼就做什麼,而是透過實踐去思考和領悟並向真正的源頭“大師們”學習。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31561268/viewspace-2374671/,如需轉載,請註明出處,否則將追究法律責任。

相關文章