微服務架構中服務注冊與發現


 

https://blog.csdn.net/u011537073/article/details/69663858

 

想象一下,如果你在寫代碼調用一個有REST API或Thrift API的服務,你的代碼需要知道一個服務實例的網絡地址(IP地址和端口)。運行在物理硬件上的傳統應用中,服務實例的網絡地址是相對靜態的,你的代碼可以從一個很少更新的配置文件中讀取網絡地址。

在一個現代的,基於雲的微服務應用中,這個問題就變得復雜多了,如下圖所示: 
Microservices 
服務實例的網絡地址是動態分配的。而且,由於自動擴展,失敗和更新,服務實例的配置也經常變化。這樣一來,你的客戶端代碼需要一套更精細的服務發現機制。

有兩種主要的服務發現模式:客戶端服務發現(client-side discovery)和服務器端服務發現(server-side discovery)。我們首先來看下客戶端服務發現。

客戶端服務發現模式

當使用客戶端服務發現的時候,客戶端負責決定可用的服務實例的網絡地址,以及圍繞他們的負載均衡。客戶端向服務注冊表(service registry)發送一個請求,服務注冊表是一個可用服務實例的數據庫。客戶端使用一個負載均衡算法,去選擇一個可用的服務實例,來響應這個請求,下圖展示了這種模式的架構: 
Microservices 
一個服務實例被啟動時,它的網絡地址會被寫到注冊表上;當服務實例終止時,再從注冊表中刪除。這個服務實例的注冊表通過心跳機制動態刷新。

Netflix OSS提供了一個客戶端服務發現的好例子。Netflix Eureka是一個服務注冊表,提供了REST API用來管理服務實例的注冊和查詢可用的實例。Netflix Ribbon是一個IPC客戶端,和Eureka一起處理可用服務實例的負載均衡。下面會深入討論Eureka。

客戶端的服務發現模式有優勢也有缺點。這種模式相對直接,但是除了服務注冊表,沒有其它動態的部分了。而且,由於客戶端知道可用的服務實例,可以做到智能的,應用明確的負載均衡決策,比如一直用hash算法。這種模式的一個重大缺陷在於,客戶端和服務注冊表是一一對應的,必須為服務客戶端用到的每一種編程語言和框架實現客戶端服務發現邏輯。

服務器端服務發現模式

下圖展示了這種模式的架構 
Microservices 
客戶端通過負載均衡器向一個服務發送請求,這個負載均衡器會查詢服務注冊表,並將請求路由到可用的服務實例上。通過客戶端的服務發現,服務實例在服務注冊表上被注冊和注銷

AWS的ELB(Elastic Load Blancer)就是一個服務器端服務發現路由器。一個ELB通常被用來均衡來自互聯網的外部流量,也可以用ELB去均衡流向VPC(Virtual Private Cloud)的流量。一個客戶端通過ELB發送請求(HTTP或TCP)時,使用的是DNS,ELB會均衡這些注冊的EC2實例或ECS(EC2 Container Service)容器的流量。沒有另外的服務注冊表,EC2實例和ECS容器也只會在ELB上注冊。

HTTP服務器和類似Nginx、Nginx Plus的負載均衡器也可以被用做服務器端服務發現負載均衡器。例如,Consul Template可以用來動態配置Nginx的反向代理。

Consul Template定期從存儲在Consul服務注冊表的數據中,生成任意的配置文件。每當文件變化時,會運行一個shell命令。比如,Consul Template可以生成一個配置反向代理的nginx.conf文件,然后運行一個命令告訴Nginx去重新加載配置。還有一個更復雜的實現,通過HTTP API或DNS去動態地重新配置Nginx Plus。

有些部署環境,比如Kubernetes和Marathon會在集群中的每個host上運行一個代理。這個代理承擔了服務器端服務發現負載均衡器的角色。為了向一個服務發送一個請求,一個客戶端使用host的IP地址和服務分配的端口,通過代理路由這個請求。這個代理會直接將請求發送到集群上可用的服務實例。

