使用 Docker 構建微服務架構,服務與服務之間的通信有什麼最佳實踐?
基本就是
同步 - HTTP RESTFul api調用非同步 - 消息隊列, RabbitMQ之類的錯誤處理是最難的部分,有很多模式,比如circuit breaker pattern, compensation transaction pattern, retry pattern 具體可以參見這本書Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications
參考這篇文章:
「Chris Richardson 微服務系列」微服務架構中的進程間通信
具體閱讀筆記如下:
基於微服務的分散式應用是運行在多台機器上的;一般來說,每個服務實例都是一個進程。因此,如下圖所示,服務之間的交互必須通過進程間通信(IPC)來實現。
對於微服務架構的交互模式,文章從兩個維度進行了描述,即
一對一:每個客戶端請求有一個服務實例來響應。
一對多:每個客戶端請求有多個服務實例來響應。同步模式:客戶端請求需要服務端即時響應,甚至可能由於等待而阻塞。
非同步模式:客戶端請求不會阻塞進程,服務端的響應可以是非即時的。
對於分為這兩個維度進行描述意義不太大,對於同步模式往往只能是1對1,而且還需要同步等待容易引起阻塞,而對於非同步模塊往往採用消息機制來實現,同時配合消息中間件可以進一步實現消息的發布訂閱。而對於EDA事件驅動架構要看到其本質也是伊布消息中間件和消息的發布訂閱。
非同步消息機制可以做到最大化的解耦,對於數據CUD的場景可以看到是比較容易通過非同步消息機制實現的,但是會進一步引入事務一致性問題,即在採用非同步消息
機制後往往通過BASE事務最終一致性來解決事務層面的問題。而對於查詢功能可以看到是比較難通過非同步消息API實現的,在引入這個之前可以看到需要考慮
兩方面的問題並解決。
其一是服務網關需要有數據緩存能力,以解決無法從源端獲取數據的場景。其二是前端開發框架本身需要支持非同步調用和數據裝載模式,特別是對於數據查詢功能對於用戶來講,在前端的感受仍然需要時同步的。即通過非同步方式返回了查詢數據後可以動態刷新前端展示界面。
服務版本的問題:這是不可避免要遇到的問題,特別是對於RestAPI調用,由於Json格式本身無Schema返回更加容易忽視了對服務
版本的管理和控制。要知道對於Json數據格式變化仍然會導致RestAPI調用後處理失敗。因此服務版本仍然採用大小版本管理機制比較好,對於小版本變
更則直接對原有服務進行覆蓋同時對所有受影響的服務消費端進行升級;而對於大版本升級則本質是新增加了一個新服務,而對於舊版本服務逐步遷移和替代。
處理局部失敗:文中提到了Netfilix的服務解決方案,對於失敗問題的解決要注意常用的仍然是服務超時設置,斷路器機制,流量控制,緩存數據或默認值返回等。不論採用哪種失敗處理策略,都需要考慮應該盡量減少服務調用失敗或超時對最終用戶造成的影響。
基於請求/響應的同步 IPC
使用同步的、基於請求/響應的 IPC
機制的時候,客戶端向服務端發送請求,服務端處理請求並返迴響應。一些客戶端會由於等待服務端響應而被阻塞,而另外一些客戶端可能使用非同步的、基於事件驅動的客戶端代碼,這些代碼可能通過
Future 或者 Rx Observable
封裝。然而,與使用消息機制不同,客戶端需要響應及時返回。這個模式中有很多可選的協議,但最常見的兩個協議是 REST 和
Thrift。
Thrift 也能夠讓你選擇傳輸協議,包括原始 TCP 和 HTTP。原始 TCP 比 HTTP 更高效,然而 HTTP
對於防火牆、瀏覽器和使用者來說更友好。文中對於兩種實現方式已經描述的相當詳細,可以看到當前互聯網OpenAPI平台和微服務架構實現中仍然是大量以採用Rest
API介面為主。
而對於消息格式的選擇,可以看到在使用RestAPI介面的時候,更多的是採用了Json消息格式而非XML,對於SOAP
WebService則更多採用了XML消息格式。如果採用Thrift則還可以採用二進位消息格式以提升性能。
服務與服務之間的通訊現在大部分是用的Http+Rest的方式來處理的,但是當服務個數的增加真的不知道為出現什麼問題,現在好像也沒有哪個公司的量級到了這個出現問題的程度,相反,我覺得是用SOA的方式來管理服務與服務之間的通訊未必不是一件壞事,畢竟好用才是王道.針對這個問題我也有一篇blog說明,你可以看看:微服務之間介面調用的一種新架構思路 歡迎拍磚
補充:這個架構是面向連接的,不是面向數據的之前各位的回復已經比較完善,這裡補充最新才出現的一個概念 - SERVICE MESH(服務網格) ,對於 Kubernetes 和 Cloud Native 的擁躉而言,它值得關注。
這個概念是開發 Linkerd 的 Buoyant 公司率先使用,其定義是提供安全的、快速的、可靠地服務間通訊,對應用透明。潛台詞就是所有應用流量的控制都可以在 Service Mesh 中實現。
A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It』s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware.
————What"s a service mesh? And why do I need one?
Service Mesh 簡單架構如下:
大量服務相互調用時,Service Mesh 架構如下:
目前比較火的 Service Mesh 開源項目是 Istio,由 Google、IBM、Lyft 共同開發,它提供了一個完整的解決方案,通過為整個服務網格提供行為洞察和操作控制來滿足微服務應用程序的多樣化需求。
Istio官方文檔中文版介紹,Istio 邏輯上分為數據面板和控制面板。
- 數據面板由一組智能代理(Envoy)組成,代理部署為邊車,調解和控制微服務之間所有的網路通信。
- 控制面板負責管理和配置代理來路由流量,以及在運行時執行策略。
Istio 目前僅支持在 Kubernetes 上的服務部署,但未來版本中將支持其他環境。
Service Mesh 的更詳細解讀,可以參考以下文章:
- Service Mesh:下一代微服務?
- Pattern: Service Mesh
微服務架構越來越複雜的情況下,Service Mesh 能夠讓很多工作變得更簡單。Kubernetes 被 Google 硬生生推進了 AWS 和 Azure,Azure Container Service(ACS)都變成以 Kubernetes 為主的 AKS 了。Istio 的前途,還是很值得期待的。
當然,英國互聯網金融初創公司 Monzo 因為特定版本 Kubernetes 和 Linkerd 的不兼容引發的血案再次告訴我們,新技術應用到生產環境之前要經過縝密的論證,然而技術人員對新技術的發展,始終要保持開放的心態去了解的。
這個跟docker無關吧,設計層面都不一樣吧。。
https://github.com/uber/hyperbahn
nsq
就三個字:無狀態
這和docker無關,除非你想使用一個跑在二層網路上的通信協議
設計應用上層架構的時候,完全不應該考慮應用是跑在 Docker 里還是 Xen 里。
推薦閱讀: