1. 程式人生 > >面向服務與微服務架構

面向服務與微服務架構

背景

最近閱讀了 Martin Fowler 和 James Lewis 合著的一篇文章 Microservices, 文中主要描述和探討了最近流行起來的一種服務架構模式——微服務,和我最近幾年工作的實踐比較相關感覺深受啟發。本文吸收了部分原文觀點,結合自身實踐經驗來探討下服務架構模式的演化。

面向服務架構(SOA)

面向服務架構 SOA 思想概念的提出已不是什麼新鮮事,大概在10年前就有不少相關書籍介紹過。當時 java 企業應用領域 J2EE 依然是主流,應用程式被部署在龐大統一的符合 J2EE 規範的容器中執行,在單一程序中提供所有的功能。 而 SOA 提出的一些架構原則,在當時看來無疑是革命性的。 由於業已存在的大量單一龐大的應用,按照 SOA 的思想和架構原則來改造無疑相當於推翻重新開發一遍,在成本上很難接受。 因此早期的 SOA 通常和另外一個術語關聯在一起——ESB(企業服務匯流排)。 當時在 SOA 的實施思路上無一例外的選擇了 ESB 模式來整合整合大量單一龐大的應用,以保護企業前期投入成本。因此 ESB 其實是 SOA 特定歷史階段的一種實現方式。

然而,願望總是美好的,現實卻要殘酷的多。過去這些年我們看到了很多實施 ESB 搞砸了的專案,投入幾百萬,產出幾乎為 0,因此 SOA 這個概念也蒙上了不詳的標籤。 近幾年流行起來的服務化架構,其擁護者開始拒絕使用包裹著失敗陰影的 SOA 這個標籤,而稱其為微服務架構(Microservices Architecture Style)。但事實上 微服務架構依然是 SOA 架構思想的一種實現。

微服務架構(Microservices)

對微服務架構我們沒有一個明確的定義,但簡單來說微服務架構是:

採用一組服務的方式來構建一個應用,服務獨立部署在不同的程序中,不同服務通過一些輕量級互動機制來通訊,例如 RPC、HTTP 等,服務可獨立擴充套件伸縮,每個服務定義了明確的邊界,不同的服務甚至可以採用不同的程式語言來實現,由獨立的團隊來維護。

微服務架構特徵(Characteristics)

1. 通過服務實現元件化
傳統實現元件的方式是通過庫(library),傳統元件是和應用一起執行在程序中,元件的區域性變化意味著整個應用的重新部署。 通過服務來實現元件,意味著將應用拆散為一系列的服務執行在不同的程序中,那麼單一服務的區域性變化只需重新部署對應的服務程序。 另外將服務作為元件可以更明確的定義出元件的邊界,因為服務之間的呼叫是跨程序的,清晰的邊界和職責定義是設計時必須考慮的。

organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations.
任何設計系統的組織,最終產生的設計等同於組織之內、之間的溝通結構。

傳統開發方式中,我們將工程師按技能專長分層為前端層、中間層、資料層,前端對應的角色為UI、頁面構建師等,中間層對應的角色為服務端業務開發工程師,資料層對應著DBA等角色。 事實上傳統應用設計架構的分層結構正反應了不同角色的溝通結構。 而微服務架構的開發模式不同於傳統方式,它將應用按業務能力來劃分為不同的服務,每個服務都要求在對應業務領域的全棧(從前端到後端)軟體實現,從介面到資料儲存到外部溝通協作等等。 因此團隊的組織是跨功能的,包含實現業務所需的全面的技能。 近年興起的全棧工程師正是因為架構和開發模式的轉變而出現,當然具備全棧的工程師其實很少,但將不同領域的工程師組織為一個全棧的團隊就容易的多。

3. 服務即產品
傳統的應用開發都是基於專案模式的,開發團隊根據一堆功能列表開發出一個軟體應用並交付給客戶後,該軟體應用就進入維護模式,由另一個維護團隊負責,開發團隊的職責結束。 而微服務架構的倡導者提議避免採用這種專案模式,更傾向於讓開發團隊負責整個產品的全部生命週期。Amazon 對此提出了一個觀點:

