日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【学习笔记】Eureka服务治理代码实例、相关配置和原理机制详解

發布時間:2024/9/30 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【学习笔记】Eureka服务治理代码实例、相关配置和原理机制详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 代碼示例
    • 啟動一個服務注冊中心
    • 注冊服務提供者
    • 高可用注冊中心
    • 服務的發現與消費
  • Eureka的一些配置
    • 服務注冊類配置
    • 服務實例類配置
    • 實例名配置
    • 端點配置
  • Eureka服務治理基礎架構原理

代碼示例

啟動一個服務注冊中心

通過@EnableEurekaServer注解啟動一個服務注冊中心提供給其他應用進行對話。這一步非常簡單,只需在一個普通的Spring Boot應用中添加這個注解就能開啟此功能,比如下面的例子:

@EnableEurekaServer @SpringBootApplication public class Application { public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(true).run(args); }

在默認設置下,該服務注冊中心也會將自己作為客戶端來嘗試注冊它自己,所以我們需要禁用它的客戶端注冊行為,只需在application.properties中增加如下配置:

server.port=1111 eureka.instance.hostname=localhost eureka.client.register-with-eureka=false eureka.client.fetch-registry=false eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

由于后續內容也都會在本地運行,為了與后續要進行注冊的服務區分,這里將服務注冊中心的端口通過server.port屬性設置為1111。 eureka.client.register-with-eureka:由于該應用為注冊中心,所以設置為false,代表不向注冊中心注冊自己。 eureka.client.fetch-registry:由于注冊中心的職責就是維護服務實例,它并不需要去檢索服務,所以也設置為false。 在完成了上面的配置后,啟動應用并訪問http://localhost:1111/。可以看到如下圖所示的Eureka信息面板,其中Instances currently registered with Eureka欄是空的,說明該注冊中心還沒有注冊任何服務。

注冊服務提供者

在完成了服務注冊中心的搭建之后,接下來我們嘗試將一個既有的Spring Boot應用加入Eureka的服務治理體系中去。 可以使用上一章中實現的快速入門工程來進行改造,將其作為一個微服務應用向服務注冊中心發布自己。首先,修改pom.xml,增加Spring Cloud Eureka模塊的依賴,具體代碼如下所示:

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

改造/hello請求處理接口,通過注入DiscoveryClient對象,在日志中打印出服務的相關內容。

@RestController public class HelloController { private final Logger logger = Logger.getLogger(getClass()); @Autowired private DiscoveryClient client; @RequestMapping(value = "/hello", method = RequestMethod.GET) public String index() { ServiceInstance instance = client.getLocalServiceInstance();logger.info("/hello, host:" + instance.getHost() + ", service_id:" + instance.getServiceId()); return "Hello World"; } } //然后,在主類中通過加上@EnableDiscoveryClient注解,激活Eureka中的DiscoveryClient實現(自動化配置,創建DiscoveryClient接口針對Eureka客戶端的EurekaDiscoveryClient實例),才能實現上述Controller中對服務信息的輸出。 @EnableDiscoveryClient @SpringBootApplication public class HelloApplication { public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); } }

最后application.properties配置文件中,通過spring.application.name屬性來為服務命名,比如命名為hello-service。再通過eureka.client.serviceUrl.defaultZone屬性來指定服務注冊中心的地址,這里我們指定為之前構建的服務注冊中心地址,完整配置如下所示:

spring.application.name=hello-service eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

下面我們分別啟動服務注冊中心以及這里改造后的hello-service服務。在hello-service服務控制臺中,Tomcat啟動之后,com.netflix.discovery.DiscoveryClient對象打印了該服務的注冊信息,表示服務注冊成功。

我們也可以通過訪問Eureka的信息面板,在Instances currently registered with Eureka一欄中看到服務的注冊信息。

高可用注冊中心

在微服務架構這樣的分布式環境中,我們需要充分考慮發生故障的情況,所以在生產環境中必須對各個組件進行高可用部署,對于微服務如此,對于服務注冊中心也一樣。但是到本節為止,我們一直都在使用單節點的服務注冊中心,這在生產環境中顯然并不合適,我們需要構建高可用的服務注冊中心以增強系統的可用性。 Eureka Server的設計一開始就考慮了高可用問題,在Eureka的服務治理設計中,所有節點即是服務提供方,也是服務消費方,服務注冊中心也不例外。是否還記得在單節點的配置中,我們設置過下面這兩個參數,讓服務注冊中心不注冊自己: eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

