搭建 Spring Cloud Eureka Server 高可用註冊中心叢集
什麼是註冊中心
Eureka Server 在微服務中承擔的角色是服務註冊中心,也是最最基礎的核心設施之一。從“Eureka”單詞的含義**“我找到了!我發現了!”可以看出,其實 Eureka 就是用來實現服務註冊、服務發現的工具**,和 dubbo 這類的分散式服務治理框架類似。各種獨立的微服務將自己註冊到 Eureka Server,Eureka Client 則提供了服務發現的能力。
本文目的
Eureka的特點在於可以相互註冊,形成高可用註冊中心叢集。這篇文章記錄一下本地搭建兩個 Eureka Server 註冊中心,讓他們互相註冊自己到對方的服務中心,最後建立一個名為 hello-service
開發環境
- IntelliJ IDEA 2018.1.6
- Maven-3.5.3
- JDK8
- spring cloud版本:Finchley.RELEASE
- spring-boot-starter版本:2.0.3.RELEASE
準備工作
由於是本地在同一臺機器上模擬搭建兩個註冊中心,需要修改 HOSTS 檔案,這裡以 Win10 系統為例,HOSTS 檔案的路徑在 C:\Windows\System32\drivers\etc
。
在末尾追加內容如下,表示訪問 eureka-server1 和 eureka-server2 時,等於訪問 127.0.0.1:
127.0.0.1 eureka-server1
127.0.0.1 eureka-server2
第1步:搭建註冊中心1
在IDEA建立工程,取名為 cat-spring-cloud-eureka-server-1
,通過Spring初始化工具,新增 eureka server 依賴(這裡就不貼圖演示了):
pom.xml:
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>me.zebe</groupId>
<artifactId>cat-spring-cloud-eureka-server-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cat-spring-cloud-eureka-server-1</name>
<description>pring Cloud Eureka 註冊中心1</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</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>
</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>
application.yml:
server:
port: 20001
eureka:
instance:
# eureka-server1 是一個別名,需要在 hosts 檔案裡面將其對映為 127.0.0.1
hostname: eureka-server1
client:
serviceUrl:
# 將自身反註冊到eureka-server2,利用相互註冊,形成高可用註冊中心叢集
defaultZone: http://eureka-server2:20002/eureka/
# 將當前服務註冊中心本身也作為服務註冊到別的服務註冊中心(eureka-server2)
register-with-eureka: true
# 不將當前服務註冊中心本身也作為服務註冊到別的服務註冊中心(如設為false,則 eureka-server2 中,unavailable-replicas 會包含此註冊中心)
# register-with-eureka: false
應用啟動器類:
package me.zebe.cat.spring.cloud.eureka.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* Spring Cloud Eureka 註冊中心1
*
* @author Zebe
*/
@EnableEurekaServer
@SpringBootApplication
public class CatSpringCloudEurekaServer1Application {
/**
* 執行入口
* @param args 執行引數
*/
public static void main(String[] args) {
SpringApplication.run(CatSpringCloudEurekaServer1Application.class, args);
System.out.println("Spring Cloud Eureka 註冊中心1 -> 已啟動。");
}
}
執行該類,啟動時會丟擲異常,提示找不到 eureka-server2,這是因為 eureka-server2 我們沒有啟動,不用管它。
第2步:搭建註冊中心2
第二個註冊中心和第一個註冊中心沒有本質上的區別,只不過是換了執行埠和註冊地址。將第二個工程取名為 cat-spring-cloud-eureka-server-2
。
pom.xml:
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>me.zebe</groupId>
<artifactId>cat-spring-cloud-eureka-server-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cat-spring-cloud-eureka-server-2</name>
<description>pring Cloud Eureka 註冊中心2</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</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>
</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>
application.yml:
server:
port: 20002
eureka:
instance:
# eureka-server2 是一個別名,需要在 hosts 檔案裡面將其對映為 127.0.0.1
hostname: eureka-server2
client:
serviceUrl:
# 將自身反註冊到eureka-server1,利用相互註冊,形成高可用註冊中心叢集
defaultZone: http://eureka-server1:20001/eureka/
# 將當前服務註冊中心本身也作為服務註冊到別的服務註冊中心(eureka-server1)
register-with-eureka: true
# 不將當前服務註冊中心本身也作為服務註冊到別的服務註冊中心(如設為false,則 eureka-server1 中,unavailable-replicas 會包含此註冊中心)
# register-with-eureka: false
應用啟動器類:
package me.zebe.cat.spring.cloud.eureka.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* Spring Cloud Eureka 註冊中心2
*
* @author Zebe
*/
@EnableEurekaServer
@SpringBootApplication
public class CatSpringCloudEurekaServer2Application {
/**
* 執行入口
* @param args 執行引數
*/
public static void main(String[] args) {
SpringApplication.run(CatSpringCloudEurekaServer2Application.class, args);
System.out.println("Spring Cloud Eureka 註冊中心2 -> 已啟動。");
}
}
執行該類,只要 hosts 檔案裡面按照配置裡面修改好了,啟動時就不會報異常了。
第3步:啟動註冊中心
先啟動註冊中心1,忽略報錯資訊,然後再啟動註冊中心2。分別訪問 http://127.0.0.1:20001 和 http://127.0.0.1:20002 。
可以看到兩個註冊中心已經互相註冊,配置檔案的註釋裡面已經寫清楚瞭如何觀察。
註冊中心1:
註冊中心2:
第4步:製作快速啟動指令碼(非必需)
將這兩個註冊中心工程,分別用Maven打包成JAR檔案,然後寫好批處理檔案,後面就可以一健啟動了,比如我為這兩個應用寫了批處理檔案,如下所示:
- 01 一健啟動 Eureka 註冊中心-1 執行在 20001.cmd
- 02 一健啟動 Eureka 註冊中心-2 執行在 20002.cmd
內容參考:
title EurekaServer1-20001
java -jar cat-spring-cloud-eureka-server-1-0.0.1-SNAPSHOT.jar
title EurekaServer2-20002
java -jar cat-spring-cloud-eureka-server-2-0.0.1-SNAPSHOT.jar
強烈建議寫為批處理檔案,因為如果要本地搭建為服務學習環境,註冊中心是首先要啟動的基礎設施。
第5步:編寫 HELLO-SERVICE 微服務
建立工程,取名為 cat-spring-cloud-hello-service
。該工程很簡單,需要依賴於 eureka client 來實現服務發現,注意需要引用 starter-web 提供WEB訪問功能。
pom.xml:
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>me.zebe</groupId>
<artifactId>cat-spring-cloud-hello-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cat-spring-cloud-hello-service</name>
<description>Spring Cloud Hello-Service 服務實現</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- spring-boot-starter-web -->
<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>
</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>
application.yml:
server:
port: 8001
spring:
application:
name: hello-service
eureka:
client:
serviceUrl:
# 如果這裡只配置一個服務註冊中心 eureka-server1,那麼當 eureka-server1 掛掉,服務便無法註冊上去
# defaultZone: http://eureka-server1:20001/eureka/
# 因此,通常的做法是,將註冊中心的地址寫成多個(用逗號隔開時,不要有空格,不然可能會報解析錯誤)
defaultZone: http://eureka-server1:20001/eureka/,http://eureka-server1:20002/eureka/
# 將當前服務註冊到eureka服務註冊中心,這樣消費者就可以發現服務
register-with-eureka: true
# 如果設定為false,則不會註冊到服務中心
#register-with-eureka: false
應用啟動器類:
package me.zebe.cat.spring.cloud.service.hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* Spring Cloud {Hello-Service} 服務提供者
*
* @author Zebe
*/
@EnableEurekaClient
@SpringBootApplication
public class CatSpringCloudEurekaHelloServiceApplication {
/**
* 執行入口
* @param args 執行引數
*/
public static void main(String[] args) {
SpringApplication.run(CatSpringCloudEurekaHelloServiceApplication.class, args);
System.out.println("Spring Cloud Eureka {Hello-Service} 服務提供者 -> 已啟動。");
}
}
服務提供控制器類:
package me.zebe.cat.spring.cloud.service.hello;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* {Hello-Service} 服務提供者控制器
*
* @author Zebe
*/
@RestController
public class HelloServiceController {
@Value("${server.port}")
private int port;
/**
* Hello
* @return 返回字串
*/
@GetMapping("/hello")
public String hello() {
// 返回值裡面顯示當前的埠號,這樣可以用來測試單個服務節點掛掉之後的執行情況
return "{Hello} From " + port;
}
}
啟動該服務,觀察註冊中心,可以看到服務註冊成功。到此為止,一個簡單的微服務註冊例子就完成了。
服務執行截圖:
本文首發於個人獨立部落格,文章連結:http://www.zebe.me/spring-cloud-eureka-server