服務器端服務發現模式也是優勢和缺陷並存。最大的好處在於服務發現的細節被從客戶端中抽象出來,客戶端只需要向負載均衡器發送請求,不需要為服務客戶端使用的每一種語言和框架,實現服務發現邏輯;另外,這種模式也有一些問題,除非這個負載均衡器是由部署環境提供的,又是另一個高需要啟動和管理的可用的系統組件。

服務注冊表(Service Registry)

服務注冊表是服務發現的關鍵部分,是一個包含了服務實例的網絡地址的數據庫,必須是高可用和最新的。客戶端可以緩存從服務注冊表處獲得的網絡地址。但是,這些信息最終會失效,客戶端會找不到服務實例。所以,服務注冊表由一個服務器集群組成,通過應用協議來保持一致性。

正如上面提到的,Netflix Eureka是一個服務注冊表的好例子。它提供了一個REST API用來注冊和查詢服務實例。一個服務實例通過POST請求來注冊自己的網絡位置,每隔30秒要通過一個PUT請求重新注冊。注冊表中的一個條目會因為一個HTTP DELETE請求或實例注冊超時而被刪除,客戶端通過一個HTTP GET請求來檢索注冊的服務實例。

Netflix通過在每個EC2的可用區中,運行一個或多個Eureka服務器實現高可用。每個運行在EC2實例上的Eureka服務器都有一個彈性的IP地址。DNS TEXT records用來存儲Eureka集群配置,實際上是從可用區到Eureka服務器網絡地址的列表的映射。當一個Eureka服務器啟動時,會向DNS發送請求,檢索Eureka集群的配置,定位節點,並為自己分配一個未占用的彈性IP地址。

Eureka客戶端(服務和服務客戶端)查詢DNS去尋找Eureka服務器的網絡地址。客戶端更想使用這個可用區內的Eureka服務器,如果沒有可用的Eureka服務器,客戶端會用另一個可用區內的Eureka服務器。

其它服務注冊的例子包括:

  • Etcd:一個高可用,分布式,一致的key-value存儲,用來共享配置和服務發現。Kubernetes和Cloudfoundry都使用了etcd;
  • Consul:一個發現和配置服務的工具。客戶端可以利用它提供的API,注冊和發現服務。Consul可以執行監控檢測來實現服務的高可用;
  • Apache Zookeeper:一個常用的,為分布式應用設計的高可用協調服務,最開始Zookeeper是Hadoop的子項目,現在已經頂級項目了。

一些系統,比如Kubernetes,Marathon和AWS沒有一個明確的服務注冊組件,這項功能是內置在基礎設置中的。

下面我們來看看服務實例如何在注冊表中注冊。

服務注冊(Service Registration)

前面提到了,服務實例必須要從注冊表中注冊和注銷,有很多種方式來處理注冊和注銷的過程。一個選擇是服務實例自己注冊,即self-registration模式。另一種選擇是其它的系統組件管理服務實例的注冊,即第third-party registration模式。

自注冊模式(The Self-Registration Pattern)

在self-registration模式中,服務實例負責從服務注冊表中注冊和注銷。如果需要的話,一個服務實例發送心跳請求防止注冊過期。下圖展示了這種模式的架構: 
Microservices 
Netflix OSS Eureka客戶端是這種方式的一個好例子。Eureka客戶端處理服務實例注冊和注銷的所有問題。Spring Cloud實現包括服務發現在內的多種模式,簡化了Eureka的服務實例自動注冊。僅僅通過@EnableEurekaClient注釋就可以注釋Java的配置類

self-registration模式同樣也是優劣並存。優勢之一在於簡單,不需要其它組件。缺點是服務實例和服務注冊表相對應,必須要為服務中用到的每種編程語言和框架實現注冊代碼。

第三方注冊模式(The Third-Party Registration Pattern)

