1.???? 服務發(fā)現(xiàn):Eureka客戶端
服務發(fā)現(xiàn)是微服務架構的關鍵原則之一。使用手動配置或一些約定方式來處理多服務多實例的方式是非常困難,并且十分脆弱的。Eureka同時是Netflix服務發(fā)現(xiàn)的服務端和客戶端。服務端可以通過配置和部署實現(xiàn)高可用,實現(xiàn)方式是每個服務端對注冊的服務復制他們的狀態(tài)到其他的服務端。
?
1.1? 如何創(chuàng)建Eureka客戶端
引入org.springframework.cloud的spring-cloud-starter-eureka工程就可以在你的項目上中創(chuàng)建Eureka客戶端。在當前版本上如何具體配置可以查看Spring Cloud 工程頁面。
1.2? 使用Eureka注冊
當一個客戶端用Eureka注冊時,它會提供諸于主機和端口,健康指標URL,主頁等元數(shù)據(jù)。Eureka接收來一個服務的所有實例的心跳信息。如果有在配置時間段內(nèi)沒有接收到心跳,這個實例通常會從注冊表中移除。
Eureka客戶端的例子如下:
| 03 | @EnableAutoConfiguration |
| 06 | public?class?Application { |
| 08 | ????@RequestMapping("/") |
| 09 | ????public?String home() { |
| 10 | ????????return?"Hello world"; |
| 13 | ????public?static?void?main(String[] args) { |
| 14 | ????????newSpringApplicationBuilder(Application.class).web(true).run(args); |
(即非常普通的Spring Boot應用)。在這個例子中我們使用了EnableEurekaClient注解,但是當只有Eureka可用時你也可以使用EnableDiscoveryClient注解。還需要如下所示的配置信息來定位Eureka服務端:
application.yml
| 4 | ??????defaultZone: http://localhost:8761/eureka/ |
其中的defaultZone為未表示首選項的客戶端提供默認的服務,是一個有后備值的魔力字符串 (即它是一個有用的默認參數(shù))。
該環(huán)境下的默認應用名(服務ID),虛擬主機名和非安全端口號分別是?${spring.application.name}, ${spring.application.name} 和 ${server.port}。
@EnableEurekaClient使得該應用成為一個Eureka “實例”(即自注冊)和一個“客戶端”(即它能查詢注冊表以定位其它服務)。eureka.insatnce.*配置信息決定了實例的行為,但是如果你確保你的應用有spring.application.name(這就是Eureka服務ID的默認值,或者說是VIP),那么默認配置也是可以的。
更多的配置選項可以查看?EurekaInstanceConfigBean?和?EurekaClientConfigBean。
1.3? Eureka服務器認證
如果一個eureka.client.serviceUrl.defaultZone的URL內(nèi)嵌了認證(如:http://user:password@localhost:8761/eureka),那么基于HTTP的認證機制就會自動加入到你的eureka客戶端中。如果有更復雜的需求可以創(chuàng)建一個DiscoveryClientOptionArgs類型的Bean并注入ClientFilter實例,當客戶端請求服務端時這些配置就會生效。
注意因為Eureka的限制,不可能去支持每一個服務器認證證書,而是使用第一個被發(fā)現(xiàn)的。
1.4? 狀態(tài)頁和健康檢查
Eureka實例的狀態(tài)和健康檢查頁面默認分別是”/info”和“/health”,它們是Spring Actuator應用中有用的默認定位設置。如果你使用一個非默認的上下文路徑或者 servlet路徑(例如server.serveletPath=/foo)或者管理端路徑(例如management.contextPath=/admin),那么你就需要改變這些,即使Actuator應用。示例如下:
application.yml.
| 3 | ????statusPageUrlPath: ${management.context-path}/info |
| 4 | ????healthCheckUrlPath: ${management.context-path}/health |
這些鏈接是客戶端之間互相使用的元數(shù)據(jù),并且在一些情形下用來決定是否向應用發(fā)送請求,所以如果它們是精準的話將會是有幫助的。
1.5? 注冊安全應用
如果你希望應用使用HTTPS協(xié)議進行交互,那么你可以在EurekaInstanceConfig中配置兩個指標,即eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true].這將使得Eureka發(fā)布的實例信息首選安全通信。Spring Cloud的發(fā)現(xiàn)客戶端就總是會為采取該種配置的服務返回一個以https開頭的URI,并且Eureka(本地)實例信息會有一個安全的健康檢查URL。
因為Eureka的內(nèi)部工作機制,它仍然會給狀態(tài)和主頁產(chǎn)生一個非安全的URL,除非你顯示重寫配置。你可使用占位符來配置eureka實例的urls,例如:
application.yml
| 3 | ????statusPageUrl: https://${eureka.hostname}/info |
| 4 | ????healthCheckUrl: https://${eureka.hostname}/health |
| 5 | ????homePageUrl: https://${eureka.hostname}/ |
(注意${eureka.hostname}是一個只能在Eureka后續(xù)版本中使用的本地占位符,你可以使用Spring占位符來達到同樣的效果,例如使用${eureka.instance.hostname})
如果你的app在代理下運行,并且SSL終端也使用了代理(例如如果你在Cloud Foundry或者其它平臺下作為一個服務運行),那么你就需要確保代理的”forwarded”頭被攔截并且被該應用處理。如果內(nèi)嵌Tomcat容器的Spring Boot應用對‘X-Forwarded-\*’頭有一個明確的配置,那么它就會自動處理這些。出現(xiàn)該類錯誤的一個標志就是你的app自身的一些鏈接會出現(xiàn)錯誤(錯誤的主機,端口和協(xié)議)。
1.6? Eureka的健康檢查
Eureka默認會根據(jù)客戶端的心跳來判斷該客戶端是否在線。除非是具體指定了否則的話發(fā)現(xiàn)客戶端是不會將通過Spring boot Actuator傳遞當前應用的健康檢查狀態(tài)。也就是意味著一旦成功注冊Eureka之后就會一直處于在線狀態(tài)。當啟用Eureka健康檢查之后就會改變這種狀態(tài),致使應用的狀態(tài)傳遞給Eureka。結果就是其它的每一個應用除非是處于在線狀態(tài),否則不會向應用發(fā)送請求。
application.yml
警告eureka.client.healthcheck.enabled=true只能在application.yml中配置。如果在bootstrap.yml中配置的話會產(chǎn)生不良影響,比如說在eureka中注冊為UNKNOWN狀態(tài)。
如果需要對健康檢查作更多控制,你可以考慮實現(xiàn)類com.netflix.appinfo.HealthCheckHandler。
1.7? 實例和客戶端面的元數(shù)據(jù)
為了在平臺中合理使用Eureka,花點時間理解Eureka元數(shù)據(jù)是如何工作是非常值得的。標準的元數(shù)據(jù)就是諸如主機名,IP地址,端口號,狀態(tài)頁和健康檢查。這些都包含在服務注冊表中,并且被客戶端用來直接與服務聯(lián)系。可以在服務注冊時加入其它元數(shù)據(jù)到eureka.instance.metadataMap中,遠程客戶端也能使用這些數(shù)據(jù),除非改變元數(shù)據(jù)產(chǎn)意義,否則總體上不會改變客戶端的行為。如下幾種特殊情形Spring Cloud已經(jīng)指定了元數(shù)據(jù)集的意義。
1.7.1??? 在Cloudfoundry上用Eureka
Cloudfoundry有一個全局路由器,因此同一個應用的所有實例有相同的主機名(其它相似架構的Paas解決方案中也是如此)。這并不是使用Eureka的障礙,但是如果你使用路由器(推薦,甚至是強制性的,具體取決于平臺的設置方式),你需要設置具體的主機名和端口號(安全或非安全的),以便他們使用路由器。你可能想通過實例元數(shù)據(jù)來區(qū)分客戶端的實例(比如說一個傳統(tǒng)的負載均衡器中)。默認情況下,eureka.instance.instanceId就是vcap.application.instance_id。例如:
application.yml
| 3 | ????hostname: ${vcap.application.uris[0]} |
通過在Cloudfoundry實例中設置的安全規(guī)則,你就可以將虛擬主機注冊成服務對服務的調(diào)用并且可以使用。該功能在Pivotal Web Services(PWS)上還不可用。
1.7.2??? 在AWS上用 Eureka
如果應用要部署在AWS云,那么Eureka實例就必須能讓AWS識別,可以通過如下定制EurekaInstanceConfigBean來做到:
| 3 | public?EurekaInstanceConfigBean eurekaInstanceConfig(InetUtils inetUtils) { |
| 4 | ??EurekaInstanceConfigBean b =?new?EurekaInstanceConfigBean(inetUtils); |
| 5 | ??AmazonInfo info = AmazonInfo.Builder.newBuilder().autoBuild("eureka"); |
| 6 | ??b.setDataCenterInfo(info); |
1.7.3??? 修改Eureka實例ID
一個比較好的Netflix Eureka實例的注冊ID就是主機名(即一個主機只有一個服務),Spring Cloud Eureka提供了諸如${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}}的合理默認形式。例如myhost:myappname:8080。
你可以通過在eureka.instance.instanceId中提供一個唯一的標識來覆蓋這些,例如:
application.yml
| 3 | ????instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}} |
通過這個元數(shù)據(jù),當在本地部署多服務實例后,就會有隨機值來確保實例是唯一的。在CloudFoundry中vcap.application.instance_id在Spring Boot應用中自動填充,因此不需要隨機值。
1.8? 使用Eureka客戶端
一旦你的應用采用了@EnableDiscoveryClient(或者@EnableEurekaClient),你就可以發(fā)現(xiàn)Eureka服務器上的服務實例。其中的一種方式就是使用類com.netflix.discovery.EurekaClient(而不是Spring Cloud DiscoveryClient),例如:
| 2 | private?EurekaClient discoveryClient; |
| 4 | public?String serviceUrl() { |
| 5 | ????InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES",?false); |
| 6 | ????return?instance.getHomePageUrl(); |
提示:不要在@PostConstruct、@Scheduled方法(或者是任何上下文還沒有啟動的位置)使用EurekaClient。它是在智能生命周期(階段為0)時被初始化的,所以你最早能夠使用它是在另一個智能生命周期的更高階段。
1.9? 對原始Netfix Eureka客戶端所做的更改
你并不非得全用原生的Netflix EurekaClient,通常情況下經(jīng)過某種方式包裝后使用起來將更方便。Spring Cloud已經(jīng)支持Feign(一個REST客戶端builder)和使用邏輯Eureka服務定位器(VIPs)來替代物理URL的Spring RestTemplate。將Ribbon配置成固定的物理服務器列表只需簡單將<client>.ribbon.listOfServers配置成用逗號分隔物理地址列表(或主機名),其中的<client>表示客戶端的ID。
你也可以使用并非為Netflix定制的org.springframework.cloud.client.discovery.DiscoveryClient,該類為發(fā)現(xiàn)客戶端提供了一個簡單的API,例如:
| 02 | private?DiscoveryClient discoveryClient; |
| 04 | public?String serviceUrl() { |
| 05 | ????List<ServiceInstance> list = discoveryClient.getInstances("STORES"); |
| 06 | ????if?(list !=?null?&& list.size() >?0?) { |
| 07 | ????????return?list.get(0).getUri(); |
1.10????? 為什么注冊一個服務這么慢?
實例需要間隔性地向注冊表發(fā)送心跳(通過客戶端的serviceUrl),默認間隔是30秒。一個服務只有當實例,服務器和客戶端在他們的本地緩存中都有相同的元數(shù)據(jù)后才能被客戶端發(fā)現(xiàn)(因此需要三個心跳)。可以通過eureka.instance.leaseRenewalIntervalInSeconds來更改心跳周期,它能加快客戶端到服務端的速度。在生產(chǎn)環(huán)境中最好是使用默認值,因為服務器內(nèi)部有一些對更新周期進行的計算。
1.11????? 區(qū)塊
如果將Eureka客戶端部署在多個區(qū)塊上,并且在使用時優(yōu)先使用一個區(qū),那么就需要正確地配置Eureka客戶端。
首先需要確保Eureka服務器部署到了每一個區(qū)塊并且是彼此的節(jié)點。可以在zones and regions部分查看更多信息。
其次你需要告訴Eureka你的服務在哪一個區(qū)塊,可以通過metadataMap屬性來進行設置。例如如果服務1部署在區(qū)塊1和區(qū)塊2上,你需要在服務1中進行如下Eureka屬性的設置
區(qū)塊1中的服務1
| 1 | eureka.instance.metadataMap.zone = zone1 |
| 2 | eureka.client.preferSameZoneEureka =?true |
區(qū)塊2中的服務1
| 1 | eureka.instance.metadataMap.zone = zone2 |
| 2 | eureka.client.preferSameZoneEureka =?true |
原創(chuàng)文章,轉載請注明:?轉載自并發(fā)編程網(wǎng) – ifeve.com本文鏈接地址:?《Spring Cloud Netflix官方文檔》1.服務發(fā)現(xiàn):Eureka客戶端
《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的《Spring Cloud Netflix官方文档》1.服务发现:Eureka客户端的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。