**Eureka Server的高可用實際上就是將自己作為服務向其他服務注冊中心注冊自己,這樣就可以形成一組互相注冊的服務注冊中心,**以實現服務清單的互相同步,達到高可用的效果。

下面我們就來嘗試搭建高可用服務注冊中心的集群。可以在上面實現的服務注冊中心的基礎之上進行擴展,構建一個雙節點的服務注冊中心集群。 創建application-peer1.properties,作為peer1服務中心的配置,并將serviceUrl指向peer2:

spring.application.name=eureka-server server.port=1111 eureka.instance.hostname=peer1 eureka.client.serviceUrl.defaultZone=http://peer2:1112/eureka/

創建application-peer2.properties,作為peer2服務中心的配置,并將serviceUrl指向peer1:

spring.application.name=eureka-server server.port=1112 eureka.instance.hostname=peer2 eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/

在/etc/hosts文件中添加對peer1和peer2的轉換,讓上面配置的host形式的serviceUrl能在本地正確訪問到;

Windows系統路徑為C:\Windows\System32\drivers\etc\hosts。 127.0.0.1 peer1
127.0.0.1 peer2 通過spring.profiles.active屬性來分別啟動peer1和peer2:java -jar eureka-server-1.0.0.jar --spring.profiles.active=peer1
java -jar eureka-server-1.0.0.jar --spring.profiles.active=peer2

此時訪問peer1的注冊中心http://localhost:1111/,如下圖所示,我們可以看到,registered-replicas中已經有peer2節點的eureka-server了。同樣的,我們訪問peer2的注冊中心http://localhost:1112/,也能看到registered-replicas中已經有peer1節點,并且這些節點在可用分片(available-replicase)之中。我們也可以嘗試關閉peer1,刷新http://localhost:1112/,可以看到peer1的節點變為了不可用分片(unavailable-replicas)。

在設置了多節點的服務注冊中心之后,服務提供方還需要做一些簡單的配置才能將服務注冊到Eureka Server集群中。我們以hello-service為例,修改application.properties配置文件,如下所示:

spring.application.name=hello-service eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/

上面的配置主要對eureka.client.serviceUrl.defaultZone屬性做了改動,將注冊中心指向了之前我們搭建的peer1與peer2。

服務的發現與消費

通過上面的內容介紹與實踐,我們已經搭建起微服務架構中的核心組件—服務注冊中心(包括單節點模式和高可用模式)。同時,還對上一章中實現的Spring Boot入門程序做了改造。通過簡單的配置,使該程序注冊到Eureka注冊中心上,成為該服務治理體系下的一個服務,命名為hello-service。現在我們已經有了服務注冊中心和服務提供者,下面就來嘗試構建一個服務消費者,它主要完成兩個目標,發現服務以及消費服務。其中,服務發現的任務由Eureka的客戶端完成,而服務消費的任務由Ribbon完成。Ribbon是一個基于HTTP和TCP的客戶端負載均衡器,它可以在通過客戶端中配置的ribbonServerList服務端列表去輪詢訪問以達到均衡負載的作用。當Ribbon與Eureka聯合使用時,Ribbon的服務實例清單RibbonServerList會被DiscoveryEnabledNIWSServerList重寫,擴展成從Eureka注冊中心中獲取服務端列表。同時它也會用NIWSDiscoveryPing來取代IPing,它將職責委托給Eureka來確定服務端是否已經啟動。在本章中,我們對Ribbon不做詳細的介紹,讀者只需要理解它在Eureka服務發現的基礎上,實現了一套對服務實例的選擇策略,從而實現對服務的消費。下一章我們會對Ribbon做詳細的介紹和分析。 下面我們通過構建一個簡單的示例,看看在Eureka的服務治理體系下如何實現服務的發現與消費。 首先,我們做一些準備工作。啟動之前實現的服務注冊中心eureka-server以及hello-service服務,為了實驗Ribbon的客戶端負載均衡功能,我們通過java-jar命令行的方式來啟動兩個不同端口的hello-service,具體如下:

java -jar hello-service-0.0.1-SNAPSHOT.jar --server.port=8081
java -jar hello-service-0.0.1-SNAPSHOT.jar --server.port=8082

