Spring Cloud Eureka-服務註冊與發現
Spring Cloud是目前用於開發微服務的主流框架之一,我們都知道在微服務架構中最為基礎、核心的模塊,就是服務註冊與發現。
在Spring Cloud裏我們可以使用它的Eureka模塊來實現服務註冊與發現,Spring Cloud Eureka是基於Netflix Eureka做了二次封裝,它主要負責完成各個微服務實例的自動化註冊和發現功能。
Eureka由兩個組件組成:
- Eureka Server(註冊中心)
- Eureka Client (服務註冊)
分布式系統中為什麽需要服務發現:
在實際的分布式環境下,架構規模往往不再是幾臺服務器,而是每個獨立服務都跑在多臺機器上。例如A服務部署在10臺機器上,B服務也部署在10臺機器上,C服務部署在5臺機器上。
現在A服務的一些功能需要調用B服務來實現,那麽問題來了,A服務要如何才能調用B服務呢?通常情況下,我們可以想到將B服務所在的所有機器地址,通過配置文件來配置到A服務中,使其能夠通過配置好的地址去發現並調用B服務。
這也的確是一個可行的方法,但是這些機器的地址都是有可能發生變化的,而且在生產環境中也會出現部分服務宕機的情況,這樣就有可能導致一些連鎖效應。隨著業務的擴展,機器也會越來越多,也沒辦法再手動通過配置文件這種方式來配置機器地址了。
鑒於人類的懶惰天性。。。呸,鑒於人類對高效工作、美好生活的追求。所以專門用於服務註冊與發現的工具被一一開發出來。有了服務治理框架後,服務發現就可以交由它來自動完成。這時候A服務只需要到註冊中心進行服務註冊,同樣的B服務也到註冊中心進行服務註冊。註冊之後,註冊中心會通過類似心跳機制來確認服務的存活。如果確認某個服務宕機後,註冊中心會把宕機的服務剔除掉。當A服務要調用B服務的時候,則到註冊中心去獲取B服務的調用地址即可,B服務調用A服務也是同理。註冊中心就相當於一個服務與服務之間的橋梁或者說中間人,可以說幫我們管理了服務之間瑣事。
Eureka服務治理體系如下:
Spring Cloud官網地址如下:
https://projects.spring.io/spring-cloud/
Eureka Server
廢話不多說,本小節我們來搭建一個Eureka Server,即服務註冊中心。打開IDEA,新建一個Spring Initializr項目:
勾選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>org.zero</groupId> <artifactId>eureka</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>eureka</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.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.SR1</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>
註:SpringBoot與SpringCloud組件的版本是有一個對應關系的,這個在官網上有詳細的對照圖。值得註意的是,SpringCloud不是以2.0.1這種數字的方式來標識版本號,而是以倫敦地鐵站的名稱來標識版本號,並且這些名稱是符合字母順序的。
項目創建好後,我們可以試著啟動看看,但是在啟動之前需要在啟動類中加上@EnableEurekaServer
註解,表示啟用Eureka Server,否則訪問就會報404。代碼如下:
package org.zero.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
啟動項目後,能夠訪問到如下Eureka註冊中心的頁面代表成功:
此時雖然能夠正常訪問到註冊中心的頁面,但是會發現控制臺一直在報錯,提示Cannot execute request on any known server
。這是因為這個Eureka Server既是server的同時,也是一個client,它也是需要把自己註冊到一個註冊中心去的。因為我們並沒有配置註冊中心的地址,所以它沒辦法註冊自己就會報這個錯誤。
既然如此,我們只需配置一下註冊中心的地址即可,編輯application.yml配置文件內容如下:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/ # 指定註冊中心的url
register-with-eureka: false # 指定不進行註冊操作,默認為true,若進行註冊的話,會顯示在Eureka信息面板上
server:
enable-self-preservation: false # 禁用eureka server的自我保護機制,建議在生產環境下打開此配置
spring:
application:
name: eureka # 指定應用的名稱
server:
port: 8761 # 指定項目的端口號
註:由於server和client是采用心跳機制來確認存活的,所以在啟動項目的過程可能依舊會報錯。但是只要啟動後不是一直報錯,並且能正常訪問Eureka信息面板頁面的話,則代表項目是在正常運行的
Eureka Client的使用
在上一小節中,我們簡單介紹了如何創建、配置Eureka Server項目。既然我們已經知道了如何搭建Eureka Server,那麽本小節我們將介紹Eureka Client的使用,會簡單演示一下如何通過Eureka Client進行服務註冊。
同樣的,使用IDEA創建一個Spring Initializr項目,只不過在勾選模塊的時候需要選擇Eureka Discovery,如下:
項目生成的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>org.zero.eureka</groupId>
<artifactId>client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>client</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.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.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</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>
項目的依賴都加載完成後,在啟動類中加上@EnableDiscoveryClient
,聲明這是一個eureka client,否則不會進行服務註冊:
package org.zero.eureka.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
接著就是在application.yml配置文件中,配置註冊中心即eureka server的地址,以及項目的名稱和啟動端口號。如下:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: eureka-client
server:
port: 9088
完成以上配置後,即可啟動項目。但是我這裏啟動項目的時候失敗了,控制臺輸出如下警告信息:
Invocation of destroy method failed on bean with name ‘scopedTarget.eurekaClient‘: org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name ‘eurekaInstanceConfigBean‘: Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
這是因為client裏不包含Tomcat的依賴,所以Spring容器無法創建一些實例,從而導致項目無法啟動,只需在pom.xml文件中,加上web依賴即可:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
項目啟動成功後,可以在eureka server的信息面板中查看到已註冊的實例信息,如下:
Eureka的高可用
高可用是在服務架構設計中,頻繁出現的詞匯。微服務架構裏自然也一樣需要保證服務的高可用性,所以本小節將簡單說明一下Eureka是如何實現高可用的。
在實際生產環境中服務器是很脆弱的,單臺服務器肯定是無法滿足高可用的需求,為了保證高可用性我們通常會準備多臺服務器。但可以發現上文中所搭建的eureka server是單機的,若這個eureka server宕機,則會導致與之關聯的全部微服務發生故障。
既然單機無法保證高可用,那麽我們就加多一臺機器好了,然後讓這兩個eureka server互相進行關聯。例如我現在有兩臺eureka server。一臺名叫eureka-server01跑在8761端口上,另一臺名叫eureka-server02跑在8762端口上。然後只需要兩個步驟即可實現高可用:
- 1.編輯這兩臺eureka server的配置文件,讓它們的註冊地址互相指向,即可關聯在一起
- 2.在eureka client的配置文件中,配置上這兩臺eureka server的地址,讓client能夠同時註冊到這兩臺eureka server上。這樣即便其中一臺eureka server掛掉,另一臺依舊可以繼續工作
1.編輯兩臺eureka server的配置文件,eureka-server01:
eureka:
client:
service-url:
defaultZone: http://localhost:8762/eureka/ # 指向eureka-server02的url
register-with-eureka: false
server:
enable-self-preservation: false
spring:
application:
name: eureka-server01
server:
port: 8761
eureka-server02:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/ # 指向eureka-server01的url
register-with-eureka: false
server:
enable-self-preservation: false
spring:
application:
name: eureka-server02
server:
port: 8762
2.編輯eureka client的配置文件,多個url使用英文逗號分隔:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
spring:
application:
name: eureka-client
server:
port: 9088
如果項目規模比較大,有兩個以上的eureka server,那該如何在配置文件中配置呢?其實只需要每臺eureka server分別配置除自己之外的eureka server機器,然後eureka client則配置所有的eureka server地址即可。如下圖:
配置文件示例,eureka-server01:
eureka:
client:
service-url:
defaultZone: http://localhost:8762/eureka/,http://localhost:8763/eureka/
register-with-eureka: false
spring:
application:
name: eureka-server01
server:
port: 8761
配置文件示例,eureka-server02:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/,http://localhost:8763/eureka/
register-with-eureka: false
spring:
application:
name: eureka-server02
server:
port: 8762
配置文件示例,eureka-server03:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
register-with-eureka: false
spring:
application:
name: eureka-server03
server:
port: 8763
eureka client的配置文件示例:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/,http://localhost:8763/eureka/
spring:
application:
name: eureka-client
server:
port: 9088
Spring Cloud Eureka-服務註冊與發現