Spring Cloud Eureka是Spring Cloud Netflix微服務套件中的一部分,它基於Netflix Eureka做了二次封裝,主要負責完成微服務架構中的服務治理功能。
Eureka分為服務端和客戶端。
其中Eureka服務端,我們也稱為服務注冊中心。如果Eureka以集群部署,當集群出現分片故障時,那么Eureka就轉入自我保護模式,它允許在分片故障期間繼續提供服務的注冊與發現,當故障分片恢復時,集群中的其他分片會將它的狀態再同步回來(不同可用區域的服務注冊中心通過異步模式互相復制各自的狀態),這意味着在任意給定時間點每個實例關於所有服務的狀態是有細微差別的。
Eureka客戶端,主要處理服務的注冊與發現,客戶端服務通過注解和參數配置的方式,嵌入在客戶端應用程序的代碼中,在應用程序運行時,Eureka客戶端向注冊中心注冊自身提供的服務並周期性的發送心跳來更新它的服務租約。同時,它也能從服務端查詢當前注冊的服務信息並把它們緩存到本地並周期性的刷新服務狀態。
一、構建服務注冊中心
1、單節點注冊中心
(1)創建一個eureka server項目,創建步驟和創建一個springboot項目一樣,只有在最后選擇依賴時,使用Eureka Server依賴即可。也可以直接創建Spring Boot項目,自行添加對Sureka Server的依賴,
對於springCloud版本不明白的話,可以看下https://zhuanlan.zhihu.com/p/63653091
(2)創建完畢后,項目的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>lcl.spring.cloud.demo</groupId>
<artifactId>eureka-server-one</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-server-one</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(3)然后,需要啟動Spring Cloud Eureka,即在項目主函數上添加@EnableEurekaServer注解
package lcl.spring.cloud.demo.eurekaserver.one; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class EurekaServerOneApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerOneApplication.class, args); } }
(4)最后一步,就是需要配置相關內容
server:
port: 1111 eureka: instance: hostname: localhost client: register-with-eureka: false fetch-registry: false service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
配置內容如上所示,具體說明如下:
server.port:由於是在本地啟動,后續需要啟動多個項目,因此調整啟動參數
eureka.instance.hostname: 設置本機名稱
eureka.client.register-with-eureka: 是否向注冊中心注冊自己,由於該項目是注冊中心,因此不向注冊中心注冊自己
eureka.client.fetch-registry: 是否需要檢索服務,由於該項目是注冊中心,因此不需要去檢索服務
eureka.client.service-url.defaultZone: 這只注冊中心地址
(5)所有配置完畢后,啟動項目,訪問:http://localhost:1111/
如上圖所示,Instances currently registered with Eureka欄是空的,說明該注冊中心還沒有任務服務注冊。
2、高可用注冊中心
(1)新搭建一個與eureka-server-one一樣的項目eureka-server-two(由於是在本地測試,因此需要多個項目,如果是在服務器,使用springboot的多環境--profile部署即可)
(2)修改eureka-server-one項目配置文件,讓其注冊中心指向eureka-server-two項目
server:
port: 1111 eureka: instance: hostname: eureka-server1 client: register-with-eureka: false fetch-registry: false service-url: defaultZone: http://eureka-server2:1112/eureka/ #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ spring: application: name: eureka-server
(3)修改eureka-server-two項目配置文件,讓其注冊中心指向eureka-server-one項目
server:
port: 1112 eureka: instance: hostname: eureka-server2 client: register-with-eureka: false fetch-registry: false service-url: defaultZone: http://eureka-server1:1111/eureka/ #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ spring: application: name: eureka-server
(4)修改host文件
127.0.0.1 eureka-server1
127.0.0.1 eureka-server2
(5)啟動eureka-server-one和eureka-server-two兩個項目,訪問:http://localhost:1111/
由上圖可見,訪問eureka-server-one,發現已經有了eureka-server2的節點,同樣的,訪問eureka-server-two,也會存在eureka-server1節點。
(6) 對於單節點的配置,我們設置eureka.client.register-with-eureka和eureka.client.fetch-registry均為false,為了高可用,可以將其設置為true,以達到注冊中心相互向對方注冊自己的服務,形成一組互相注冊的注冊中心,以實現服務清單的互相同步。
調整配置參數后,重新啟動兩個注冊中心,訪問:http://localhost:1111/
由上圖可以看到,已經有兩個Eureka-server項目注冊到了注冊中心
二、服務注冊與服務發現
1、單節點注冊中心服務注冊
(1)新建springboot項目,然后添加對eureka-client的依賴
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>lcl.spring.cloud.demo</groupId>
<artifactId>eureka-client-one</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-client-one</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(2)創建API請求類
package lcl.spring.cloud.demo.eurekaclient.one.api;
import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/v1") @Slf4j public class HelloApi { @GetMapping("/hello") public String hello(){ return "hello......"; } }
(3)在項目主函數中添加@EnableDiscoveryClient注解,啟用Eureka Client
package lcl.spring.cloud.demo.eurekaclient.one;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaClientOneApplication { public static void main(String[] args) { SpringApplication.run(EurekaClientOneApplication.class, args); } }
(4)配置客戶端名稱及注冊中心地址
spring:
application:
name: eureka-client eureka: client: service-url: defaultZone: http://localhost:1111/eureka/ instance: hostname: lcl-pc1 server: port: 8081
(5)啟動eureka-client項目,出現以下日志,說明服務注冊成功:
(6)重新訪問http://localhost:1111/,可以發現,服務已經注冊
2、高可用注冊中心服務注冊
(1)只需要調整配置文件中注冊中心地址和eureka.instance.hostname即可,多個注冊中心使用逗號分隔
spring:
application:
name: eureka-client eureka: client: service-url: defaultZone: http://localhost:1111/eureka/,http://localhost:1112/eureka/ instance: hostname: lcl-pc2 server: port: 8081
(2)啟動eureka-client-one項目,並重新訪問注冊中心:http://localhost:1111/
(3)如果我們不想使用主機名來定義注冊中心的地址,也可以使用IP地址的形式,開啟使用IP地址的形式,需要配置如下參數:
eureka.instance.eureka.instance.prefer-ip-address: true
3、服務發現與服務消費
(1)為了模擬多個服務提供者,根據項目eureka-client-one復制項目eureka-client-two,調整eureka-client-two的端口號為8082(此處主要是因為在本地執行,如果在linux服務器上執行,可以使用springboot的多環境部署),運行eureka-client-two項目,訪問:http://localhost:1111/,可以發現兩個項目均已注冊。
(2)新建一個項目,用於消費該服務,需要依賴eureka-client和ribbon,整體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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-cloud-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(3)配置注冊中心地址、項目端口號、項目名稱等內容
server:
port: 5551 spring: application: name: ribbon-concumer eureka: client: service-url: defaultZone: http://localhost:1111/eureka/,http://localhost:1112/eureka/
(4)項目主函數添加@EnableDiscoveryClient,同時在主函數中創建RestTemplate實例,並使用@LoadBalanced開啟客戶端負載均衡
package com.example.spring.cloud.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplication
public class SpringCloudDemoApplication { @Bean @LoadBalanced RestTemplate restTemplate(){ return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(SpringCloudDemoApplication.class, args); } }
(5)創建一個api類,該類中使用RestTemplate請求服務提供者
package com.example.spring.cloud.demo.api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/v1") public class HelloApi { @Autowired RestTemplate restTemplate; @GetMapping("/helloConsumer") public String getStr(){ return restTemplate.getForEntity("http://EUREKA-CLIENT/v1/hello",String.class).getBody(); } }
(6)由於在eureka-client的兩個項目中,分別配置了eureka.instance.hostname為lcl1-pc1和lcl-pc2,因此需要設置host
127.0.0.1 lcl-pc1
127.0.0.1 lcl-pc2
(7)啟動新項目,訪問注冊中心:http://localhost:1111/
可以發現新增加的項目也注冊到注冊中心上了
(8)訪問新項目接口:http://localhost:5551/v1/helloConsumer,可以發現返回結果即是服務提供者的返回。
這里可以給兩個eureka-client的hello方法加上日志輸出,可以發現,調用新項目接口時,是輪詢訪問兩個client項目的。