在成功啟動兩個hello-service服務之后,如下圖所示,從Eureka信息面板中可以看到名為HELLO-SERVICE的服務中出現了兩個實例單元,分別是通過命令行啟動的8081端口和8082端口的服務。

創建一個Spring Boot的基礎工程來實現服務消費者,取名為ribbon-consumer,并在pom.xml中引入如下的依賴內容。較之前的hello-service,我們新增了Ribbon模塊的依賴spring-cloud-starter-ribbon。

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

創建應用主類ConsumerApplication,通過@EnableDiscoveryClient注解讓該應用注冊為Eureka客戶端應用,以獲得服務發現的能力

同時,在該主類中創建RestTemplate的Spring Bean實例,并通過@LoadBalanced注解開啟客戶端負載均衡。

@EnableDiscoveryClient @SpringBootApplication public class ConsumerApplication { @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); } }

創建ConsumerController類并實現/ribbon-consumer接口。在該接口中,通過在上面創建的RestTemplate來實現對HELLO-SERVICE服務提供的/hello接口進行調用。**可以看到這里訪問的地址是服務名HELLO-SERVICE,而不是一個具體的地址,**在服務治理框架中,這是一個非常重要的特性,也符合在本章一開始對服務治理的解釋。

@RestController public class ConsumerController { @Autowired RestTemplate restTemplate; @RequestMapping(value = "/ribbon-consumer", method = RequestMethod.GET) public String helloConsumer() { return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody(); } }

在application.properties中配置Eureka服務注冊中心的位置,需要與之前的HELLO-SERVICE一樣,不然是發現不了該服務的,同時設置該消費者的端口為9000,不能與之前啟動的應用端口沖突。

spring.application.name=ribbon-consumer server.port=9000 eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

啟動ribbon-consumer應用后,我們可以在Eureka信息面板中看到,當前除了HELLO-SERVICE之外,還多了我們實現的RIBBON-CONSUMER服務。

通過向http://localhost:9000/ribbon-consumer發起GET請求,成功返回了“Hello World”。

此時,我們可以在ribbon-consumer應用的控制臺中看到如下信息,Ribbon輸出了當前客戶端維護的HELLO-SERVICE的服務列表情況。其中包含了各個實例的位置,Ribbon就是按照此信息進行輪詢訪問,以實現基于客戶端的負載均衡。另外還輸出了一些其他非常有用的信息,如對各個實例的請求總數量、第一次連接信息、上一次連接信息、總的請求失敗數量等。

再嘗試發送幾次請求,并觀察啟動的兩個HELLO-SERVICE的控制臺,可以看到兩個控制臺會交替打印下面的日志,

com.didispace.web.HelloController : /hello, host:PC-201602152056,
service_id:hello-service

這是我們之前在HelloController中實現的對服務信息的輸出,可以用來判斷當前ribbon-consumer對HELLO-SERVICE的調用是否是負載均衡的。

Eureka的一些配置

服務注冊類配置

關于服務注冊類的配置信息,我們可以通過查看org.springframework.cloud.netflix.eureka.EurekaClientConfigBean的源碼來獲得比官方文檔中更為詳盡的內容,這些配置信息都以eureka.client為前綴。下面我們針對一些常用的配置信息做進一步的介紹和說明。
指定注冊中心
將一個Spring Boot應用納入Eureka的服務治理體系,除了引入Eureka的依賴之外,就是在配置文件中指定注冊中心,主要通過eureka.client.serviceUrl參數實現.
該參數的定義如下所示:

private Map<String, String> serviceUrl = new HashMap<>(); { this.serviceUrl.put(DEFAULT_ZONE, DEFAULT_URL); } public static final String DEFAULT_URL = "http://localhost:8761" + DEFAULT_PREFIX + "/"; public static final String DEFAULT_ZONE = "defaultZone";

它的配置值存儲在HashMap類型中,并且設置有一組默認值,默認值的key為defaultZone、value為http://localhost:8761/eureka/。
當構建了高可用的服務注冊中心集群時,我們可以為參數的value值配置多個注冊中心的地址(通過逗號分隔)。比如下面的例子:

eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/

另外,為了服務注冊中心的安全考慮,很多時候我們都會為服務注冊中心加入安全校驗。這個時候,在配置serviceUrl時,需要在value值的URL中加入相應的安全校驗信息,比如http://<username>:<password>@localhost:1111/eureka。
其中,<username>為安全校驗信息的用戶名,<password>為該用戶的密碼。

