Spring Cloud是目前用於開發微服務的主流框架之一,咱們都知道在微服務架構中最爲基礎、核心的模塊,就是服務註冊與發現。java
在Spring Cloud裏咱們可使用它的Eureka模塊來實現服務註冊與發現,Spring Cloud Eureka是基於Netflix Eureka作了二次封裝,它主要負責完成各個微服務實例的自動化註冊和發現功能。web
Eureka由兩個組件組成:spring
分佈式系統中爲何須要服務發現:apache
在實際的分佈式環境下,架構規模每每再也不是幾臺服務器,而是每一個獨立服務都跑在多臺機器上。例如A服務部署在10臺機器上,B服務也部署在10臺機器上,C服務部署在5臺機器上。服務器
如今A服務的一些功能須要調用B服務來實現,那麼問題來了,A服務要如何才能調用B服務呢?一般狀況下,咱們能夠想到將B服務所在的全部機器地址,經過配置文件來配置到A服務中,使其可以經過配置好的地址去發現並調用B服務。架構
這也的確是一個可行的方法,可是這些機器的地址都是有可能發生變化的,並且在生產環境中也會出現部分服務宕機的狀況,這樣就有可能致使一些連鎖效應。隨着業務的擴展,機器也會愈來愈多,也沒辦法再手動經過配置文件這種方式來配置機器地址了。app
鑑於人類的懶惰天性。。。呸,鑑於人類對高效工做、美好生活的追求。因此專門用於服務註冊與發現的工具被一一開發出來。有了服務治理框架後,服務發現就能夠交由它來自動完成。這時候A服務只須要到註冊中心進行服務註冊,一樣的B服務也到註冊中心進行服務註冊。註冊以後,註冊中心會經過相似心跳機制來確認服務的存活。若是確認某個服務宕機後,註冊中心會把宕機的服務剔除掉。當A服務要調用B服務的時候,則到註冊中心去獲取B服務的調用地址便可,B服務調用A服務也是同理。註冊中心就至關於一個服務與服務之間的橋樑或者說中間人,能夠說幫咱們管理了服務之間雜事。框架
Eureka服務治理體系以下:
maven
Spring Cloud官網地址以下:分佈式
廢話很少說,本小節咱們來搭建一個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 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 server是單機的,若這個eureka server宕機,則會致使與之關聯的所有微服務發生故障。
既然單機沒法保證高可用,那麼咱們就加多一臺機器好了,而後讓這兩個eureka server互相進行關聯。例如我如今有兩臺eureka server。一臺名叫eureka-server01跑在8761端口上,另外一臺名叫eureka-server02跑在8762端口上。而後只須要兩個步驟便可實現高可用:
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