SpringCloud服務(wù)注冊(cè)與發(fā)現(xiàn)(Eureka)

作者:xcbeyond
瘋狂源自夢(mèng)想,技術(shù)成就輝煌!微信公眾號(hào):《程序猿技術(shù)大咖》號(hào)主,專注后端開發(fā)多年,擁有豐富的研發(fā)經(jīng)驗(yàn),樂于技術(shù)輸出、分享,現(xiàn)階段從事微服務(wù)架構(gòu)項(xiàng)目的研發(fā)工作,涉及架構(gòu)設(shè)計(jì)、技術(shù)選型、業(yè)務(wù)研發(fā)等工作。對(duì)于Java、微服務(wù)、數(shù)據(jù)庫、Docker有深入了解,并有大量的調(diào)優(yōu)經(jīng)驗(yàn)。

0、前言
      微服務(wù)是近兩年比較火的概念,被稱為程序員必備技能之一了,可見其運(yùn)用之廣。最近整理下資料進(jìn)行系統(tǒng)的學(xué)習(xí),與大家一一分享。

       微服務(wù)是相對(duì)于傳統(tǒng)單體式架構(gòu)而言的。單體式架構(gòu)是一份代碼,部署都是基于單個(gè)單元進(jìn)行的,它的優(yōu)點(diǎn)是易于部署,但面臨的就是可用性低、可伸縮性差。微服務(wù)的出現(xiàn)解決了這個(gè)問題,它以單獨(dú)的服務(wù)來做一個(gè)功能,因此,每個(gè)單獨(dú)的功能被稱為一個(gè)服務(wù),各個(gè)服務(wù)之間可以相互調(diào)用。

(微服務(wù)更多了解請(qǐng)參看微服務(wù)介紹)

        本章節(jié)主要講解各個(gè)服務(wù)之間是如何進(jìn)行相互調(diào)用的,即:SpringCloud Eureka,它是云端服務(wù)發(fā)現(xiàn),一個(gè)基于 REST 的服務(wù),用于定位服務(wù),以實(shí)現(xiàn)云端中間層服務(wù)發(fā)現(xiàn)和故障轉(zhuǎn)移。

1、SpringCloud Eureka介紹
1.1 Eureka服務(wù)治理
1.1.1 服務(wù)治理
        服務(wù)治理是微服務(wù)架構(gòu)中最為核心和基礎(chǔ)的模塊,它主要用來實(shí)現(xiàn)各個(gè)微服務(wù)實(shí)例的自動(dòng)化注冊(cè)和發(fā)現(xiàn)。

        Spring Cloud Eureka是Spring Cloud Netflix微服務(wù)套件中的一部分,它基于Netflix Eureka做了二次封裝。主要負(fù)責(zé)完成微服務(wù)架構(gòu)中的服務(wù)治理功能。

Eureka服務(wù)治理體系如下:

1.1.2 服務(wù)注冊(cè)
       在服務(wù)治理框架中,通常都會(huì)構(gòu)建一個(gè)注冊(cè)中心,每個(gè)服務(wù)單元向注冊(cè)中心登記自己提供的服務(wù),包括服務(wù)的主機(jī)與端口號(hào)、服務(wù)版本號(hào)、通訊協(xié)議等一些附加信息。注冊(cè)中心按照服務(wù)名分類組織服務(wù)清單,同時(shí)還需要以心跳檢測的方式去監(jiān)測清單中的服務(wù)是否可用,若不可用需要從服務(wù)清單中剔除,以達(dá)到排除故障服務(wù)的效果。

1.1.3 服務(wù)發(fā)現(xiàn)
      在服務(wù)治理框架下,服務(wù)間的調(diào)用不再通過指定具體的實(shí)例地址來實(shí)現(xiàn),而是通過服務(wù)名發(fā)起請(qǐng)求調(diào)用實(shí)現(xiàn)。服務(wù)調(diào)用方通過服務(wù)名從服務(wù)注冊(cè)中心的服務(wù)清單中獲取服務(wù)實(shí)例的列表清單,通過指定的負(fù)載均衡策略取出一個(gè)服務(wù)實(shí)例位置來進(jìn)行服務(wù)調(diào)用。

1.2 Eureka
1.2.1 Eureka介紹
       Spirng Cloud Eureka使用Netflix Eureka來實(shí)現(xiàn)服務(wù)注冊(cè)與發(fā)現(xiàn)。它既包含了服務(wù)端組件,也包含了客戶端組件,并且服務(wù)端與客戶端均采用java編寫,所以Eureka主要適用于通過java實(shí)現(xiàn)的分布式系統(tǒng),或是JVM兼容語言構(gòu)建的系統(tǒng)。Eureka的服務(wù)端提供了較為完善的REST API,所以Eureka也支持將非java語言實(shí)現(xiàn)的服務(wù)納入到Eureka服務(wù)治理體系中來,只需要其他語言平臺(tái)自己實(shí)現(xiàn)Eureka的客戶端程序。目前.Net平臺(tái)的Steeltoe、Node.js的eureka-js-client等都已經(jīng)實(shí)現(xiàn)了各自平臺(tái)的Ereka客戶端組件。