You buidl it, you run it.

開發團隊對軟體在生產環境的執行負全部責任,讓服務的開發者與服務的使用者(客戶)形成每天的交流反饋,來自直接客戶端的反饋有助於開發者提升服務的質量。

4. 智慧終端與啞管道
微服務架構拋棄了 ESB 過度複雜的業務規則編排、訊息路由等。 服務作為智慧終端,所有的業務智慧邏輯在服務內部處理,而服務間的通訊儘可能的輕量化,不新增任何額外的業務規則。

5. 去中心統一化
傳統應用中傾向採用統一的技術平臺或產品來解決所有問題。 不是每個問題都是釘子,也不是每個解決方案都是一個錘子。 問題有其具體性,解決方案也應有其針對性。 用最適合的技術方案去解決具體的問題,在大一統的傳統應用中其實很難做到,而微服務的架構意味著,你可以針對不同的業務服務特徵選擇不同的技術平臺或產品,有針對性的解決具體的業務問題。

6. 基礎設施自動化
單一程序的傳統應用被拆分為一系列的多程序服務後,意味著開發、除錯、測試、整合、監控和釋出的複雜度都會相應增大。 必須要有合適的自動化基礎設施來支援微服務架構模式,否則開發、運維成本將大大增加。

7. Design for failure
正因為將服務獨立在不同的程序中後,引入了額外的失敗因素。 任何時刻對服務的呼叫都可能因為服務方不可用導致失敗,這就要求服務的消費方需要優雅的處理此類錯誤。 這其實是相對傳統應用開發方式的一個缺點,不過隨著一些開源服務化框架的出現,對業務開發人員而言適當的遮蔽了類似的錯誤處理,不過開發人員依然需要知道對服務的呼叫是完全不同於程序內的方法或函式呼叫的。

8. 進化設計
一旦採用了微服務架構模式,那麼在服務需要變更時我們要特別小心,服務提供者的變更可能引發服務消費者的相容性破壞,時刻謹記保持服務契約(介面)的相容性。 對於解耦服務消費方和服務提供方,伯斯塔爾法則(Postel's law)特別適用:

Be conservative in what you send, be liberal in what you accept.
傳送時要保守,接收時要開放。

按照伯斯塔爾法則的思想來設計實現服務呼叫時,傳送的資料要更保守,意味著最小化的傳送必要的資訊,接收時更開放意味著要最大限度的容忍資訊的相容性。 多餘的資訊不認識可以忽略,而不應該拒絕或丟擲錯誤。

微服務架構應用

採用微服務架構面臨的第一個問題就是如何將一個單一應用拆分為多個服務。 有一個一般的原則是,單一服務提供的功能是可以獨立被替換和升級的。 也就是說如果有 A 和 B 兩個功能,如果 A 功能發生變化時同時 B 功能也需要變化,那麼 A 和 B 這兩個功能應該被劃在一個服務中。

微服務架構應用的成功經驗近年已越來越多,例如國外的 Amazon,Netflix,國內如阿里都採用微服務架構取得了很多正面的成功案例。 但通過上文所述微服務架構特徵看出,其實微服務架構模式有利有弊,需要根據實際的業務、團隊、環境進行仔細權衡利弊。 其中的服務拆分帶來的額外開發、測試、運維、監控的複雜度,在現有的環境、團隊下是否能夠很好的支援。

另外,有人可能會說,我一開始不採用微服務架構方式,而是在單一程序內基於清晰定義的模組化方式,模組之間通過介面呼叫,到了適當階段,必要的時候再將模組拆分為服務。 其實這個想法顯得過於理想,因為程序內良好定義的介面通常不是很好的服務化介面。 一開始沒有考慮服務化的設計方法,那麼後期拆分時依然是一個痛苦的過程。

總結

正如,Martin Fowler 在其文中所說,微服務架構是否就是企業應用開發的未來,還有待時間的檢驗。 就目前的情況看,對此我們可以保持謹慎的樂觀,這條路依然值得去探索。 實際任何的架構決策都是基於我們不完美的現狀做出的,這正是架構取捨的微妙之處,超越任何的方法論。