SpringColud Eureka的服務註冊與發現

1、Eureka簡介

本文中全部代碼都會上傳到git上,請放心瀏覽
項目git地址:https://github.com/839022478/Spring-Cloudjava

在傳統應用中,組件之間的調用,經過有規範的約束的接口來實現,從而實現不一樣模塊間良好的協做。可是被拆分紅微服務後,每一個微服務實例的網絡地址均可能動態變化,數量也會變化,使得原來硬編碼的地址失去了做用。須要一箇中心化的組件來進行服務的登記和管理,爲了解決上面的問題,因而出現了服務治理,就是管理全部的服務信息和狀態,也就是咱們所說的註冊中心git

1.1 註冊中心

好比咱們去作火車或者汽車,須要去買票乘車,只看咱們有沒有票(有沒有服務),有就去買票(獲取註冊列表),而後乘車(調用),不用關心到底有多少車在運行github

流程圖:
在這裏插入圖片描述
使用註冊中心,咱們不須要關心有多少提供方,只管去調用就能夠了,那麼註冊中心有哪些呢?web

註冊中心:Eureka,Nacos,Consul,Zookeeperspring

本文中講解的是比較火熱的Spring Cloud微服務下的Eureka,Eureka是Netflix開發的服務發現框架,是一個RESTful風格的服務,是一個用於服務發現和註冊的基礎組件,是搭建Spring Cloud微服務的前提之一,它屏蔽了Server和client的交互細節,使得開發者將精力放到業務上。數據庫

服務註冊與發現主要包括兩個部分:服務端(Eureka Server)和客戶端(Eureka Client)瀏覽器

  • 服務端(Eureka Server): 一個公共服務,爲Client提供服務註冊和發現的功能,維護註冊到自身的Client的相關信息,同時提供接口給Client獲取註冊表中其餘服務的信息,使得動態變化的Client可以進行服務間的相互調用。緩存

  • 客戶端(Eureka Client): Client將本身的服務信息經過必定的方式登記到Server上,並在正常範圍內維護本身信息一致性,方便其餘服務發現本身,同時能夠經過Server獲取到本身依賴的其餘服務信息,完成服務調用,還內置了負載均衡器,用來進行基本的負載均衡服務器

Eureka GIt官網:https://github.com/Netflix/Eureka網絡

1.3 服務註冊與發現

服務註冊與發現關係圖:
在這裏插入圖片描述

1.2 client功能和server功能

1.2.1 client功能

  1. 註冊:每一個微服務啓動時,將本身的網絡地址等信息註冊到註冊中心,註冊中心會存儲(內存中)這些信息。
  2. 獲取服務註冊表:服務消費者從註冊中心,查詢服務提供者的網絡地址,並使用該地址調用服務提供者,爲了不每次都查註冊表信息,因此client會定時去server拉取註冊表信息到緩存到client本地。
  3. 心跳:各個微服務與註冊中心經過某種機制(心跳)通訊,若註冊中心長時間和服務間沒有通訊,就會註銷該實例。
  4. 調用:實際的服務調用,經過註冊表,解析服務名和具體地址的對應關係,找到具體服務的地址,進行實際調用。

1.2.2 server註冊中心功能

  1. 服務註冊表:記錄各個微服務信息,例如服務名稱,ip,端口等。
    註冊表提供 查詢API(查詢可用的微服務實例)和管理API(用於服務的註冊和註銷)。
  2. 服務註冊與發現:註冊:將微服務信息註冊到註冊中心。發現:查詢可用微服務列表及其網絡地址。
  3. 服務檢查:定時檢測已註冊的服務,如發現某實例長時間沒法訪問,就從註冊表中移除。

2、Eureka單節點搭建

2.1 pom.xml

在有的教程中,會引入spring-boot-starter-web,這個依賴其實不用,由於spring-cloud-starter-netflix-eureka-server的依賴已經包含了它,在pom依賴進去,就能夠了

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

2.2 application.yml

server:
  port: 8500
eureka:
  client:
    #是否將本身註冊到Eureka Server,默認爲true,因爲當前就是server,故而設置成false,代表該服務不會向eureka註冊本身的信息
    register-with-eureka: false
    #是否從eureka server獲取註冊信息,因爲單節點,不須要同步其餘節點數據,用false
    fetch-registry: false
    #設置服務註冊中心的URL,用於client和server端交流
    service-url:
      defaultZone: http://localhost:8080/eureka/

2.3 服務端啓動類

啓動類上添加此註解標識該服務爲配置中心
@EnableEurekaServer

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

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }

}

2.4 啓動

咱們啓動EurekaDemoApplication ,而後在瀏覽器中輸入地址 http://localhost:8500/,就能夠啓動咱們的 Eureka 了,咱們來看下效果,出現了這個畫面,就說明咱們已經成功啓動~,只是此時咱們的服務中是尚未客戶端進行註冊
在這裏插入圖片描述

3、服務註冊

注意:在客戶端pom裏面咱們須要加上spring-boot-starter-web,不然服務是沒法正常啓動的

3.1 pom.xml

<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>
        </dependency>

3.2 application.yml

#註冊中心
eureka:
  client:
    #設置服務註冊中心的URL
    service-url:
      defaultZone: http://localhost:8500/eureka/
  #服務名
  instance:
    appname: mxn

3.3 客戶端啓動類

在客戶端啓動類中咱們須要加上 @EnableDiscoveryClient註解

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class EurekaClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication.class, args);
    }
}

3.4 查看效果

工程啓動後,刷新http://localhost:8500/頁面,咱們能夠發現服務註冊成功了
在這裏插入圖片描述

而且咱們能夠在idea日誌打印中看到DiscoveryClient_MXN/DESKTOP-5BQ3UK8 - registration status: 204,說明就是註冊成功了
Eureka Server與Eureka Client之間的聯繫主要經過心跳的方式實現。心跳(Heartbeat)即Eureka Client定時向Eureka Server彙報本服務實例當前的狀態,維護本服務實例在註冊表中租約的有效性。

Eureka Client將定時從Eureka Server中拉取註冊表中的信息,並將這些信息緩存到本地,用於服務發現

4、Eureka 端點

官網地址:https://github.com/Netflix/eureka/wiki/Eureka-REST-operations

Eureka服務器還提供了一個端點(eureka/apps/{applicaitonName})能夠查看所註冊的服務詳細信息 。applicaitonName就是微服務的名稱,好比這裏咱們訪問 http://localhost:8500/eureka/apps/mxn

在這裏插入圖片描述

5、Eureka 原理

5.1 本質

存儲了每一個客戶端的註冊信息。EurekaClient從EurekaServer同步獲取服務註冊列表。經過必定的規則選擇一個服務進行調用

5.2 Eureka架構圖

在這裏插入圖片描述

  • 服務提供者: 是一個eureka client,向Eureka Server註冊和更新本身的信息,同時能從Eureka Server註冊表中獲取到其餘服務的信息。
  • 服務註冊中心: 提供服務註冊和發現的功能。每一個Eureka Cient向Eureka Server註冊本身的信息,也能夠經過Eureka Server獲取到其餘服務的信息達到發現和調用其餘服務的目的。
  • 服務消費者: 是一個eureka client,經過Eureka Server獲取註冊到其上其餘服務的信息,從而根據信息找到所需的服務發起遠程調用。
  • 同步複製: Eureka Server之間註冊表信息的同步複製,使Eureka Server集羣中不一樣註冊表中服務實例信息保持一致。
  • 遠程調用: 服務客戶端之間的遠程調用。
  • 註冊: Client端向Server端註冊自身的元數據以供服務發現。
  • 續約: 經過發送心跳到Server以維持和更新註冊表中服務實例元數據的有效性。當在必定時長內,Server沒有收到Client的心跳信息,將默認服務下線,會把服務實例的信息從註冊表中刪除。
  • 下線: Client在關閉時主動向Server註銷服務實例元數據,這時Client的服務實例數據將從Server的註冊表中刪除。
  • 獲取註冊表: Client向Server請求註冊表信息,用於服務發現,從而發起服務間遠程調用。

5.3 Eureka自我保護

有時候咱們會看到這樣的提示信息:EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.,這是由於默認狀況下,Eureka Server在必定時間內,沒有接收到某個微服務心跳,會將某個微服務註銷(90S)。可是當網絡故障時,微服務與Server之間沒法正常通訊,上述行爲就很是危險,由於微服務正常,不該該註銷,它的指導思想就是 寧肯保留健康的和不健康的,也不盲目註銷任何健康的服務
咱們也能夠經過命令去關閉自我保護的功能:

eureka:
  server: 
    enable-self-preservation: false

那麼自我保護是如何觸發的呢?
自我保護機制的觸發條件是,當每分鐘心跳次數( renewsLastMin) 小於 numberOfRenewsPerMinThreshold時,而且開啓自動保護模式開關( eureka.server.enable-self-preservation = true) 時,觸發自我保護機制,再也不自動過時租約
上面咱們全部的小於 numberOfRenewsPerMinThreshold,究竟是怎麼計算的呢,咱們在eureka源碼中能夠得知

numberOfRenewsPerMinThreshold = expectedNumberOfRenewsPerMin * 續租百分比(默認爲0.85)
expectedNumberOfRenewsPerMin = 當前註冊的應用實例數 x 2
當前註冊的應用實例數 x 2 是由於,在默認狀況下,註冊的應用實例每半分鐘續租一次,那麼一分鐘心跳兩次,所以 x 2

例如:咱們有10個服務,指望每分鐘續約數:10 * 2=20,指望閾值:20*0.85=17,當少於17時,就會觸發自我保護機制
在這裏插入圖片描述

5.4 健康檢查

因爲server和client經過心跳保持 服務狀態,而只有狀態爲UP的服務才能被訪問。看eureka界面中的status。
在這裏插入圖片描述

好比心跳一直正常,服務一直UP,可是此服務DB(數據庫)連不上了,沒法正常提供服務。

此時,咱們須要將 微服務的健康狀態也同步到server。只須要啓動eureka的健康檢查就行。這樣微服務就會將本身的健康狀態同步到eureka。配置以下便可。

在client端配置:將本身的健康狀態傳播到server。

eureka:
  client:
    healthcheck:
      enabled: true

5.5 Eureka監聽事件

import com.netflix.appinfo.InstanceInfo;
import org.springframework.cloud.netflix.eureka.server.event.*;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class CustomEvent {

    @EventListener
    public void listen(EurekaInstanceCanceledEvent event ) {
        System.out.println(LocalDateTime.now()+"服務下線事件:"+event.getAppName()+"---"+event.getServerId());
//發釘釘
    }

    @EventListener
    public void listen(EurekaInstanceRegisteredEvent event) {
        InstanceInfo instanceInfo = event.getInstanceInfo();
        System.out.println(LocalDateTime.now()+"服務上線事件:"+instanceInfo.getAppName()+"---"+instanceInfo.getInstanceId());
    }

    @EventListener
    public void listen(EurekaInstanceRenewedEvent event) {
        System.out.println(LocalDateTime.now()+"服務續約/心跳上報事件:"+event.getAppName()+"---"+event.getServerId());

    }

    @EventListener
    public void listen(EurekaRegistryAvailableEvent event) {
        System.out.println(LocalDateTime.now()+"註冊中心可用事件");
    }

    @EventListener
    public void listen(EurekaServerStartedEvent event) {
        System.out.println(LocalDateTime.now()+"註冊中心啓動事件");

    }
}

5.6 Renew: 服務續約

Eureka Client 會每隔 30 秒發送一次心跳來續約。 經過續約來告知 Eureka Server 該 Eureka Client 運行正常,沒有出現問題。 默認狀況下,若是 Eureka Server 在 90 秒內沒有收到 Eureka Client 的續約,Server 端會將實例從其註冊表中刪除,此時間可配置,通常狀況不建議更改。

5.6 服務剔除

若是Eureka Client在註冊後,既沒有續約,也沒有下線(服務崩潰或者網絡異常等緣由),那麼服務的狀態就處於不可知的狀態,不能保證可以從該服務實例中獲取到回饋,因此須要服務剔除此方法定時清理這些不穩定的服務,該方法會批量將註冊表中全部過時租約剔除,剔除是定時任務,默認60秒執行一次。延時60秒,間隔60秒

剔除的限制:
1.自我保護期間不清除。
2.分批次清除。

6、Eureka缺陷

因爲集羣間的同步複製是經過HTTP的方式進行,基於網絡的不可靠性,集羣中的Eureka Server間的註冊表信息不免存在不一樣步的時間節點,不知足CAP中的C(數據一致性)

7、總結

中間咱們講解了eureka的節點搭建,以及原理,對於如今很火熱的微服務,咱們對Eureka是很是有必要進行了解的,若是以爲文章對你有幫助,來個點贊支持吧,若是對文章有疑問或建議,歡迎討論留言,謝謝你們~

相關文章
相關標籤/搜索