服務實例類配置

元數據
在org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean的配置信息中,有一大部分內容都是對服務實例元數據的配置,那么什么是服務實例的元數據呢?它是Eureka客戶端在向服務注冊中心發送注冊請求時,用來描述自身服務信息的對象,其中包含了一些標準化的元數據,比如服務名稱、實例名稱、實例IP、實例端口等用于服務治理的重要信息;以及一些用于負載均衡策略或是其他特殊用途的自定義元數據信息。 在使用Spring Cloud Eureka的時候,所有的配置信息都通過org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean進行加載,但在真正進行服務注冊的時候,還是會包裝成com.netflix.appinfo.InstanceInfo對象發送給Eureka服務端。這兩個類的定義非常相似,我們可以直接查看com.netflix.appinfo.InstanceInfo類中的詳細定義來了解原生Eureka對元數據的定義。其中,Map<String,String>metadata=new ConcurrentHashMap<String,String>()是自定義的元數據信息,而其他成員變量則是標準化的元數據信息。Spring Cloud的EurekaInstanceConfigBean對原生元數據對象做了一些配置優化處理,在后續的介紹中,我們也會提到這些內容。 我們可以通過eureka.instance.<properties>=<value>的格式對標準化元數據直接進行配置,其中<properties>就是EurekaInstanceConfigBean對象中的成員變量名。而對于自定義元數據,可以通過eureka.instance.metadataMap.<key>=<value>的格式來進行配置,比如: eureka.instance.metadataMap.zone=shanghai 接下來,我們將針對一些常用的元數據配置做進一步的介紹和說明。

實例名配置

實例名,即InstanceInfo中的instanceId參數,它是區分同一服務中不同實例的唯一標識。在Netflix Eureka的原生實現中,實例名采用主機名作為默認值,這樣的設置使得在同一主機上無法啟動多個相同的服務實例。所以,在Spring Cloud Eureka的配置中,針對同一主機中啟動多實例的情況,對實例名的默認命名做了更為合理的擴展,它采用了如下默認規則:

${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}

對于實例名的命名規則,我們可以通過eureka.instance.instanceId參數來進行配置。比如,在本地進行客戶端負載均衡調試時,需要啟動同一服務的多個實例,如果我們直接啟動同一個應用必然會產生端口沖突。雖然可以在命令行中指定不同的server.port來啟動,但是這樣還是略顯麻煩。實際上,我們可以直接通過設置server.port=0或者使用隨機數server.port=${random.int[10000,19999]}來讓Tomcat啟動的時候采用隨機端口。但是這個時候我們會發現注冊到Eureka Server的實例名都是相同的,這會使得只有一個服務實例能夠正常提供服務。對于這個問題,我們就可以通過設置實例名規則來輕松解決:

eureka.instance.instanceId=${spring.application.name}:${random.int}}

通過上面的配置,利用應用名加隨機數的方式來區分不同的實例,從而實現在同一主機上,不指定端口就能輕松啟動多個實例的效果。

端點配置

在InstanceInfo中,我們可以看到一些URL的配置信息,比如homePageUrl、statusPageUrl、healthCheckUrl,它們分別代表了應用主頁的URL、狀態頁的URL、健康檢查的URL。其中,狀態頁和健康檢查的URL在Spring Cloud Eureka中默認使用了spring-boot-actuator模塊提供的/info端點和/health端點。雖然我們在之前的示例中并沒有對這些端點做具體的設置,但是實際上這些URL地址的配置非常重要。為了服務的正常運作,我們必須確保Eureka客戶端的/health端點在發送元數據的時候,是一個能夠被注冊中心訪問到的地址,否則服務注冊中心不會根據應用的健康檢查來更改狀態(僅當開啟了healthcheck功能時,以該端點信息作為健康檢查標準)。而/info端點如果不正確的話,會導致在Eureka面板中單擊服務實例時,無法訪問到服務實例提供的信息接口。 大多數情況下,我們并不需要修改這幾個URL的配置,但是在一些特殊情況下,比如,為應用設置了context-path,這時,所有spring-boot-actuator模塊的監控端點都會增加一個前綴。所以,我們就需要做類似如下的配置,為/info和/health端點也加上類似的前綴信息:

management.context-path=/hello eureka.instance.statusPageUrlPath=\${management.context-path}/info eureka.instance.healthCheckUrlPath=${management.context-path}/health

