NO IMAGE

服務呼叫者要在眾多的微服務中呼叫具體的服務提供者,必然涉及到負載均衡的問題,根據負載均衡的實現可以分為集中式LB、程序內LB和獨立程序LB。

集中式LB

集中式LB

LB上有所有的服務地址配置,當服務消費者呼叫某個服務的時候,LB會根據負載均衡策略(隨機、輪詢等)將請求轉發到具體的服務上。此外,服務呼叫者還需要知道LB的地址,通常的做法是運維在伺服器上配置一個DNS域名或者IP,這個域名指向LB。

這種實現方式的問題每次呼叫都要訪問LB,LB存在單點問題,無法水平擴充套件

程序內LB

程序內LB

為了解決每次服務呼叫都經過LB的不足,把LB放在客戶端可以很好解決,這裡多了一個登錄檔,服務提供方啟動時,首先將服務地址註冊到服務登錄檔,定期傳送心跳包到服務登錄檔,檢查存活狀態。

服務消費方要訪問某個服務時,經歷以下過程:

  1. 服務消費者在啟動時從服務登錄檔獲取需要的服務註冊資訊
  2. 將服務提供者註冊資訊快取在本地(客戶端LB)
  3. 監聽服務提供者註冊資訊的變更,如接收到服務註冊中心的服務變更通知,則在本地快取中更新服務的註冊資訊
  4. 根據本地快取中的服務註冊資訊構建服務呼叫請求,並根據負載均衡策略(隨機負載均衡,Round-Robin負載均衡等)來轉發請求
  5. 對服務提供方的存活進行檢測,如果出現服務不可用的服務提供方,將從本地快取中剔除,定期檢測本地服務登錄檔的存活狀態

這一方案對服務登錄檔的可用性要求很高,一般採用能滿足高可用分散式一致的元件(例如Zookeeper、Consul、Etcd等)來實現。這裡由於LB是在服務呼叫者的程序內,那麼每個服務呼叫者都有自己的本地LB,不會導致每次呼叫都直接訪問LB的情況,而且服務呼叫者直接訪問服務提供者,沒有額外的開銷。

這樣部署的條件是服務登錄檔要支援高可用,通常採用叢集部署的方式實現。目前開源元件比如Dubbo、Eureka、Karyon都是採用類似這種服務註冊發現機制,不足是要對不同的語言開發不同的客戶端,因為LB需要進行路由,不同的語言就需要開發不同的客戶端進行路由,比如Dubbo本身是用Java開發的,只要配和註冊中心比如zookeeper就可以完成服務註冊和發現,但是使用Node.js如果要呼叫dubbo服務就需要開發基於Node.js的客戶端去發現dubbo的服務,相當於是Node.js版的Dubbo。

獨立程序LB

獨立程序LB

與第二種類似,區別是這將LB作為獨立程序,好處是多語言環境下可以不用開發不同的客戶端,不足是部署複雜,增加了出錯除錯的複雜度。只要LB程序的主機部署了其他應用,不管是什麼語言開發的都能通過LB完成路由,這樣就不需要開發專門的客戶端去路由了

每次服務呼叫都要穿透主機所在的LB,包括請求和響應。目前開源的元件有Airbnb的SmartStack