微服務通訊原則:智慧終端和啞管道

banq發表於2017-11-29
大部分公司遷移到微服務架構面臨的一個挑戰是如何實現微服務之間的通訊。

在過去單體架構中,各個元件都在同一個程式中執行,相互通訊只是相互的函式的呼叫而已。但是在微服務環境中,元件之間是由伺服器硬性邊界分隔了,一般位於不同的VM或JVM或伺服器中,相互之間需要透過埠進行通訊。

解決微服務間通訊問題的最好方法就是遵循Martin Fowler 2014年定義微服務的論文中的“智慧端點和啞管道”原則。

本文闡述了Martin Fowler的這個微服務通訊概念,並解釋瞭如何遵循“啞管”正規化構建微服務通訊的現代技術。


微服務通訊的型別
微服務之間有兩種主要的通訊形式:
1. 請求-響應:一個服務透過發出指定請求來呼叫另一個服務,這種方式通常用於儲存或檢索資料。該服務然後等待響應:得到某個響應資源或響應確認。

2.觀察者:基於事件的隱式呼叫,其中一個服務釋出事件,其他一個或多個正在監視該事件的觀察者透過非同步執行邏輯來響應該事件。

為了說明這兩種通訊型別,以社交媒體應用程式的使用者註冊流程為例。

微服務通訊原則:智慧終端和啞管道

當使用者註冊建立賬戶時,客戶端向API端點發出POST請求,向後端API傳送其基本概要資訊,如名稱,密碼,電子郵件地址等。由於這是微服務架構,因此這個請求需要呼叫幾個後端微服務來處理底層的功能。

有一個核心使用者後設資料服務,是用於儲存基本的配置檔案資訊,還有一個密碼服務,用於密碼明文儲存,以供使用者登入後進行比較。還有其他一些微服務在後臺執行以響應使用者註冊:比如傳送一封電子郵件要求使用者點選一個連結來驗證他們的電子郵件地址,還有一種微服務是搜尋朋友以便將這新註冊的使用者推薦給他們。

最初的兩種請求是儲存配置檔案資訊和密碼,這毫無疑問是明確使用請求 - 響應通訊方式。這種方式是同步堵塞式的,客戶端會一直堵塞等待資料都被保留在後端以後返回200 OK響應。但是,客戶端是不需要等待驗證電子郵件被髮送出去以後或推薦朋友以後才返回響應。對於這兩個功能,最好使用觀察者模式,即後端服務監視使用者註冊事件並非同步觸發。

瞭解何時何地使用請求 - 響應模型與觀察者模型是設計有效的微服務通訊的關鍵。


反模式:集中式服務匯流排
建立一個複雜的集中式通訊匯流排,在其中根據邏輯進行路由和轉發訊息是架構設計中的陷阱,這樣做往往會導致很多問題。相反,微服務更傾向於採取分散的方法:微服務使用啞管(非智慧,不具備智慧路由等高階功能的訊息系統)來從一個端點到另一個端點獲取訊息。

微服務通訊原則:智慧終端和啞管道


乍看起來,中央匯流排的圖形不如在微服務產生的許多直接連線通訊的網路可怕。但是,重要的是要考慮在中央匯流排裡其實還是存在相同的連線。只是所有這些通訊路徑現在都嵌入到一個單體元件中了。這種中央單體匯流排會是的系統變得過於複雜,並且從效能角度和工程角度都可能成為瓶頸或單點風險。

分散的微服務通訊使開發團隊能夠在架構的不同邊界上進行並行工作,同時不會破壞其他元件。如果每個微服務將其他服務視為外部資源,而不必區分內部服務和外部資源,則意味著每個微服務都封裝了自己的格式化輸入/輸出邏輯。這使得團隊可以獨立新增功能或修改現有功能,而無需修改中央匯流排。縮放擴充套件微服務通訊也是分散的,以便每個服務可以有自己的負載平衡器和縮放邏輯。