另外,有時候為了安全考慮,也有可能會修改/info和/health端點的原始路徑。這個時候,我們也需要做一些特殊的配置,比如像下面這樣:

endpoints.info.path=/appInfo endpoints.health.path=/checkHealth eureka.instance.statusPageUrlPath=/${endpoints.info.path} eureka.instance.healthCheckUrlPath=/${endpoints.health.path}

在上面所舉的兩個示例中,我們使用了eureka.instance.statusPageUrlPath和eureka.instance.healthCheckUrlPath參數,這兩個配置值有一個共同特點,它們都使用相對路徑來進行配置。由于Eureka的服務注冊中心默認會以HTTP的方式來訪問和暴露這些端點,因此當客戶端應用以HTTPS的方式來暴露服務和監控端點時,相對路徑的配置方式就無法滿足需求了。所以,Spring Cloud Eureka還提供了絕對路徑的配置參數,具體示例如下所示:

eureka.instance.statusPageUrl=https://${eureka.instance.hostname}/info eureka.instance.healthCheckUrl=https://${eureka.instance.hostname}/health eureka.instance.homePageUrl=https://${eureka.instance.hostname}/

Eureka服務治理基礎架構原理

Eureka服務治理基礎架構的三個核心要素:
服務注冊中心:Eureka提供的服務端,提供服務注冊與發現的功能,也就是在上一節中我們實現的eureka-server。
服務提供者:提供服務的應用,可以是Spring Boot應用,也可以是其他技術平臺且遵循Eureka通信機制的應用。它將自己提供的服務注冊到Eureka,以供其他應用發現,也就是在上一節中我們實現的HELLO-SERVICE應用。
服務消費者:消費者應用從服務注冊中心獲取服務列表,從而使消費者可以知道去何處調用其所需要的服務,在上一節中使用了Ribbon來實現服務消費,另外后續還會介紹使用Feign的消費方式。 很多時候,客戶端既是服務提供者也是服務消費者。

服務治理機制
在體驗了Spring Cloud Eureka通過簡單的注解配置就能實現強大的服務治理功能之后,我們來進一步了解一下Eureka基礎架構中各個元素的一些通信行為,以此來理解基于Eureka實現的服務治理體系是如何運作起來的。以下圖為例,其中有這樣幾個重要元素: “服務注冊中心-1”和“服務注冊中心-2”,它們互相注冊組成了高可用集群。 “服務提供者”啟動了兩個實例,一個注冊到“服務注冊中心-1” 上,另外一個注冊到“服務注冊中心-2”上。 還有兩個“服務消費者”,它們也都分別只指向了一個注冊中心

根據上面的結構,下面我們來詳細了解一下,從服務注冊開始到服務調用,及各個元素所涉及的一些重要通信行為。
服務提供者

—服務注冊
“服務提供者”在啟動的時候會通過發送REST請求的方式將自己注冊到Eureka Server上,同時帶上了自身服務的一些元數據信息。Eureka Server接收到這個REST請求之后,將元數據信息存儲在一個雙層結構Map中,其中第一層的key是服務名,第二層的key是具體服務的實例名。(我們可以回想一下之前在實現Ribbon負載均衡的例子中,Eureka信息面板中一個服務有多個實例的情況,這些內容就是以這樣的雙層Map形式存儲的。) 在服務注冊時,需要確認一下eureka.client.register-with-eureka=true參數是否正確,該值默認為true。若設置為false將不會啟動注冊操作。

—服務同步

如架構圖中所示,這里的兩個服務提供者分別注冊到了兩個不同的服務注冊中心上,也就是說,它們的信息分別被兩個服務注冊中心所維護。此時,由于服務注冊中心之間因互相注冊為服務,當服務提供者發送注冊請求到一個服務注冊中心時,它會將該請求轉發給集群中相連的其他注冊中心,從而實現注冊中心之間的服務同步。通過服務同步,兩個服務提供者的服務信息就可以通過這兩臺服務注冊中心中的任意一臺獲取到。

—服務續約