在third-party registration模式中,服務實例不會自己在服務注冊表中注冊,由另一個系統組件service registrar負責。service registrar通過輪詢部署環境或訂閱事件去跟蹤運行中的實例的變化。當它注意到一個新的可用的服務實例時,就會到注冊表中去注冊。service registrar也會將停止的服務實例注銷,下圖展示了這種模式的架構。 
Microservices 
service registrar的一個例子是開源的Registrator項目。它會自動注冊和注銷像Docker容器一樣部署的服務。Registrator支持etcd和Consul等服務注冊。

另一個service registrar的例子是NetflixOSS Prana。主要用於非JVM語言編寫的服務,它是一個和服務實例配合的『雙輪』應用。Prana會在Netflix Eureka上注冊和注銷實例。

service registrar是一個部署環境的內置組件,由Autoscaling Group創建的EC2實例可以被ELB自動注冊。Kubernetes服務也可以自動注冊。

third-party registration模式主要的優勢在於解耦了服務和服務注冊表。不需要為每個語言和框架都實現服務注冊邏輯。服務實例注冊由一個專用的服務集中實現。缺點是除了被內置到部署環境中,它本身也是一個高可用的系統組件,需要被啟動和管理。

總結

在一個微服務應用中,服務實例在運行時的配置也會動態變化,包括他們的網絡地址。為了滿足客戶端向服務發送請求的需要,必須要實現服務發現機制。

服務發現的關鍵部分是服務注冊表。服務注冊表是一個可用的服務實例的數據庫。服務注冊表提供了一個管理API和一個查詢API。服務實例的注冊和注銷通過管理API實現,查詢API用來尋找可用的服務實例。

有兩種主要的服務發現模式:客戶端服務發現和服務器端服務發現。客戶端服務發現系統中,客戶端查詢服務注冊表,選擇一個可用的實例,響應一個請求;在服務器端服務發現系統中,客戶端通過一個路由器發送請求,這個路由器會去查詢服務注冊表,並將請求發送給可用的實例。

有兩種形式可以實現服務實例的注冊和注銷,一種是self-registration模式,一種是third-party registration模式。

一些部署環境中,需要通過類似Netflix Eureka,etcd或Apache Zookeeper的組件,啟動自己的服務發現基礎設施。其它的部署環境中,服務發現是內置的。比如,Kubernetes和Marathon處理服務實例的注冊和注銷,還會在每個集群host上運行一個代理,作為服務器端服務發現路由器的角色。

一個HTTP反向代理和Nginx也可以被用做服務器端服務發現負載均衡器。服務注冊表可以推送路由信息到Nginx,引起配置更新,比如可以用Consul Template。Nginx Plus支持動態的重配置機制,可以從注冊表中拉取服務實例相關的信息,還提供了遠程配置的API。

 

微服務與微服務間分布式調用最主要的概念便是: protocol-aware heterogeneous interoperability; 各微服務可各自擁有自身的 platform (Java,C#, Scala…等等), 但, 各微服務間卻只能藉由單一共同的協議 (protocol); 如: REST; 進行分布式的調用 

 

微服務架構的產品或許會有數百甚至數千個微服務所構成。所以, 部署微服務時, 便很難經由手工來完成, 而必須相當程度的依賴自動化的 DevOps 工具。

 

 服務注冊與發現  部署  監控
Zookeeper
Doozer
Etcd
SmartStack
Eureka
NSQ
Serf
Spotify
DNS
SkyDNS
Consul
 Cloud Foundry
Gradle
Docker
Docker Hub
Docker Machine
Kitematic
Docker Compose
Docker Swarm
AWS
Jenkins
Continuum
Hudson
Artifactory
Terraform
Grunt
OpenShift
SonarCube
Logstash
New Relic
Graphite
Mesosphere / DCOS
Winston
Hystrix

 

原文:微服務架構

轉自:http://blog.csdn.net/jiaolongdy/article/details/51188798


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM