Chris Richardson 微服務系列翻譯全7篇連接:html
原文連接:Service Discovery in a Microservices Architecture
nginx
假設咱們須要經過 REST API 或 Thrift API 去調用某個服務,爲了完成一次請求,咱們須要知道服務實例的地址(IP和端口號)。傳統運行在物理機上的應用,服務實例的網絡地址通常是靜態的,能夠從配置文件中去讀取地址。git
對於基於雲平臺的微服務中,有更多以下的問題須要解決:github
服務實例的網絡地址是動態分配的。因爲擴展、升級,服務地址會常常變更,所以,客戶端須要使用更負責的服務發現機制。算法
主要有兩種服務發現機制:客戶端發現模式和服務端發現模式。數據庫
客戶端決定服務實例的網絡地址,並對請求實現負載均衡。客戶端查詢服務註冊表(可用服務實例的數據庫),而後使用負載均衡算法從中選擇一個實例並請求。下圖展現該模式的架構:apache
服務實例的網絡地址在啓動時記錄到服務註冊表上,等實例中止時從服務註冊表中刪除。服務實例的註冊信息一般使用心跳機制來按期刷新。編程
Netflix OSS 是客戶端發現模式的絕佳範例。Netflix Eureka 實現了服務註冊表,爲服務註冊管理和可用實例查詢提供了 REST API 接口,Netflix Ribbon 是 IPC 客戶端,與 Eureka 一塊兒實現對請求的負載均衡。緩存
客戶端發現機制有諸多優點和不足。優勢:一、相對直接,除服務註冊外,其餘部分無需改動。二、客戶端知曉可用的服務實例,能針對特定應用智能的實現負載均衡,例如一致性哈希算法。不足:客戶端與服務註冊表綁定,要針對服務端用到的每一個編程語言和框架,實現客戶端的服務發現邏輯。服務器
下圖展現了服務端發現模式的架構:
客戶端經過負載均衡向某個服務發出請求,負載均衡查詢服務註冊表,並將請求路由至可用的服務實例。如同客戶端發現模式,服務實例在服務註冊表中註冊或刪除。
AWS Elastic Load Balancer (ELB)是服務端發現路由的範例。ELB 一般對外部的網絡請求進行負載均衡,也可對虛擬私有云的內部請求進行負載均衡。客戶端使用 DNS 經過 ELB 發出請求(HTTP或TCP),ELB 將請求負載均衡到一系列註冊的 EC2 實例或 ECS 容器,這二者沒有單獨的服務註冊表,而是註冊在 ELB 中。
一些部署環境使用 Kubernetes 和 Marathon 在每一個集羣運行一個代理,做爲服務端發現的負載均衡。代理能夠根據 IP地址和端口 來路由客戶端請求,透明的將客戶端的請求轉發到集羣中某個可用的服務實例上。
服務端發現機制的優勢:客戶端無需關注服務發現的細節,只需簡單的向負載均衡發送請求,如上文所說,某些部署環境免費提供了這一功能;不足:除非部署環境提供了負載均衡,不然也成爲了須要額外配置和管理的高可用組件。
服務註冊表是服務發現的核心部分,是包含服務實例的網絡地址的數據庫。服務註冊表須要高可用和實時更新。客戶端能緩存從服務註冊表中獲取的網絡地址,然而這些信息最終會過期,客戶端也不能再根據該信息發現服務實例。所以,服務註冊表對集羣中的實例使用複製協議來保證一致性。
Netflix Eureka 是服務註冊表的範例,爲服務實例的註冊和查詢提供了 REST API:服務實例能夠經過 POST 請求來註冊網絡地址,每 30秒經過 PUT 去更新註冊信息,也可主動經過 DELETE 請求或實例註冊超時來刪除註冊信息,客戶端使用 GET 請求來檢索已註冊的服務實例。
Netflix 經過在每一個 AWS EC2 域運行一個或多個 Eureka 服務實例來實現高可用。DNS TEXT 記錄了 Eureka 集羣的配置文件,配置文件映射了可用域和 Eureka 服務器網絡地址的映射關係。Eureka 服務啓動時查詢 DNS 獲取 Eureka 集羣配置,肯定同伴位置,爲本身分配未被使用的彈性 IP 地址。
Eureka 客戶端傾向使用同一域內的 Eureka 服務器,若是該域中沒有可用的服務,則會使用其餘域中的 Eureka 服務。
其餘的服務註冊表例如:
像 Kubernetes、Marathon 和 AWS ,服務註冊表是架構內置的一部分。
服務實例必須在註冊表中註冊和註銷,有如下不一樣的兩種方法:一、服務實例本身註冊,也叫作自注冊模式;二、系統中其餘組件管理服務實例的註冊,也就是第三方註冊模式。
使用自注冊模式時,服務實例負責在註冊表中註冊和註銷,另外也須要發送心跳來防止註冊信息過時,以下圖所示:
Netflix OSS Eureka 客戶端就是這種模式的一個範例,他負責處理服務實例註冊和註銷的各個方面。Spring Cloud 實現了包括服務發如今內的各類模式,使得利用 Eureka 自注冊服務實例更簡單,只須要給 Java 配置類上添加 @EnableEurekaClient 便可。
自注冊的優點:相對簡單,不使用其餘系統組件。不足:服務實例與服務註冊表耦合,必須在每一個客戶端實現註冊邏輯。
使用第三方註冊模式,服務實例不須要向服務註冊表註冊,而是經過服務註冊器的系統組件來處理。服務註冊器經過輪詢或訂閱事件的方式來跟蹤運行實例的更改,一旦監測到有新的可用服務實例,會向註冊表註冊此服務。服務註冊器也負責註銷已終止的服務實例。架構圖以下圖所示:
Registrator 是一個開源的服務註冊器,他可以自動註冊和註銷 Docker 容器中的服務實例,支持包括 etcd 和 Consul 在內的多種服務註冊表。
NetflixOSS Prana 是另外一個服務註冊器,主要面向非 JVM 語言的服務,與服務實例一塊兒運行。Prana 使用 Netflix Eureka 來註冊和註銷服務實例。
第三方服務註冊器的優勢:服務與服務註冊器解耦,無需爲不一樣的編程語言實現服務註冊的邏輯,而是經過一個專有服務以集中化的方式進行管理。不足:除非內置在部署環境中,否則又是一個須要被維護和管理的高可用組件。
微服務應用中,服務實例的網絡地址會動態的變化,所以,爲了使客戶端可以向服務端發起請求,必須有服務發現機制。
服務註冊表是服務發現的關鍵。服務註冊表是可用服務實例的數據庫,提供了管理和查詢的 API,服務實例使用管理 API 實現註冊和註銷,系統組件使用查詢 API 發現可用的服務實例。
服務發現有兩種模式:客戶端發現和服務端發現。使用客戶端發現的系統中,客戶端直接查詢註冊表,選擇一個可用實例發起請求;在服務端發現的系統中,客戶端經過路由轉發請求,路由會查詢服務註冊表並將請求轉發到可用服務實例上。
服務實例的註冊和註銷也有兩種方式。一是服務實例本身註冊到服務註冊表中,即自注冊模式;另外一種是其餘系統組件處理註冊和註銷,也就是第三方註冊模式。
在一些部署環境中,可使用 Netflix Eureka、etcd、Apache Zookeeper 等實現服務發現。而另外一些部署環境則內置了服務發現,例如,Kubernetes 和 Marathon 用來處理服務註冊和註銷,他們在集羣的每一個主機上運行一個代理完成服務端發現路由。
NHINX 可以用做服務端發現負載均衡使用,服務註冊表能夠向 NGINX 推送路由信息,例如使用 Cosul Template。