SpringCloud之Eureka註冊中心
Eureka為什麼出現?
微服務user-service對外提供服務,需要對外暴露自己的地址。而consumer(呼叫者)需要記錄服務提供者的地址。將來地址出現變更,還需要及時更新。這在服務較少的時候並不覺得有什麼,但是在現在日益複雜的網際網路環境,一個專案肯定會拆分出十幾,甚至數十個微服務。此時如果還人為管理地址,不僅開發困難,將來測試、釋出上線都會非常麻煩,這與DevOps的思想是背道而馳的。
Eureka做什麼?
Eureka負責管理、記錄服務提供者的資訊。服務呼叫者無需自己尋找服務,而是把自己的需求告訴Eureka,然後Eureka會把符合你需求的服務告訴你。
同時,服務提供方與Eureka之間通過“心跳”
這就實現了服務的自動註冊、發現、狀態監控。
Eureka實現原理圖
-
-
提供者:啟動後向Eureka註冊自己資訊(地址,提供什麼服務)
-
消費者:向Eureka訂閱服務,Eureka會將對應服務的所有提供者地址列表傳送給消費者,並且定期更新
-
MsgController:
packagecom.itcast.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; /** * @Classname MsgController * @Description TODO * @Date 2020/12/18 10:24 * @Created by Administrator*/ @Controller public class MsgController { @RequestMapping("hello") @ResponseBody public String hello(){ return "hello spring-cloud~"; } }
application.yml:
server:
port: 8888
spring:
application:
name: msg-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
pom:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud-demo</artifactId> <groupId>com.itcast</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>msg-server</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
啟動類:
package com.itcast; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; /** * @Classname MsgApplication * @Description TODO * @Date 2020/12/18 10:09 * @Created by Administrator */ @EnableDiscoveryClient @SpringBootApplication public class ServerApplication { public static void main(String[] args) { SpringApplication.run(ServerApplication.class,args); } @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
2、msg-consumer微服務:
MsgController:
package com.itcast.controller; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.netflix.ribbon.proxy.annotation.Hystrix; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.client.RestTemplate; import java.util.List; /** * @Classname MsgController * @Description TODO * @Date 2020/12/18 10:21 * @Created by Administrator */ @Controller public class MsgController { @Autowired RestTemplate restTemplate; @Autowired DiscoveryClient discoveryClient; @RequestMapping("hello") @ResponseBodypublic String hello(){ List<ServiceInstance> instances = discoveryClient.getInstances("msg-server"); ServiceInstance serviceInstance = instances.get(0); String url="http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/hello"; String forObject = restTemplate.getForObject(url, String.class); return forObject; } }
application.yml
server:
port: 8080
spring:
application:
name: msg-consumer
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
pom:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud-demo</artifactId> <groupId>com.itcast</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>msg-consumer</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> </project>
啟動類:
package com.itcast; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.SpringCloudApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; /** * @Classname Application * @Description TODO * @Date 2020/12/18 10:19 * @Created by Administrator */ //@EnableDiscoveryClient //@SpringBootApplication //@EnableHystrix @SpringCloudApplication public class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class); } @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); } }
3、Eureka註冊中心
啟動類:
package com.itcast; //import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; /** * @Classname EurekaApplication * @Description TODO * @Date 2020/12/18 11:29 * @Created by Administrator */ @SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class); } }
application.yml
server:
port: 10086
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10087/eureka
# fetch-registry: false
# register-with-eureka: false
pom
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud-demo</artifactId> <groupId>com.itcast</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>eureka-server</artifactId> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> </project>
Eureka架構中的三個核心角色
-
服務註冊中心
Eureka的服務端應用,提供服務註冊和發現功能
-
服務提供者
提供服務的應用,可以是SpringBoot應用,也可以是其它任意技術實現,只要對外提供的是Rest風格服務即可。
-
服務消費者
消費應用從註冊中心獲取服務列表,從而得知每個服務方的資訊,知道去哪裡呼叫服務方。
多個Eureka之間的配置
Eureka1:
Eureka2:
服務續約(心跳)配置
eureka:
instance:
lease-expiration-duration-in-seconds: 90
lease-renewal-interval-in-seconds: 30
獲取服務列表
eureka:
client:
registry-fetch-interval-seconds: 5
失效剔除
有些時候,我們的服務提供方並不一定會正常下線,可能因為記憶體溢位、網路故障等原因導致服務無法正常工作。Eureka Server需要將這樣的服務剔除出服務列表。因此它會開啟一個定時任務,每隔60秒對所有失效的服務(超過90秒未響應)進行剔除。
可以通過eureka.server.eviction-interval-timer-in-ms
引數對其進行修改,單位是毫秒,生成環境不要修改。
自我保護
我們關停一個服務,就會在Eureka面板看到一條警告:
這是觸發了Eureka的自我保護機制。當一個服務未按時進行心跳續約時,Eureka會統計最近15分鐘心跳失敗的服務例項的比例是否超過了85%。在生產環境下,因為網路延遲等原因,心跳失敗例項的比例很有可能超標,但是此時就把服務剔除列表並不妥當,因為服務可能沒有宕機。Eureka就會把當前例項的註冊資訊保護起來,不予剔除。生產環境下這很有效,保證了大多數服務依然可用。
但是這給我們的開發帶來了麻煩, 因此開發階段我們都會關閉自我保護模式:
eureka:
server:
enable-self-preservation: false # 關閉自我保護模式(預設為開啟)
eviction-interval-timer-in-ms: 1000 # 掃描失效服務的間隔時間(預設為60*1000ms)