請求 - 響應模型
微服務之間的請求 - 響應通訊用於一個服務傳送請求並期望返回資源或確認響應。
實現這種模式的最基本的方法是使用HTTP,最好遵循REST原則。兩個微服務之間的標準HTTP通訊管道通常如下所示:

原始服務 --> Http負載平衡器 ---->後端服務

在這種方法中,有一個簡單的負載均衡器可以位於服務通訊中間,原始服務可以向負載均衡器發出HTTP請求,負載平衡器可以將該請求轉發到後端微服務的其中任何一個例項。

但是,在某些情況下,服務之間的流量非常高,或者開發工程團隊希望儘可能減少微服務之間的延遲。在這種情況下,他們可能採用胖客戶端負載平衡。這種方法通常使用諸如Consul,Eureka或ZooKeeper之類的系統來跟蹤微服務例項及其IP地址的集合。然後,發起的微服務可以直接向需要與之通話的後臺服務例項發出請求。

Consul維護一個解析到不同後端微服務例項的DNS記錄,以便一個服務可以在沒有負載均衡器情況下直接與另一個服務對話,。

值得注意的框架是GRPC,它已經成為多語言應用程式的強大武器。GRPC可以使用外部負載均衡器進行操作,類似於上面的HTTP方法,也可以使用胖客戶端負載均衡器。然而,GRPC的突出特點是它將通訊負載轉換成一種稱為協議緩衝區protocol buffers的通用格式。

protocol buffers允許後端服務將通訊負載序列化為有效的二進位制格式以便透過線路傳輸,然後將其反序列化為適合其特定執行時的物件模型。

觀察者模型
觀察者模型對於擴充套件微服務至關重要。並不是每個通訊都需要回應或確認。事實上,在許多長時間的工作流程中,至少有一些邏輯實現應該是完全非同步和非阻塞的。

分發這種型別的工作負載的標準方式是使用代理服務來傳遞訊息,理想的是實現一個佇列。RabbitMQ,ZeroMQ,Kafka甚至Redis Pub / Sub都可以用作啞管道,它們允許微服務釋出事件,同時允許其他微服務訂閱他們需要感興趣的事件。

這種方法的巨大優勢在於,釋出服務方不需要知道事件訂閱了多少使用者,或者這些訂閱者做什麼事情來響應自己的事件。在消費者發生故障的情況下,大多數佇列系統具有重試/重新傳送功能以確保訊息最終被處理。生產者只需“傳送然後忘記”即可,相信訊息代理的佇列將確保訊息最終到達正確的消費者。即使所有消費者都忙於無法立即回應事件,佇列仍然會持久儲存,直到消費者準備好處理事件。

觀察者模型的另一個好處是微服務系統的未來可擴充套件性。一旦在生產者服務中實現了事件廣播,新的消費者型別可以在事件發生之後被新增和訂閱,而不需要改變生產者。例如,在本文開頭的社交媒體應用程式中,有兩位消費者訂閱了使用者註冊事件:電子郵件驗證服務和朋友推薦服務。工程師可以輕鬆地新增第三個服務,回覆使用者註冊事件,透過電子郵件傳送所有通訊錄中名單有該新使用者的哪些人群,讓他們知道他們的聯絡人剛剛註冊。這項新功能完全不需要對原來的核心功能使用者註冊服務進行任何更改,從而消除了增加新功能可能會破壞關鍵的使用者註冊功能的風險。

觀察者模型是微服務部署中非常強大的工具,不實現觀察者通訊的微服務架就無法發揮其全部潛力。

結論
當你接受架構和邏輯分離的概念以後,智慧端點和啞管的微服務原理就很容易理解。儘管使用“啞管”,微服務還是可以實現基本的訊息傳遞,也就不需要集中式的中央服務匯流排。相反,微服務應該利用那些在請求響應和觀察者通訊中都是傻瓜式管道或稱啞管的中介軟體系統。


Microservice Principles: Smart Endpoints and Dumb

相關文章