SpringCloud學習筆記(三) Eureka服務註冊與發現

Eureka是什麼

Eureka是Netflix的一個子模塊,也是核心模塊之一。 Eureka是一個基於REST的服務,用於定位服務,以實現雲端中間層服務發現和故障轉移。服務註冊與發現對於微服務架構來說是非常重要的,有了服務發現與註冊,只需要使用服務的標識符,就可以訪問到服務,而不需要修改服務調用的配置文件了。功能類似於dubbo的註冊中心,比如Zookeeper。

Netflix在設計Eureka時遵守的是AP原則( 可用性Availability、 分區容錯性Partition tolerance)

原理

基本架構

SpringCloud封裝了Netflix公司開發的Eureka模塊來實現服務註冊和發現(請對比Zookeeper)。

Eureka採用了C-S的設計架構。Eureka Server作爲服務註冊功能的服務器,它是服務註冊中心。

而系統中的其他微服務,使用Eureka的客戶端連接到Eureka Server並維持心跳連接。這樣系統的維護人員就可以通過Eureka Server來監控系統中各個微服務是否正常運行。SpringCloud 的一些其他模塊(比如Zuul) 就可以通過Eureka Server來發現系統中的其他微服務,並執行相關的邏輯。

Eureka包含兩個組件:Eureka Server和Eureka Client

Eureka Server提供服務註冊服務
各個節點啓動後,會在EurekaServer中進行註冊, 這樣EurekaServer中的服務註冊表中將會存儲所有可用服務節點的信息,服務節點的信息可以在界面中直觀的看到。

EurekaClient是一個Java客戶端
用於簡化Eureka Server的交互,客戶端同時也具備一個內置的、使用輪詢(round-robin)負載算法的負載均衡器。在應用啓動後,將會向Eureka Server發送心跳(默認週期爲30秒)。如果Eureka Server在多個心跳週期內沒有接
收到某個節點的心跳,EurekaServer將會從服務註冊表中把這個服務節點移除(默認90秒)。

三大角色

  1. Eureka Server提供服務註冊和發現
  2. Service Provider服務提供方將自身服務註冊到Eureka,從而使服務消費方能夠找到
  3. Service Consumer服務消費方從Eureka獲取註冊服務列表,從而能夠消費服務

在這裏插入圖片描述

構建步驟

eureka服務註冊中心Module

microservicecloud-eureka-7001

application.yml

server:
  port: 7001

eureka:
  instance:
    hostname: localhost #eureka 服務端的實例名稱
  client:
    register-with-eureka: false #false表示不向註冊中心註冊自己。只有客戶端才向Eureka進行註冊
    fetch-registry: false #false表示自己端就是註冊中心,我的職責就是維護服務實例,並不需要去檢索服務
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  #設置與Eureka Server交互的地址,查詢服務和註冊服務都需要依賴這個地址

啓動類

在啓動類上加@EnableEurekaServer註解,表示爲EurekaServer服務器端,接受其它微服務註冊進來。

啓動成功後訪問localhost:7001便可看見Eureka的界面。

將已有的部門微服務註冊進eureka服務中心

將microservicecloud-provider-dept-8001 註冊進 microservicecloud-eureka-7001

provider8001的pom

<!-- 新增以下依賴 -->
<!-- 將微服務provider註冊進Eureka -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

provider8001的application.yml

# 追加以下內容

eureka:
  client:                  #客戶端註冊進Eureka服務列表內#
    service-url:
      defaultZone: http://localhost:7001/eureka

以上defaultZone的配置,取自Eureka7001的application中的defaultZone的配置:

defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

這是Eureka7001設置的,與Eureka Server交互的地址,查詢服務和註冊服務都需要依賴這個地址

provider8001的啓動類

增加@EnableEurekaClient註解,本服務啓動後會自動註冊進Eureka服務中

啓動

先啓動服務端Eureka7001的服務,再啓動客戶端provider8001的服務,訪問localhost:7001
在這裏插入圖片描述
該處的服務名取自provider8001的application.yml中配置的:

spring:
  application:
    name: microservicecloud-dept  #對外暴露的微服務的名字

actuator與註冊微服務信息完善

主機名:服務名稱修改

DESKTOP-S98DNUG:microservicecloud-dept:8001 是入駐Eureka裏的標識id,要把它換個別名
在這裏插入圖片描述修改provider8001的application.yml

eureka:
  instance:
    instance-id: microservicecloud-dept8001

重啓Eureka7001和provider8001,可發現標識id變爲microservicecloud-dept8001

訪問信息有ip地址提示

鼠標指向標識id時,讓瀏覽器左下角顯示服務ip
在這裏插入圖片描述
修改provider8001的application.yml

eureka:
  instance:
    prefer-ip-address: true   #訪問路徑可以顯示ip地址

重啓後可顯示ip
在這裏插入圖片描述

微服務info內容詳細信息

點擊標識id的超鏈接後 報告ErrorPage
在這裏插入圖片描述
provider8001的pom

<!-- 添加以下依賴 -->
<!-- actuator監控信息完善 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

總的父工程microservicecloud修改pom.xml添加構建build信息

<build>
    <finalName>microservicecloud</finalName><!--父工程名字-->
    <resources>
        <resource>
            <directory>src/main/resources</directory><!--允許訪問所有工程裏這個路徑下的內容-->
            <filtering>true</filtering><!--過濾開啓-->
        </resource>
    </resources>
    <plugins>
        <plugin>
            <!--負責解析和解讀的插件-->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <!--以$開頭和以$結尾的 在src/main/resources路徑下的配置文件信息 可以讀取-->
            <configuration>
                <delimiters>
                    <delimit>$</delimit>
                </delimiters>
            </configuration>
        </plugin>
    </plugins>
</build>

provider8001的application.yml

info:
  app.name: microservicecloud-provider-8001
  company.name: www.demo.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$

點擊標識id可以看到

eureka自我保護

某時刻某一個微服務不可用了,eureka不會立刻清理,依舊會對該微服務的信息進行保存
在這裏插入圖片描述在這裏插入圖片描述什麼是自我保護模式

默認情況下,如果EurekaServer在一定時間內沒有接收到某個微服務實例的心跳,EurekaServer將會註銷該實例(默認90秒)。但是當網絡分區故障發生時,微服務與EurekaServer之間無法正常通信,以上行爲可能變得非常危險了——因爲微服務本身其實是健康的,此時本不應該註銷這個微服務。Eureka通過“自我保護模式”來解決這個問題——當EurekaServer節點在短時間內丟失過多客戶端時(可能發生了網絡分區故障),那麼這個節點就會進入自我保護模式。一旦進入該模式,EurekaServer就會保護服務註冊表中的信息,不再刪除服務註冊表中的數據(也就是不會註銷任何微服務)。當網絡故障恢復後,該Eureka Server節點會自動退出自我保護模式。

在自我保護模式中,Eureka Server會保護服務註冊表中的信息,不再註銷任何服務實例。當它收到的心跳數重新恢復到閾值以上時,該Eureka Server節點就會自動退出自我保護模式。它的設計哲學就是寧可保留錯誤的服務註冊信息,也不盲目註銷任何可能健康的服務實例。

綜上,自我保護模式是一種應對網絡異常的安全保護措施。使用自我保護模式,可以讓Eureka集羣更加的健壯、穩定。

在Spring Cloud中,可以使用eureka.server.enable-self-preservation = false禁用自我保護模式。

服務發現Discovery

對於註冊進eureka裏面的微服務,可以通過服務發現來獲得該服務的信息

provider8001的DeptController

//添加以下內容
import org.springframework.cloud.client.discovery.DiscoveryClient;

@Autowired
private DiscoveryClient discoveryClient;

@RequestMapping(value="/dept/discovery", method=RequestMethod.GET)
public Object discovery(){
    //獲取所有服務
    List<String> list = discoveryClient.getServices();
    System.out.println("*********" + list);

    //找到名稱爲MICROSERVICECLOUD-DEPT的服務,打印它的相關信息
    List<ServiceInstance> srvList = discoveryClient.getInstances("MICROSERVICECLOUD-DEPT");
    for(ServiceInstance element : srvList){
        System.out.println(element.getServiceId() + "\t" + element.getHost()
                           + "\t" + element.getPort() + "\t" + element.getUri());
    }
    return this.discoveryClient;
}

provider8001的啓動類

增加@EnableDiscoveryClient註解,做服務發現