在注冊完服務之后,服務提供者會維護一個心跳用來持續告訴Eureka Server:“我還活著”,以防止Eureka Server的“剔除任務”將該服務實例從服務列表中排除出去,我們稱該操作為服務續約(Renew)。 關于服務續約有兩個重要屬性,我們可以關注并根據需要來進行調整
eureka.instance.lease-renewal-interval-in-seconds=30
eureka.instance.lease-expiration-duration-in-seconds=90 eureka.instance.lease-renewal-interval-in-seconds參數用于定義服務續約任務的調用間隔時間,默認為30秒。eureka.instance.lease-expiration-duration-in-seconds參數用于定義服務失效的時間,默認為90秒。 服務消費者取服務 到這里,在服務注冊中心已經注冊了一個服務,并且該服務有兩個實例。當我們啟動服務消費者的時候,它會發送一個REST請求給服務注冊中心,來獲取上面注冊的服務清單。為了性能考慮,Eureka Server會維護一份只讀的服務清單來返回給客戶端,同時該緩存清單會每隔30秒更新一次。 獲取服務是服務消費者的基礎,所以必須確保eureka.client.fetch-registry=true參數沒有被修改成false,該值默認為true。若希望修改緩存清單的更新時間,可以通過eureka.client.registry-fetch-interval-seconds=30參數進行修改,該參數默認值為30,單位為秒。

服務消費者

----獲取服務
到這里,在服務注冊中心已經注冊了一個服務,并且該服務有兩個實例。當我們啟動服務消費者的時候,它會發送一個REST請求給服務注冊中心,來獲取上面注冊的服務清單。為了性能考慮,Eureka Server會維護一份只讀的服務清單來返回給客戶端,同時該緩存清單會每隔30秒更新一次。 獲取服務是服務消費者的基礎,所以必須確保eureka.client.fetch-registry=true參數沒有被修改成false,該值默認為true。若希望修改緩存清單的更新時間,可以通過eureka.client.registry-fetch-interval-seconds=30參數進行修改,該參數默認值為30,單位為秒。

----服務調用

服務消費者在獲取服務清單后,通過服務名可以獲得具體提供服務的實例名和該實例的元數據信息。因為有這些服務實例的詳細信息,所以客戶端可以根據自己的需要決定具體調用哪個實例,在Ribbon中會默認采用輪詢的方式進行調用,從而實現客戶端的負載均衡。

----服務下線

在系統運行過程中必然會面臨關閉或重啟服務的某個實例的情況,在服務關閉期間,我們自然不希望客戶端會繼續調用關閉了的實例。所以在客戶端程序中,當服務實例進行正常的關閉操作時,它會觸發一個服務下線的REST請求給Eureka Server,告訴服務注冊中心:“我要下線了”。服務端在接收到請求之后,將該服務狀態置為下線(DOWN),并把該下線事件傳播出去。

服務注冊中心

----失效剔除
有些時候,我們的服務實例并不一定會正常下線,可能由于內存溢出、網絡故障等原因使得服務不能正常工作,而服務注冊中心并未收到“服務下線”的請求。為了從服務列表中將這些無法提供服務的實例剔除,Eureka Server在啟動的時候會創建一個定時任務,默認每隔一段時間(默認為60秒)將當前清單中超時(默認為90秒)沒有續約的服務剔除出去。

---- 自我保護
當我們在本地調試基于Eureka的程序時,基本上都會碰到這樣一個問題,在服務注冊中心的信息面板中出現類似下面的紅色警告信息: EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE. 實際上,該警告就是觸發了Eureka Server的自我保護機制。之前我們介紹過,服務注冊到Eureka Server之后,會維護一個心跳連接,告訴Eureka Server自己還活著。Eureka Server在運行期間,會統計心跳失敗的比例在15分鐘之內是否低于85%,如果出現低于的情況(在單機調試的時候很容易滿足,實際在生產環境上通常是由于網絡不穩定導致),Eureka Server會將當前的實例注冊信息保護起來,讓這些實例不會過期,盡可能保護這些注冊信息。但是,在這段保護期間內實例若出現問題,那么客戶端很容易拿到實際已經不存在的服務實例,會出現調用失敗的情況,所以客戶端必須要有容錯機制,比如可以使用請求重試、斷路器等機制。 由于本地調試很容易觸發注冊中心的保護機制,這會使得注冊中心維護的服務實例不那么準確。所以,我們在本地進行開發的時候,可以使用eureka.server.enable-self-preservation=false參數來關閉保護機制,以確保注冊中心可以將不可用的實例正確剔除。

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的【学习笔记】Eureka服务治理代码实例、相关配置和原理机制详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。