服務架構:微服務架構
作者:趙帥虎
微服務架構是由很多小而自治的微服務組合而成,每個服務都提供一套獨立自洽的業務能力。微服務的定義比較直白,但只有理解它的設計理念和原則,才能真正用好它。
微服務架構是由很多小而自治的微服務組合而成,每個服務都提供一套獨立自洽的業務能力。從應用的層面,我們首先對業務進行建模,業務域定義的邊界也自然而然作為每個微服務的職能邊界。
什么是微服務?
微服務的定義比較直白,但只有理解它的設計理念和原則,才能真正用好它。從單個服務/服務間關系來看,有以下特征:
- 微服務通常很小、提供很少但獨立的功能,服務間耦合度很低。一個很小的研發團隊就可以開發和維護一個微服務。
- 每個服務都是一個單獨的代碼庫,可以由一個很小的研發團隊來管理。
- 服務可以獨立部署,而不需要重新構建和部署整個應用。
- 每個服務負責維護自己的數據和狀態,數據所有權歸本服務所有,其他服務必須通過該服務訪問數據和狀態。
- 服務之間通過定義好的API進行通信,對外隱藏API的內部實現細節。
- 支持多語言編程,不同服務可以使用獨立的技術棧進行開發,自由選擇編程語言、框架和庫。
如果從更全局的視角來看,微服務架構還必須下面幾個組件:
- 服務管理和編排。該組件負責把服務部署在物理機/虛擬機節點上、做失敗檢查、在多個節點上負責對服務的多個實例做負載均衡等。我們通常可以使用現成的開源技術來充當這個組件,比如k8s。
- API Gateway。API Gateway給所有Client提供了訪問入口。Client通常不會直接訪問提供業務支持的服務,而是調用API Gateway,由Gateway負責把請求轉發給后端對應的服務。
使用 API Gateway 有很多優勢:
- 解耦Client和服務,我們可以單獨對服務進行更新或重構,client端可能不需要更新甚至不需要感知。
- 服務間通信可以使用更靈活的方式,比如不走HTTP協議,而是走rpc等二進制協議、消息隊列等,某些超大數據量的場景甚至會走p2p協議。
- API Gateway可以承擔一些跨業務的職能,比如權限認證、日志、SSL校驗、負載均衡等。
- API Gateway一般會提供一些開箱即用的能力,比如限流、緩存、請求篡改、權限校驗等。
架構優勢
- 支持敏捷迭代。由于微服務可以獨立部署,所以修復bug和上線新特性也更容易。你可以獨立更新特定的服務,而不是重新部署整個應用,如果更新出現問題,也支持快速回滾。在傳統應用中,一旦在應用的某個環節發現問題,整個發布流程都要被阻塞。新特性也可以等著bug修復后再去測試和發布。
- 小而專的研發團隊。微服務可以很小,小到一個獨立的小團隊iu可以構建、測試和阿布。小團隊非常適合推行敏捷迭代流程。往往大型團隊的生產力更弱一些,因為溝通滿,管理成本上升,由此也不適合再推行敏捷迭代。
- 代碼庫小。在大型單體應用中,隨著時間推移,代碼依賴越來越復雜。增加新特性意味著要改很多地方的代碼。由于不共享代碼和數據,微服務架構將依賴最小化,部署新特性也更容易。
- 可以融合使用多種技術。團隊成員可以選擇最適合服務的技術,并在適當的情況下混合使用多個技術棧。
- 故障隔離。如果一個特定的微服務掛掉了,只要上游微服務在設計時考慮到容災處理,通常不會影響整個應用的正常功能。比如,采用適當的熔斷機制,或者服務間通信走異步消息隊列。
- 架構擴展性好。每個服務都可以單獨進行擴容,這樣的話,我們就能獨立擴容需要更多資源的子系統,而不是整個應用。使用K8s等對服務進行編排,我們可以把多個服務的實例部署在同一臺機器上,以提高資源利用率。
- 原生支持服務間的數據隔離。如果要更新數據的schema,只有單個服務受到影響。在單體應用中,更新schema往往不太容易,因為應用的多個模塊都會通過庫依賴的形式訪問數據,在更新時,很難追蹤到所有使用的地方和使用方式,導致schema的迭代有很多未知的風險。
有哪些挑戰
微服務的架構優勢是有代價的,在采用微服務架構之前,我們要認識到未來可能面臨的挑戰:
- 架構復雜度高。相對于單體應用,微服務應用有很多可變的組件。每個服務都更簡單了,但整個系統變得更復雜了。
- 開發和測試麻煩,尤其是集成測試。在實現一個微服務時,如果它依賴了其他服務,編寫和測試過程都會比單體應用更復雜。現存的工具在設計時可能并未考慮到服務依賴。如果我們要對相互依賴的多個服務進行重構,難度也會比重構單體應用高。在測試時,涉及到服務依賴,需要單獨維護多套與線上相似的測試環境。考慮到每個服務都有多個測試版本,迭代比較快時,很容易出問題。
- 互相獨立的服務,很難做治理。由于微服務以區中心化的方式去構建各個服務,在服務治理上增加了額外的難度。最終整個應用中可能包含多個編程語言,使用了多種框架,開發人員可以更自由地選擇小眾的技術,導致后期維護成本反而更高。
- 容易產生網絡擁塞和延遲。很多小且功能獨立的服務需要通過API或消息隊列繼續頻繁的通信。由于底層走網卡進行通信,對比單體架構的代碼庫依賴,網絡通信的代價可能很高。當服務的依賴鏈很長時,比如 A調用B,B調用C,C調用...,額外的網絡延遲會高到無法接受。所以在設計服務時,需要慎重考慮API的設計,應避免過度繁瑣的API,考慮到編碼格式(二進制協議優于文本協議),優先使用異步通信模式或消息隊列模式;
- 跨服務的數據一致性問題。每個微服務負責自身的數據持久化,導致多個服務的數據可能存在不一致。通常我們使用最終一致性原則解決這些問題;
- 服務管理難度高。微服務架構的成功采用離不開成熟的DevOps文化。處理跨服務的日志追蹤,尤其是一個用戶操作觸發整個鏈路的微服務調用,日志都要記錄下來,并且在發生錯誤時,能夠把整個調用鏈的日志拉取出來;
- 服務的發布版本管理。在更新服務時,不能對API做破壞性的更新,否則依賴它的服務可能會掛掉。由于多個開發團隊在同一時間段可能都要對服務做更新,所以接口設計必須保持向前或向后兼容。一個典型的低級錯誤是:刪除了API定義的某些字段,或修改了某些字段的業務含義;
- 要求研發團隊懂分布式系統。微服務通常是分布式的,需要認真評估團隊是否具備對應的能力和經驗;
最佳實踐
- 基于業務場景對服務進行建模;
- 盡量去中心化。每個團隊都要負責設計和構建服務,避免分享代碼或底層數據結構。
- 數據存儲只允許單個服務訪問,每個服務根據自己的業務需求設計選擇存儲方案和數據格式。
- 服務間通過設計良好的API進行通信,應盡量避免透露實現細節。API的定義應當基于業務場景進行設計,而不是根據內部的技術實現進行設計。
- 避免服務間的耦合。服務間耦合的原因通常是把數據庫schema透傳給外部,或通信協議彈性比較差。
- 將跨業務域的需求交給API Gateway來處理,比如身份認證、SSL驗證。
- 保持API Gateway的純粹性,不摻入業務邏輯。API Gateway只處理和轉發client側的請求,不感知任何業務邏輯。否則API Gateway將成為一個依賴,導致服務間的耦合。
- 服務間應該高內聚、低耦合。應該一起變化的邏輯應該被打包到一個服務里,統一部署。如果他們分散在不同的服務里,這些服務將高度耦合在一起,一個服務的更新也將連鎖導致另一個服務的更新。兩個服務間繁瑣的通信是“高耦合低內聚”的體現。
- 故障隔離。應當采取一定的恢復策略,以避免一個服務的故障引發連鎖反應。
責任編輯:姜華
來源:
今日頭條