• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • SpringCloud-01-Eureka服務注冊與發現

    標簽: SpringCloud  微服務  Java  java  分布式

    Eureka服務注冊與發現

    1. Eureka基礎知識

    1. 什么是服務治理

    SpringCloud封裝了Netflix公司開發的Eureka模塊來實現服務治理

    在傳統的RPC遠程調用框架中,管理每個服務與服務之間依賴關系比較復雜,管理比較復雜,所以需要使用服務治理,管理服務與服務之間依賴關系,可以實現服務調用、負載均衡、容錯等,實現服務發現與注冊

    2. 什么是服務注冊與發現

    Eureka采用了CS的設計架構,Eureka Server作為服務注冊功能的服務器,它是服務注冊中心,而系統中的其他微服務,使用Eureka的客戶端連接到Eureka Server并維持 心跳鏈接 。這樣系統的維護人員就可以通過Eureka Server來監控系統中各個微服務是否正常運行。

    在服務注冊與發現中,有一個注冊中心。當服務器啟動的時候,會把當前自己服務器的信息(比如:服務地址、通訊地址等)以別名方式注冊到注冊中心中。另一方(消費者/服務提供者),以該別名的方式去注冊中心上獲取到實際的服務通訊地址,然后再實現本地RPC調用。RPC遠程調用框架核心設計思想:在于注冊中心,因為使用注冊中心管理每個服務與服務之間的依賴關系(服務治理概念)。在任何RPC遠程框架中,都會有一個注冊中心(存放服務地址相關信息(接口地址))

    下左圖是Eureka系統架構,右圖是Dubbo系統架構
    在這里插入圖片描述

    3. Eureka包含兩個組件:Eureka ServerEureka Client

    • Eureka Server提供服務注冊中心

      各個微服務節點通過配置啟動后,會在EurekaServer中進行注冊,這樣EurekaServer中的服務注冊表中將存儲所有可用服務節點的信息,服務節點的信息可以在界面中直觀看到。

    • Eureka Client通過注冊中心進行訪問

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

    2. 單機Eureka構建步驟

    1. IDEA生成Eureka Server端服務注冊中心

    • 1 建Module

    • 2 改POM

      1.X和2.X的對比說明:

      SpringBoot1.X對應的SpringCloud中,不要再用了!!!

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

      SpringBoot2.X對應的SpringCloud中

      <dependency>
      	<groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
      </dependency>
      
    • 3 寫配置文件YML

      server:
        port: 7001
      
      eureka:
        instance:
          hostname: localhost #eureka服務端的實例名稱
        client:
          #false表示不向注冊中心注冊自己
          register-with-eureka: false
          #false表示自己端就是注冊中心,我的職責就是維護服務實例,并不需要去檢索服務
          fetch-registry: false     
          service-url:
            # 設置與Eureka Server交互的地址查詢服務和注冊服務都需要依賴這個地址
            defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      
    • 4 SpringBoot應用主啟動類

      package cn.sher6j.springcloud;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      
      /**
       * @author sher6j
       */
      @SpringBootApplication
      @EnableEurekaServer//聲明我是服務注冊中心
      public class EurekaMain7001 {
          public static void main(String[] args) {
              SpringApplication.run(EurekaMain7001.class);
          }
      }
      
    • 5 測試

      完成以上步驟后,運行該Eureka Server主啟動類,訪問 localhost:7001,就會看到下面的服務注冊中心:
      在這里插入圖片描述
      可以發現,目前還沒有任何服務入駐進服務注冊中心中,在應用中顯示:No instances available

    2. 將Eureka Client端中的服務提供端注冊進Eureka Server作為Service Provider

    • 1 建module

    • 2 改POM

      1.X和2.X的對比說明:

      SpringBoot1.X對應的SpringCloud中,不要再用了!!!

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

      SpringBoot2.X對應的SpringCloud中

      <dependency>
      	<groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
      
    • 3 寫配置文件YML

      server:
        port: 8001
      
      spring:
        application:
          name: cloud-payment-service  # 入駐Eureka服務注冊中心的服務名稱
        datasource:
          type: com.alibaba.druid.pool.DruidDataSource  # 當前數據源操作類型
          driver-class-name: org.gjt.mm.mysql.Driver    # mysql驅動包
          url: jdbc:mysql://localhost:3306/cloud20?useUnicode=true&characterEncoding=utf-8&useSSL=false
          username: root
          password: root
      
      eureka:
        client:
          #表示是否將自己注冊進EurekaServer默認為true。
          register-with-eureka: true
          #是否從EurekaServer抓取已有的注冊信息,默認為true。單節點無所謂,集群必須設置為true才能配合ribbon使用負載均衡
          fetchRegistry: true
          service-url:
            #單機版
            defaultZone: http://localhost:7001/eureka # 入駐的服務注冊中心地址
      
      mybatis:
        mapperLocations: classpath:mapper/*.xml
        type-aliases-package: cn.sher6j.springcloud.entities  # 所有Entity別名類所在包
      
    • 4 SpringBoot應用主啟動類

      package cn.sher6j.springcloud;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
      /**
       * 主啟動類
       * @author sher6j
       */
      @SpringBootApplication
      @EnableEurekaClient
      public class PaymentMain8001 {
          public static void main(String[] args) {
              SpringApplication.run(PaymentMain8001.class);
          }
      }
      
    • 5 測試

      先要啟動EurekaServer,因為有了服務注冊中心,具體的服務提供者才能后向其中注冊自己的服務,如下圖:
      在這里插入圖片描述
      可以發現,注冊到服務注冊中心的服務名(圖中藍框)即為我們在yml配置文件中設置的服務名,上面頁面中出現的 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的自我保護機制

    3. 將Eureka Client端中的服務消費端注冊進Eureka Server稱為Service Consumer

    • 1 建module

    • 2 改POM

    • 3 寫配置文件

      server:
        port: 80
      
      spring:
        application:
          name: cloud-order-service
      
      eureka:
        client:
          #表示是否將自己注冊進EurekaServer默認為true。
          register-with-eureka: false
          #是否從EurekaServer抓取已有的注冊信息,默認為true。單節點無所謂,集群必須設置為true才能配合ribbon使用負載均衡
          fetchRegistry: true
          service-url:
            #單機
            defaultZone: http://localhost:7001/eureka
      
    • 4 主啟動類

      package cn.sher6j.springcloud;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
      
      /**
       * @author sher6j
       */
      @SpringBootApplication
      @EnableEurekaClient
      public class OrderMain80 {
          public static void main(String[] args) {
              SpringApplication.run(OrderMain80.class);
          }
      }
      
      
    • 5 測試

      如圖此時80,8001兩個微服務都已經注冊到Eureka服務注冊中心
      在這里插入圖片描述
      此時,再回看最開始的Eureka系統架構,在服務注冊中心和服務提供者沒有集群的情況下,7001端口的微服務就對應了服務注冊中心,而該服務不需要向服務注冊中心注冊自己,8001端口的微服務作為服務提供方入住到服務注冊中心,8002端口的微服務作為服務消費方也同樣注冊到服務注冊中心
      在這里插入圖片描述

    3. 集群Eureka構建步驟

    1. Eureka集群原理說明

    服務注冊中心Eureka Server中分為 服務注冊服務發現,服務注冊過程將服務信息注冊進服務注冊中心,服務發現過程從服務注冊中心上獲取服務信息,而這個過程的實質就是:將服務名作為key存儲,然后根據value取得服務的調用地址

    整個Eureka的過程如果:

    1. 先啟動Eureka注冊中心
    2. 啟動服務提供者服務
    3. 服務提供者服務將自身信息(比如服務地址)以別名方式注冊到Eureka注冊中心
    4. 消費者服務在需要調用接口時,使用服務別名到注冊中心獲取實際的RPC遠程調用地址
    5. 消費者獲得調用地址后,底層實際是利用 HttpClient 技術實現遠程調用
    6. 消費者獲得服務地址后會緩存字本地JVM內存中,默認每間隔30秒更新一次服務調用地址

    那么微服務RPC遠程服務調用最核心的是什么呢???

    高可用!!!,如果注冊中心只有一個,而這個注冊中心出現了故障,那么整個微服務就直接GG了,整個微服務環境就不可用了,所以應該搭建Eureka注冊中心集群, 實現 負載均衡 + 故障容錯

    那怎么實現Eureka注冊中心的集群呢?用一句話總結就是——互相注冊,相互守望,如下圖所示:
    在這里插入圖片描述
    服務注冊中心實現相互注冊,讓彼此都知道對方的存在,也就是注冊中心集群中的每一個注冊中心都知道整個集群中的其他注冊中心,比如如果有三個注冊服務中心7001,7002,7003,那么就將7002和7003注冊給7001, 將7002和7001注冊給7003, 將7003和7001注冊給7002, 以此類推,而這些個注冊服務中心作為一個整體對外看做一個注冊服務中心。

    2. EurekaServer集群環境構建步驟

    • 參考cloud-eureka-server7001新建一個服務注冊中心cloud-eureka-server7001。

    • 2 改POM,copy復制cloud-eureka-server7001的POM文件即可。

    • 3 修改映射配置

      找到C:\Windows\System32\drivers\etc路徑下的hosts文件,將其內容修改成如下內容:

      # learn-spring-cloud
      127.0.0.1 eureka7001.com
      127.0.0.1 eureka7002.com
      

      當然我是用的SwitchHosts對該文件進行的修改。這樣的話就可以通過一臺主機(127.0.0.1即localhost)的不同端口模擬實現不同的主機(127.0.0.1:7001和127.0.0.1:7002)。

    • 4 寫配置文件YML(區別于單機)

      以前單機的時候,注冊中心的配置文件是這樣的:

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

      而現在已經有兩個注冊中心,可以看做兩臺機器,顯然 hostname 不能再叫localhost,而集群不能再這樣,對于7001端口的注冊中心,修改其配置文件:

      server:
        port: 7001
      
      eureka:
        instance:
          hostname: eureka7001.com #eureka服務端的實例名稱
        client:
          #false表示不向注冊中心注冊自己
          register-with-eureka: false
          #false表示自己端就是注冊中心,我的職責就是維護服務實例,并不需要去檢索服務
          fetch-registry: false
          service-url:
            # 互相注冊,相互守望
            defaultZone: http://eureka7002.com:7002/eureka/
      

      首先更改了其服務端的實例名稱,最重要的是在defaultZone中將自己注冊給7002,舉一反三,7002的配置文件顯然如下:

      server:
        port: 7002
      
      eureka:
        instance:
          hostname: eureka7002.com #eureka服務端的實例名稱
        client:
          #false表示不向注冊中心注冊自己
          register-with-eureka: false
          #false表示自己端就是注冊中心,我的職責就是維護服務實例,并不需要去檢索服務
          fetch-registry: false
          service-url:
            # 互相注冊,相互守望
            defaultZone: http://eureka7001.com:7001/eureka/
      

      這樣就實現了兩個服務注冊中心的相互注冊。

    • 主啟動類

      7002的主啟動類和7001一樣

      package cn.sher6j.springcloud;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
      
      /**
       * @author sher6j
       */
      @SpringBootApplication
      @EnableEurekaServer//聲明我是服務注冊中心
      public class EurekaMain7002 {
          public static void main(String[] args) {
              SpringApplication.run(EurekaMain7002.class);
          }
      }
      
    • 測試

      如圖:兩個服務中心已經完成了互相注冊。DS Replicas這個下面的信息就表示是這個Eureka Server相鄰節點,且這些節點加上自己互為一個集群。
      在這里插入圖片描述

    3. 將服務提供方服務8001發布到上面2臺Eureka集群配置中

    修改其配置文件即可

    server:
      port: 8001
    
    spring:
      application:
        name: cloud-payment-service  # 入駐Eureka服務注冊中心的服務名稱
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource  # 當前數據源操作類型
        driver-class-name: org.gjt.mm.mysql.Driver    # mysql驅動包
        url: jdbc:mysql://localhost:3306/cloud20?useUnicode=true&characterEncoding=utf-8&useSSL=false
        username: root
        password: root
    
    eureka:
      client:
        #表示是否將自己注冊進EurekaServer默認為true。
        register-with-eureka: true
        #是否從EurekaServer抓取已有的注冊信息,默認為true。單節點無所謂,集群必須設置為true才能配合ribbon使用負載均衡
        fetchRegistry: true
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 入駐的服務注冊中心地址
    
    mybatis:
      mapperLocations: classpath:mapper/*.xml
      type-aliases-package: cn.sher6j.springcloud.entities  # 所有Entity別名類所在包
    

    也就是將自己的微服務注冊到每一個服務注冊中心里去,見配置文件中的defaultZone

    4. 將服務消費方服務80發布到上面2臺Eureka集群配置中

    和上面的是一樣的,只需要修改其配置文件,將自己注冊進兩個服務注冊中心中。

    下面進行測試:首先 要啟動EurekaServer服務,即7001和7002服務,這樣就有了服務注冊中心,然后 再啟動服務提供方即8001, 最后 啟動服務消費方即80。如圖:7001和7002已經構成集群,且都可以拉取到80和8001兩個服務:
    在這里插入圖片描述

    5. 服務提供方8001服務的集群環境構建

    • 參考8001服務新建8002服務

    • 改POM:和8001的POM文件一樣

    • 寫配置文件:將端口改為8002,其他和8001相同,兩個微服務 對外暴露的服務名相同 均為cloud-payment-service 從而構成集群

      server:
        port: 8002
      
      spring:
        application:
          name: cloud-payment-service  # 入駐Eureka服務注冊中心的服務名稱
        datasource:
          type: com.alibaba.druid.pool.DruidDataSource  # 當前數據源操作類型
          driver-class-name: org.gjt.mm.mysql.Driver    # mysql驅動包
          url: jdbc:mysql://localhost:3306/cloud20?useUnicode=true&characterEncoding=utf-8&useSSL=false
          username: root
          password: root
      
      eureka:
        client:
          #表示是否將自己注冊進EurekaServer默認為true。
          register-with-eureka: true
          #是否從EurekaServer抓取已有的注冊信息,默認為true。單節點無所謂,集群必須設置為true才能配合ribbon使用負載均衡
          fetchRegistry: true
          service-url:
            # 單機版
            #      defaultZone: http://localhost:7001/eureka # 入駐的服務注冊中心地址
            # 集群版
            defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 入駐的服務注冊中心地址
      
      mybatis:
        mapperLocations: classpath:mapper/*.xml
        type-aliases-package: cn.sher6j.springcloud.entities  # 所有Entity別名類所在包
      
    • 主啟動類、業務類:直接從8001里copy即可

      package springcloud;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
      
      /**
       * 主啟動類
       * @author sher6j
       */
      @SpringBootApplication
      @EnableEurekaClient
      public class PaymentMain8002 {
          public static void main(String[] args) {
              SpringApplication.run(PaymentMain8002.class);
          }
      }
      
    • 修改controller添加端口號已區分這兩個具體的微服務:讀取配置文件中設置的端口號。8002的修改同8001。

      package cn.sher6j.springcloud.controller;
      
      import cn.sher6j.springcloud.entities.CommonResult;
      import cn.sher6j.springcloud.entities.Payment;
      import cn.sher6j.springcloud.service.PaymentService;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.web.bind.annotation.*;
      
      /**
       * @author sher6j
       */
      @RestController
      @Slf4j
      public class PaymentController {
      
          @Autowired
          private PaymentService paymentService;
      
          @Value("${server.port}")
          private String serverPort;
      
          /**
           * 插入payment
           * @param payment
           * @return
           */
          @PostMapping("/payment/create")
          public CommonResult create(@RequestBody Payment payment) {
              int result = paymentService.create(payment);
              log.info("=======插入結果:" + result);
      
              if (result > 0) {
                  return new CommonResult(200, "插入數據庫成功, 端口號:" + serverPort, result);
              } else {
                  return new CommonResult(444, "插入數據庫失敗", null);
              }
          }
      
          /**
           * 根據id查詢訂單
           * @param id
           * @return
           */
          @GetMapping("/payment/get/{id}")
          public CommonResult getPaymentById(@PathVariable("id") Long id) {
              Payment payment = paymentService.getPaymentById(id);
              log.info("=======查詢結果:" + payment);
      
              if (payment != null) {
                  return new CommonResult(200, "查詢數據庫成功, 端口號:" + serverPort, payment);
              } else {
                  return new CommonResult(444, "沒有對應記錄,查詢ID:" + id, null);
              }
          }
      }
      
    • 測試

      如圖,可以看到此時服務注冊中心構成集群,而相同名字的服務提供方的實際提供者已經出現了兩個,分別是8001和8002,,也就是說服務提供方微服務也實現了集群。
      在這里插入圖片描述
      此時再回看最開始的Eureka微服務架構圖,其集群架構圖對應本實例應為:
      在這里插入圖片描述

    6. 負載均衡

    此時,我們使用80端口的服務消費方來訪問 CLOUD-PAYMENT-SERVICE 服務,輸入網址http://localhost/consumer/payment/get/1,但是我們每次得到的數據都是:

    {
    	code: 200,
    	message: "查詢數據庫成功, 端口號:8001",
    	data: {
    		id: 1,
    		serial: "aaaa001"
    	}
    }
    

    也就是說每次訪問的具體微服務都是8001端口的CLOUD-PAYMENT-SERVICE服務,這明顯是不符合業務邏輯的,原因就是在消費方代碼中我們將服務訪問地址寫死了,沒有實現負載均衡,這顯然是不對的,所以我們應該讓80訪問服務名,而不是具體的服務,同時在配置文件中通過 @LoadBalanced 注解賦予RestTemplate負載均衡能力,該負載均衡默認為輪詢方式,所以講80服務的配置文件修改如下:

    package cn.sher6j.springcloud.config;
    
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * @author sher6j
     */
    @Configuration
    public class ApplicationContextConfig {
        @Bean
        @LoadBalanced//使用該注解賦予RestTemplate負載均衡的能力
        public RestTemplate getRestTemplate() {
            return new RestTemplate();
        }
    }
    //applicationContext.xml <bean id="" class="">
    

    然后重啟80端口,發現每次訪問 CLOUD-PAYMENT-SERVICE 服務時,具體的微服務在8001和8002之間進行輪詢切換:
    在這里插入圖片描述
    當然此時負載均衡我們還沒有用到Ribbon,再Ribbon和Eureka整個后消費者可以直接調用服務而不用再關心地址和端口號,且該服務還有負載功能。

    4. actuator微服務信息完善

    1. 主機名稱:服務名稱修改

    當前問題:在注冊中心顯示的微服務中,我們發現服務名含有主機名稱,這顯然不是我們希望看到的
    在這里插入圖片描述
    怎么能解決這個問題呢,只需要修改服務提供方(8001和8002)的配置文件,向其中的eureka部分加入即可配置該服務顯示的服務名稱

    instance:
      instance-id: payment8001
    

    最終的整體配置文件如下:

    server:
      port: 8001
    
    spring:
      application:
        name: cloud-payment-service  # 入駐Eureka服務注冊中心的服務名稱
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource  # 當前數據源操作類型
        driver-class-name: org.gjt.mm.mysql.Driver    # mysql驅動包
        url: jdbc:mysql://localhost:3306/cloud20?useUnicode=true&characterEncoding=utf-8&useSSL=false
        username: root
        password: root
    
    eureka:
      client:
        #表示是否將自己注冊進EurekaServer默認為true。
        register-with-eureka: true
        #是否從EurekaServer抓取已有的注冊信息,默認為true。單節點無所謂,集群必須設置為true才能配合ribbon使用負載均衡
        fetchRegistry: true
        service-url:
          # 單機版
    #      defaultZone: http://localhost:7001/eureka # 入駐的服務注冊中心地址
          # 集群版
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 入駐的服務注冊中心地址
      instance:
        instance-id: payment8001
    
    mybatis:
      mapperLocations: classpath:mapper/*.xml
      type-aliases-package: cn.sher6j.springcloud.entities  # 所有Entity別名類所在包
    

    8002服務的修改同上,此時再訪問注冊中心,看到的服務具體名稱中就沒有主機名了,而是我們配置好的服務名稱:
    在這里插入圖片描述

    2. 訪問信息有IP信息提示

    當前問題:我們在鼠標移動到具體服務時,提示的地址信息中并沒有服務所在具體主機的IP地址,這在開發中不方便定位具體微服務。
    在這里插入圖片描述
    解決方式仍然是通過配置文件,在配置文件中向其中的eureka部分加入即可配置該服務訪問路徑可以顯示IP地址:

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

    最終的配置文件如下:

    server:
      port: 8001
    ......
    eureka:
      client:
        ......
      instance:
        instance-id: payment8001
        prefer-ip-address: true  # 訪問路徑可以顯示IP地址
    ......
    

    鼠標再次移動到該服務時,可以發現,已經提示了IP地址:
    在這里插入圖片描述

    5. 服務發現Discovery

    對于注冊進Eureka服務注冊中心的微服務,可以通過服務發現來獲取該服務的信息。

    1. 修該微服務的Controller,向其中注入DiscoveryClient,并編寫相應Controller方法

    package cn.sher6j.springcloud.controller;
    
    ......
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    ......
    /**
     * @author sher6j
     */
    @RestController
    @Slf4j
    public class PaymentController {
    
        .......
    
        @Autowired
        private DiscoveryClient discoveryClient;
    	
        .......
    
        @GetMapping("/payment/discovery")
        public Object discovery() {
            List<String> services = discoveryClient.getServices(); //獲取服務列表的信息
            for (String service : services) {
                log.info("=======service:" + service + "=======");
            }
    
            //根據微服務名稱獲取具體服務實例
            List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
            for (ServiceInstance instance : instances) {
                log.info("=======" + instance.getServiceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri() + "=======");
            }
    
            return this.discoveryClient;
        }
    }
    

    DiscoveryClient對象中的 getServices 方法用于獲取服務列表的信息,也就是有哪些服務,如cloud-payment-service服務, getInstances 方法用于獲取服務列表對應的具體服務實例,如cloud-payment-service服務對應的8001和8002服務。

    2. 修改主啟動類

    只需要在主啟動類上添加注解@EnableDiscoveryClient,修改后的主啟動類:

    @SpringBootApplication
    @EnableEurekaClient
    @EnableDiscoveryClient
    public class PaymentMain8001 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8001.class);
        }
    }
    

    3. 測試

    訪問地址http://localhost:8001/payment/discovery,我們可以看到獲取的服務信息,即完成了服務發現:
    在這里插入圖片描述
    后臺也對服務列表進行了日志打印:
    在這里插入圖片描述

    6. Eureka自我保護(CAP里面的AP分支)

    1. 自我保護機制

    保護模式主要用于一組客戶端和EurekaServer之間存在網絡分區場景下的保護。一旦進入保護模式,Eureka Server將會嘗試保護其服務注冊表中的信息,不再刪除服務注冊表中的數據,也就是不會注銷任何微服務

    如果在Eureka Server的首頁看到以下提示,說明Eureka進入了保護模式(上面2. 單機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不會立刻清理,而是依舊會對該微服務的信息進行保存。

    2. 產生原因

    • 為什么會產生Eureka自我保護機制???

      為了防止 EurekaClient可以正常運行,但是與EurekaServer網絡不通 情況下,EurekaServer不會立刻將EurekaClient服務剔除。

    • 什么是自我保護模式?

      默認情況下,如果EurekaServer在一定時間內沒有接收到某個微服務實例的心跳,EurekaServer將會注銷該實例(默認90秒)。但是當網絡分區故障發生(延時、卡頓、擁擠)時,微服務與EurekaServer之前無法正常通信,以上行為可能變得非常危險——因為微服務本身是健康的,只是由于網絡問題鏈接不到EurekaServer,此時本不應該注銷這個微服務。Eureka通過“自我保護模式”來解決這個問題——當EurekaServer節點在短時間內丟失過多客戶端時(可能發生了網絡分區故障,網絡延時),那么這個節點就會進入自我保護模式。

      在自我保護模式中,EurekaServer會保護服務注冊表中的信息,不再注銷任何服務實例,寧可保留錯誤的服務注冊信息,也不盲目注銷任何可能健康的服務實例。使用自我保護模式,可以讓Eureka集群更加的健壯、穩定。

    3. 怎么禁止自我保護

    • 在EurekaServer端修改配置文件即可設置關閉自我保護機制

      eureka:
        server:
        	# 關閉自我保護機制,保證不可用服務被及時剔除
          enable-self-preservation: false
          # 時間間隔
          eviction-interval-time-in-ms: 2000 
      
    • 在EurekaClient端修改配置文件

      eureka:
        instance:
          instance-id: payment8001
          # Eureka客戶單向服務端發送心跳的時間間隔,默然是30秒
          lease-renewal-interval-in-seconds: 1
          # Eureka服務端在收到最后一次心跳后等待時間上限,默然為90秒,超時將剔除服務
          lease-expiration-duration-in-seconds: 2 
      

      這樣就會使EurekaClient客戶端的微服務很快死亡。

    版權聲明:本文為liujia2115原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/liujia2115/article/details/106234247

    智能推薦

    SpringCloud: 服務的注冊與發現(Eureka)

    一、spring cloud簡介 spring cloud 為開發人員提供了快速構建分布式系統的一些工具,包括配置管理、服務發現、斷路器、路由、微代理、事件總線、全局鎖、決策競選、分布式會話等等。它運行環境簡單,可以在開發人員的電腦上跑。另外說明spring cloud是基于springboot的,所以需要開發中對springboot有一定的了解。 二、創建服務注冊中心 在這里,我們需要用的的組件...

    SpringCloud之——Eureka服務注冊與發現

    SpringCloud之——Eureka服務注冊與發現 Eureka作為SpringCloud全家桶的注冊中心,最常說到的問題就是他與zookeeper的區別是什么,我們都知道ACP(可用性、一致性、分區容錯性),那么P是必須要保證的,而三者又不可能同時滿足,那么在設計的時候就看各自產品的側重點了,Eureka和Zookeeper兩個都能夠作為注冊中心使用,他們的主要區別是...

    Springcloud 服務注冊與發現 Eureka

    在Springcloud項目中,服務提供者對外提供服務,服務消費者進行消費服務,如果微服務很多,就需要一個服務管理中心去統一管理服務,而消費者在調用服務時就可以去這個管理中心中去查找需要調用的服務進行調用。 Eureka在Springcloud中就作為最常用的服務注冊與發現的組件,下面主要記錄一下Eureka的基本原理與使用方法。 Eureka是什么 Eureka是Netflix的核心模塊之一,它...

    SpringCloud 服務注冊與發現 - Eureka詳解

    Euraka官網地址(github): https://github.com/Netflix/eureka/ Euraka官方已經停更,市面上還有許多產品可以做注冊中心,替代Eureka, 如:Zoookeeper,Consul,Nacos等都是替代品 官網停更說明如下圖: Euraka基礎知識 服務治理 在傳統的RPC遠程調用框架中,管理每個服務與服務之間的依賴關系比較復雜,所以需要服務治理,管...

    SpringCloud系列-Eureka服務注冊與發現

    Eureka服務注冊與發現         Eureka是netfix開源的服務發現組件,本身是一個基于Rest的服務。它包含Server和Client兩部分。SpringCloud將它集成子項目Spring Cloud Netfix中,從而實現微服務的注冊與發現。 Application service &ndash...

    猜你喜歡

    SpringCloud(一):Eureka服務注冊與發現

    Eureka是Netflix開源的一款提供服務注冊和發現的產品,是springCloud體系中最重要最核心的組件之一。 Eureka作為SpringCloud的注冊中心,主要負責服務的注冊與發現; 每個微服務都是一個Eureka client組件,負責將該服務根據id、ip和端口注冊到Eureka Server中; Eureka Server是一個注冊中心,該組件內部維護了一個注冊表,保存了各個服...

    SpringCloud服務的注冊與發現(Eureka)

    - 服務治理的概念 服務治理是微服務架構中最為核心和基礎的模塊,主要用來實現各個微服務實列的自動化注冊與發現。微服務實例可以是一個簡單的SpringBoot程序 - 如何實現服務注冊與服務發現 在程序中服務提供方需要顯示的將服務注冊到注冊中心去。在注冊登記中心登記在自己提供的服務,主機。端口號,版本號,通信協議等等。注冊中心通過服務名進行管理,例如: 服務調用方通過服務名發起調用實現,調用方需要向...

    SpringCloud的服務注冊與發現Eureka

    服務注冊中心 所有的服務端以及訪問服務的客戶端都需要先連接到eureka服務器。在啟動服務的時候會自動注冊到eureka服務器。每一個服務都有自己的名字,在配置文件中設置的,這個名字會被注冊到eureka服務器,使用服務的一方只需要名字加上方法名就可以調用到該服務。 在默認的設置下,在啟動服務的時候,服務注冊中心也會把自己當成服務注冊給自己,所以需要禁用它的這種客戶端注冊的行為 在主類中使用注解@...

    SpringCloud : 服務的注冊與發現(Eureka)

    一、spring cloud簡介 spring cloud 為開發人員提供了快速構建分布式系統的一些工具,包括配置管理、服務發現、斷路器、路由、微代理、事件總線、全局鎖、決策競選、分布式會話等等。它運行環境簡單,可以在開發人員的電腦上跑。另外說明spring cloud是基于springboot的,所以需要開發中對springboot有一定的了解。 二、創建服務注冊中心 2.1 首先創建一個mav...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    精品国产乱码久久久久久蜜桃不卡