啓動

在這裏插入圖片描述
在這裏插入圖片描述

consumer80工程的DeptController_Consumer

//測試@EnableDiscoveryClient,消費端可以調用服務發現
@RequestMapping(value = "/consumer/dept/discovery")
public Object discovery(){
    return restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery", Object.class);
}

啓動,訪問localhost:80/consumer/dept/discovery可以看到相關信息。

集羣配置

pom文件

新建模塊microservicecloud-eureka-7002和microservicecloud-eureka-7003,在各自的pom文件中引入和7001相同的依賴

<dependencies>
    <!--eureka-server服務端-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
    </dependency>
    <!--修改後立即生效,熱部署-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>springloaded</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
</dependencies>

啓動類

爲Eureka7002和Eureka7003建啓動類,與7001相同

package com.demo.springCloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer //EurekaServer服務器端啓動類,接受其它微服務註冊進來
public class EurekaServer7002_App {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer7002_App.class, args);
    }
}

修改映射配置

修改hosts文件

C:\Windows\System32\drivers\etc路徑下的hosts文件,新增如下內容:

127.0.0.1		eureka7001.com
127.0.0.1		eureka7002.com
127.0.0.1		eureka7003.com

三臺Eureka服務器的yml配置

7001修改eureka.instance.hostname和client.service-url.defaultZone;7002與7003要修改端口號、hostname、defalutZone配置成除了自身之外的另外兩個

server:
  port: 7001

eureka:
  instance:
    hostname: euraka7001.com
#    單機版  hostname: localhost #eureka 服務端的實例名稱
  client:
    register-with-eureka: false #false表示不向註冊中心註冊自己。只有客戶端才向Eureka進行註冊
    fetch-registry: false #false表示自己端就是註冊中心,我的職責就是維護服務實例,並不需要去檢索服務
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
#    單機版  defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  #設置與Eureka Server交互的地址,查詢服務和註冊服務都需要依賴這個地址

provider8001發佈到上面三臺Eureka集羣的配置中

修改provider8001的application.yml

eureka:
  client:                  #客戶端註冊進Eureka服務列表內
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  #      defaultZone: http://localhost:7001/eureka

啓動

訪問http://eureka7002.com:7002/可以看到相關信息

Eureka和Zookeeper

Zookeeper遵守CP

當向註冊中心查詢服務列表時,我們可以容忍註冊中心返回的是幾分鐘以前的註冊信息,但不能接受服務直接down掉不可用。也就是說,服務註冊功能對可用性的要求要高於一致性。 但是zk會出現這樣-種情況, 當master節點因爲網絡故障與其他節點失去聯繫時,剩餘節點會重新進行leader選舉。問題在於,選舉leader的時間太長,30 ~ 120s,且選舉期間整個zk集羣都是不可用的,這就導致在選舉期間註冊服務癱瘓。在雲部署的環境下,因網絡問題使得zk集羣失去master節點是較大概率會發生的事,雖然服務能夠最終恢復,但是漫長的選舉時間導致的註冊長期不可用是不能容忍的。

Eureka保證AP

Eureka看明白了這一點,因此在設計時就優先保證可用性。Eureka各個節點都是平等的,幾個節點掛掉不會影響正常節點的工作,剩餘的節點依然可以提供註冊和查詢服務。而Eureka的客戶端在向某個Eureka註冊或時如果發現連接失敗,則會自動切換至其它節點,只要有一臺Eureka還在,就能保證註冊服務可用(保證可用性),只不過查到的信息可能不是最新的(不保證強一 致性)。除此之外,Eureka還有一種自我保護機制,如果在15分鐘內超過85%的節點都沒有正常的心跳,那麼Eureka就認爲客戶端與註冊中心出現了網絡故障,此時會出現以下幾種情況:

  1. Eureka不再從註冊列表中移除因爲長時間沒收到心跳而應該過期的服務
  2. Eureka仍然能夠接受新服務的註冊和查詢請求,但是不會被同步到其它節點上(即保證當前節點依然可用)
  3. 當網絡穩定時,當前實例新的註冊信息會被同步到其它節點中。

因此,Eureka可以很好的應對因網絡故障導致部分節點失去聯繫的情況,而不會像zookeeper那樣使整個註冊服務癱瘓。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章