架構雜談《九》
微服務與輕量級通訊機制
微服務架構是一種架構模式,它提倡將單一應用程式劃分成一組小的服務,服務之間胡亮協調、互相配合,為使用者提供最終價值。在微服務架構中,服務與服務之間通訊時,通常是通過輕量級的通訊機制,實現彼此間的互通互聯、互相協作。所謂輕量級通訊機制,通常是指與語言無關、與平臺無關的這類協議。通過輕量級通訊機制,使服務與服務之間的協作變得簡單、標準化。
1、同步通訊與非同步通訊
1.1概述
微服務架構是一種架構模式,它提倡將單一應用程式劃分成一組小的服務。因此,微服務架構本質上分散式系統。
相比傳統的單機系統,由於服務和資料分佈在不同的節點上,每次互動都需要跨節點與執行,這使得網路成為微服務架構實施考慮的必要因素之一。
1.2 同步通訊與非同步通訊的選擇
同步通訊是指當客戶端發出請求後,在服務端處理未結束前,客戶端一直處於等待狀態,直到最終獲得服務端的響應。
非同步通訊則是指當客戶端發出請求後,服務端或者第三方元件會先接受訊息並應答,然後在合適的時間對請求進行處理。在這中間。客戶端不需要一直處於等待狀態。
2、遠端呼叫RPC
RPC(Remote Procedure Call)又稱遠端過程呼叫。是一種典型的分散式節點間同步通訊的實現方式。遠端過程呼叫採用客戶端/服務端的模式,請求的發起者是客戶端,提供響應的是伺服器端。
客戶端通過客戶代理存根(Stub),傳遞函式引數,向伺服器端發起函式呼叫。伺服器端通過伺服器代理存根(Skeleton),接受到客戶端的請求後,對請求進行處理。並在結束後向客戶端返回響應,從而完成一次通訊。
2.1遠端過程呼叫的核心
遠端過程呼叫採用客戶端/伺服器端模式。請求的發起者是客戶端,提供響應的是伺服器端。客戶端與伺服器端的互動模式圖如下:
1、首先,客戶端呼叫本地代理存根,傳送請求到伺服器端,等待應答資訊
2、在伺服器端,服務代理處於睡眠狀態,直到客戶端請求到達並將其喚醒
3、服務代理獲得請求引數後,交由伺服器的服務程式碼對其進行處理
4、應用程式處理結束後,由服務代理向客戶端傳送應答,等待下一次請求
5、客戶端代理存根接收應答資訊,交給客戶端的呼叫程式碼進行處理。
2.2遠端方法呼叫
傳統的遠端過程呼叫框架主要包括 Sun RPC、DCE/RPC,主要基於C語言實現,以函式呼叫為主。
隨著面嚮物件語言的快速發展,序列化/反序列化等特性的誕生。基於不同語言的遠端過程呼叫框架開始提供物件遠端訪問的功能,如 Thrift、protocol buffers等,同傳統的遠端過程呼叫框架相比,有一類框架能夠允許客戶端通過物件導向的呼叫方式,呼叫遠端的實現。我們稱這類呼叫為遠端方法呼叫,換句話說 遠端方法呼叫是遠端過程呼叫的一種物件導向的實現。
2.3 RPC的弊端
RPC 通過 使用代理存根(Stub/Skeleton)的方式,遮蔽了通訊雙發底層的呼叫細節,讓客戶端不必顯式地區分當前程式碼級別的方法呼叫是本地呼叫還是遠端呼叫。因此使分散式節點間的通訊變得簡單。但是,雖然RPC 的呼叫機制遮蔽了呼叫的細節,簡化了呼叫流程。但其也存在著弊端。
1:耦合度高
2:靈活性差
3、REST
3.1 REST 概述
REST(Representation State Transfer)(表述性狀態傳遞)是這幾年使用較廣泛的分散式節點間通訊的實現方式,REST 從語義層面將響應結果定義為資源,並使用HTTP的標準動詞對映為對資源的操作,形成了一種以資源為核心、以HTTP為操作方式的,與語言無關、平臺無關的服務間通訊機制。
3.2 REST的核心
資源:(Resource)是一種抽象的概念,是指對某類資訊實體的抽象。實體是指伺服器端需要處理的具體資訊,它可以是一段文字、一種圖片也可以是檔案系統中的一個檔案、資料庫中的一張表等。與物件導向設計中的概念類似,資源通常以名詞為核心來定義,每個資源對應一個特點的URI作為標識。
表述:(Representation)資源的表述是對資源在某個特定時刻的狀態的描述。資源是一種資訊實體,實體在客戶端與伺服器端進行資訊交換時,可以有多種表現形式,如:文字可以用TXT格式表現,也可以用HTML格式、XML格式、JSON格式表現,甚至可以採用二進位制格式;圖片可以用JPG格式標識也可以用PNG格式表現。這種資源的表述格式在客戶端與伺服器端通過請求-響應的協商機制來確定。實際上,URI 僅代表資源的實體,並不代表它的表述。如:有些URL最後的.html 字尾名並屬於表述範疇,表述應該在HTTP請求的頭資訊中用 Accept和Content-Type 欄位來指定。這兩個欄位才是對“表述”的描述。
狀態轉移:(State Transfer)是指在客戶端同服務端互動的過程中。客戶端能夠通過資源的表述,實現操作資源的目的。當我們使用瀏覽器訪問一個網站時,就代表了客戶端和伺服器端的一個互動過程。在這個過程中,必然會涉及資料或者狀態的變化。但是我們知道HTTP是一個無狀態的協議。這意味著,所有的狀態都儲存在伺服器端。因此,如果客戶端想要操作資源,必須通過某種手段,讓伺服器端發生狀態的轉移。而這種轉移是建立在資源的表述上的。所以通常將其稱為表述層狀態轉移。
統一介面:(Uniform Interface)客戶端操作資源的方式,通常是基於HTTP的4個動詞(Verb):GET、POST、PUT、DELETE。它們分別對應4種資源的操作方式。
GET:用來獲取資源
POST:用來新建資源
PUT:用來更新資源
DELETE:用來銷燬資源
因為客戶端是通過HTTP的這4個動詞操作資源的。也就意味著不管請求的URI是什麼,請求的資源有什麼不同,但操作資源的介面都是統一的。
3.3 REST的優勢
通過資源表述、狀態轉移以及統一介面,REST 將客戶端的請求、伺服器端的響應基於資源聯絡起來,逐漸形成了一種以資源為核心、以HTTP為操作方式的、與語言無關、平臺無關的通訊機制。同時,由於HTTP本身的無狀態性,使用REST,能夠有效保持服務/應用的無狀態性,利於將來的水平伸縮。
3.4 REST的不足
隨著團隊或者組織業務的不斷增長,伺服器端響應內容複雜度的增加,REST的使用面臨如下的挑戰:
1:如何標準化資源結構
2:如何處理資源的相關連結
3.4.1 如何標準化資源結構
使用REST可以將業務場景的具體資訊定義為資源。並基於JSON或者XML返回給客戶端,隨著業務的不斷增長,邏輯的增加,伺服器端對內容的響應結構會變得越來越複雜(所謂響應結構,是指伺服器端的響應內容結構,既資源的結構)
REST作為指導性的原則,並沒有定義伺服器端響應結構應該遵循什麼標準。這也就意味著在企業內部、不同的部門、不同的開發小組,對同一類資源所定義的結構可能不同,因此如何定義一套標準的資源響應結構,成為服務數量增多後使用的REST面臨的一個挑戰。
3.4.2 如何有效處理相關資源的連結
大部分REST的實現,都是基於 JSON 作為傳輸格式,但 JSON最大的遺憾在於沒有對超連結處理做內建的支援,而這部分卻恰恰是 Web 的基石,這帶來的潛在問題是,對於呼叫介面的客戶端而言,每次需要檢視相關的介面文件,才能瞭解如何修改資源的狀態,或者獲取相關聯資源的資訊。因此,如何用有效的方式管理REST中相關資源的依賴以及連結,是否能夠將這種方式標準化,成為服務數量增多後使用REST面臨的另一個挑戰。
3.4.3 其他需要考慮的因素
效能:
由於REST 是基於 HTTP 之上的協議,而HTTP本身是一個使用廣泛的、基於TCP/IP的應用層協議,因此 REST 並不是低延時通訊的最好選擇。對於服務之間對低延時要求的場景,可能需要選擇不同的底層協議,如UDP 來達到希望的效能,或者其他RPC框架
開發成本:
使用REST,其傳輸格式是XML或者JSON的文字格式,在享受平臺無關、語言無關優勢的同時,團隊需要編寫更多的程式碼來解析文字格式的協議,不過目前已經有很多成熟的庫幫助我們來做類似的事情,如 Java下解決 JSON的 JSON-lib、org.json 以及 C# 下的 Newtonsoft.Json
說明:
1、參考書籍:《分散式服務架構:原理、設計與實戰》《微服務架構與實踐》
2、如有不合適的地方請反饋。綜合後更改。