1.2.2 Eureka服務(wù)端
      Eureka服務(wù)端,即服務(wù)注冊(cè)中心。它同其他服務(wù)注冊(cè)中心一樣,支持高可用配置。依托于強(qiáng)一致性提供良好的服務(wù)實(shí)例可用性,可以應(yīng)對(duì)多種不同的故障場景。

       Eureka服務(wù)端支持集群模式部署,當(dāng)集群中有分片發(fā)生故障的時(shí)候,Eureka會(huì)自動(dòng)轉(zhuǎn)入自我保護(hù)模式。它允許在分片發(fā)生故障的時(shí)候繼續(xù)提供服務(wù)的發(fā)現(xiàn)和注冊(cè),當(dāng)故障分配恢復(fù)時(shí),集群中的其他分片會(huì)把他們的狀態(tài)再次同步回來。集群中的的不同服務(wù)注冊(cè)中心通過異步模式互相復(fù)制各自的狀態(tài),這也意味著在給定的時(shí)間點(diǎn)每個(gè)實(shí)例關(guān)于所有服務(wù)的狀態(tài)可能存在不一致的現(xiàn)象。

1.2.3 Eureka客戶端
         Eureka客戶端,主要處理服務(wù)的注冊(cè)和發(fā)現(xiàn)??蛻舳朔?wù)通過注冊(cè)和參數(shù)配置的方式,嵌入在客戶端應(yīng)用程序的代碼中。在應(yīng)用程序啟動(dòng)時(shí),Eureka客戶端向服務(wù)注冊(cè)中心注冊(cè)自身提供的服務(wù),并周期性的發(fā)送心跳來更新它的服務(wù)租約。同時(shí),他也能從服務(wù)端查詢當(dāng)前注冊(cè)的服務(wù)信息并把它們緩存到本地并周期行的刷新服務(wù)狀態(tài)。

2、服務(wù)注冊(cè)中心(Eureka服務(wù)端)
2.1 注冊(cè)中心項(xiàng)目構(gòu)建
2.1.1 新建模塊化項(xiàng)目父項(xiàng)目
(SpringCloud系列教程的工程j將以Maven模塊化項(xiàng)目方式創(chuàng)建,便于各個(gè)微服務(wù)的項(xiàng)目管理。)

父項(xiàng)目并不是創(chuàng)建注冊(cè)中心所必須的,只是為了方便后續(xù)各個(gè)服務(wù)工程的管理。

(1)與新建一般SpringBoot項(xiàng)目一樣,請(qǐng)參考【SpringBoot 系列】一、SpringBoot項(xiàng)目搭建。

       新建名為“springCloud”項(xiàng)目作為父項(xiàng)目,項(xiàng)目結(jié)構(gòu)如下圖:

(2)修改添加pom.xml配置及SpringCloud依賴包。

 ①  將packaging標(biāo)簽值修改為pom。(如果不修改添加,則無法添加子項(xiàng)目),如下:

    <groupId>com.xcbeyond.springcloud</groupId>
    <artifactId>springCloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>springCloud</name>
    <url>http://maven.apache.org</url>
②添加SpringCloud的依賴包:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
    <relativePath/>
</parent>
③添加dependency對(duì)所有子模塊都是有效的,即:在子模塊中不用再額外添加這些依賴:

<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>
    </dependency>
 
    <dependency>
           <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
</dependencies>
(3)使用modules標(biāo)簽實(shí)現(xiàn)模塊化項(xiàng)目管理 。

        在pom.xml中添加modules標(biāo)簽,引入服務(wù)發(fā)現(xiàn)springCloudEureka項(xiàng)目,如下:

<!-- 使用modules標(biāo)簽實(shí)現(xiàn)模塊化項(xiàng)目管理 -->
<modules>
    <!-- 服務(wù)發(fā)現(xiàn)。 (Eureka Server)-->
    <module>springCloudEureka</module>
</modules>
或者在pom.xml的Overview視圖中,【Modules】選項(xiàng)中直接進(jìn)行“添加”或“創(chuàng)建”子項(xiàng)目。如下圖:

pom.xml完整配置如下:






<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>com.xcbeyond.springcloud</groupId>
    <artifactId>springCloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>springCloud</name>
    <url>http://maven.apache.org</url>
 
    <!-- 使用modules標(biāo)簽實(shí)現(xiàn)模塊化項(xiàng)目管理 -->
    <modules>
        <!-- 服務(wù)發(fā)現(xiàn)。 (Eureka Server)-->
        <module>springCloudEureka</module>
    </modules>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath/>
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </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>
        </dependency>
        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>
2.1.2 新建Eureka服務(wù)注冊(cè)中心子項(xiàng)目
(1)新建springCloudEureka項(xiàng)目作為Eureka注冊(cè)中心,如下圖:

(2)pom.xml中添加依賴包。

注冊(cè)中心依賴于Eureka Server,所以需要添加以下依賴:

<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-server</artifactId>
        <version>2.0.0.RELEASE</version>
    </dependency>
</dependencies>
2.2 Eureka服務(wù)注冊(cè)中心代碼實(shí)現(xiàn)及配置
(1)springCloudEureka啟動(dòng)類。

com.xcbeyond.springcloud.eureka.SpringCloudEureka.java

(這是一個(gè)常規(guī)的SpringBoot項(xiàng)目,啟動(dòng)類只需額外使用@EnableEurekaServer注解開啟對(duì)對(duì)EurekaServer的支持)

package com.xcbeyond.springcloud.eureka;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
 
/**
 * Eureka啟動(dòng)類
 * @author xcbeyond
 * 2018年8月3日上午9:40:48
 */
@SpringBootApplication
//開啟對(duì)EurekaServer的支持,即:作為Eureka服務(wù)端
@EnableEurekaServer
public class SpringCloudEureka {
    public static void main(String[] args) {
        SpringApplication.run(SpringCloudEureka.class, args);
    }
}
(2)配置application.properties,如下:

#當(dāng)前Eureka服務(wù)器端口
server.port=8761
#服務(wù)注冊(cè)中心實(shí)例的主機(jī)名
eureka.instance.hostname=localhost
#是否向服務(wù)注冊(cè)中心注冊(cè)自己
eureka.client.registerWithEureka=false
#是否檢索服務(wù)
eureka.client.fetchRegistry=false
2.3、啟動(dòng)Eureka
        運(yùn)行springCloudEureka項(xiàng)目的啟動(dòng)類SpringCloudEureka,啟動(dòng)成功后,訪問http://localhost:8761/,可以看到Eureka的信息面板,如下圖,則表明Eureka啟動(dòng)配置成功。

3、服務(wù)提供者(Eureka客戶端)
3.1 Eureka客戶端
     客戶端在啟動(dòng)的時(shí)候,會(huì)通過Rest請(qǐng)求的方式將自己注冊(cè)到Eureka Server上,同時(shí)附帶一些服務(wù)自身的元信息。Eureka Server接收到這個(gè)Rest請(qǐng)求之后,將元數(shù)據(jù)信息存儲(chǔ)在一個(gè)雙層結(jié)構(gòu)的Map中,其中第一層的key是服務(wù)名。第二層的key 是具體服務(wù)的實(shí)例名。

      在Eureka客戶端,需要確認(rèn)一下eureka.client.register-with-eureka=true參數(shù)是否正確,該值默認(rèn)為true。若設(shè)置為fasle將不會(huì)啟動(dòng)注冊(cè)操作。

       Eureka客戶端實(shí)質(zhì)是代表一個(gè)服務(wù),用來完成具體的業(yè)務(wù)功能模塊。

3.2 創(chuàng)建Eureka客戶端項(xiàng)目
  按照 “2.1.2 新建Eureka服務(wù)注冊(cè)中心子項(xiàng)目”的方式創(chuàng)建Eureka客戶端項(xiàng)目springCloudEurekaClient,如下:

3.3 導(dǎo)入依賴包
     pom.xml如下:

<?xml version="1.0"?>
<project
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
 
    <parent>
        <groupId>com.xcbeyond.springcloud</groupId>
        <artifactId>springCloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    
    <groupId>com.xcbeyond.springcloud</groupId>
    <artifactId>springCloudEurekaClient</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
    <name>springCloudEurekaClient</name>
    <url>http://maven.apache.org</url>
    <description>服務(wù)提供者。</description>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <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>
            <version>2.0.0.RELEASE</version>
        </dependency>
 
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
3.4 Eureka客戶端代碼實(shí)現(xiàn)及配置
(1)啟動(dòng)類實(shí)現(xiàn)

com.xcbeyond.springcloud.eurekaclient.EurekaClientApplication.java

package com.xcbeyond.springcloud.eurekaclient;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 
/**
 * Eureka Client(服務(wù)提供者)啟動(dòng)類
 * @author xcbeyond
 * 2018年8月3日下午3:05:44
 */
@SpringBootApplication
//開啟作為Eureka Server的客戶端的支持
@EnableEurekaClient
public class EurekaClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication.class, args);
    }
}
(2)application.properties如下:

(/springCloudEurekaClient/src/main/resources/application.properties)

#當(dāng)前服務(wù)器端口
server.port=8001
#應(yīng)用名
spring.application.name=Eureka-Client
 
#服務(wù)注冊(cè)中心地址,需按照注冊(cè)中心IP進(jìn)行對(duì)應(yīng)修改
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
3.5啟動(dòng)Eureka客戶端
 運(yùn)行啟動(dòng)類EurekaClientApplication,啟動(dòng)完成后,訪問Eureka信息面板http://localhost:8761/,發(fā)現(xiàn)Instancescurrently registered with Eureka一欄顯示EUREKA-CLIENT已經(jīng)注冊(cè)成功,如下圖: