1. 程式人生 > >Eureka 註冊中心看這一篇就夠了

Eureka 註冊中心看這一篇就夠了

     服務註冊中心是服務實現服務化管理的核心元件,類似於目錄服務的作用,主要用來儲存服務資訊,譬如提供者 url 串、路由資訊等。服務註冊中心是微服務架構中最基礎的設施之一。   在微服務架構流行之前,註冊中心就已經開始出現在分散式架構的系統中。Dubbo 是一個在國內比較流行的分散式框架,被大量的中小型網際網路公司所採用,它提供了比較完善的服務治理功能,而服務治理的實現主要依靠的就是註冊中心。    ## 什麼是註冊中心      註冊中心可以說是微服務架構中的“通訊錄”,它記錄了服務和服務地址的對映關係。在分散式架構中,服務會註冊到這裡,當服務需要呼叫其它服務時,就到這裡找到服務的地址,進行呼叫。 ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/timg.jfif)   舉個現實生活中的例子,比如說,我們手機中的通訊錄的兩個使用場景: > 當我想給張三打電話時,那我需要在通訊錄中按照名字找到張三,然後就可以找到他的手機號撥打電話。—— 服務發現 > > 李四辦了手機號並把手機號告訴了我,我把李四的號碼存進通訊錄,後續,我就可以從通訊錄找到他。—— 服務註冊 > > 通訊錄 —— ?什麼角色(提示:服務註冊中心)   總結:服務註冊中心的作用就是**服務的註冊**和**服務的發現**。    ## 常見的註冊中心    - Netflix Eureka - Alibaba Nacos - HashiCorp Consul - Apache ZooKeeper - CoreOS Etcd - CNCF CoreDNS    | 特性 | Eureka | Nacos | Consul | Zookeeper | | :-------------- | :---------- | :------------------------- | :---------------- | :--------- | | CAP | AP | CP + AP | CP | CP | | 健康檢查 | Client Beat | TCP/HTTP/MYSQL/Client Beat | TCP/HTTP/gRPC/Cmd | Keep Alive | | 雪崩保護 | 有 | 有 | 無 | 無 | | 自動登出例項 | 支援 | 支援 | 不支援 | 支援 | | 訪問協議 | HTTP | HTTP/DNS | HTTP/DNS | TCP | | 監聽支援 | 支援 | 支援 | 支援 | 支援 | | 多資料中心 | 支援 | 支援 | 支援 | 不支援 | | 跨註冊中心同步 | 不支援 | 支援 | 支援 | 不支援 | | SpringCloud整合 | 支援 | 支援 | 支援 | 支援 |    ## 為什麼需要註冊中心      瞭解了什麼是註冊中心,那麼我們繼續談談,為什麼需要註冊中心。在分散式系統中,我們不僅僅是需要在註冊中心找到服務和服務地址的對映關係這麼簡單,我們還需要考慮更多更復雜的問題: - 服務註冊後,如何被及時發現 - 服務宕機後,如何及時下線 - 服務如何有效的水平擴充套件 - 服務發現時,如何進行路由 - 服務異常時,如何進行降級 - 註冊中心如何實現自身的高可用   這些問題的解決都依賴於註冊中心。簡單看,註冊中心的功能有點類似於 DNS 伺服器或者負載均衡器,而實際上,註冊中心作為微服務的基礎元件,可能要更加複雜,也需要更多的靈活性和時效性。所以我們還需要學習更多 Spring Cloud 微服務元件協同完成應用開發。    ## 註冊中心解決了什麼問題    - 服務管理 - 服務的依賴關係管理    ## 什麼是 Eureka 註冊中心      Eureka 是 Netflix 開發的服務發現元件,本身是一個基於 REST 的服務。Spring Cloud 將它整合在其子專案 Spring Cloud Netflix 中,實現 Spring Cloud 的服務註冊與發現,同時還提供了負載均衡、故障轉移等能力。    ## Eureka 註冊中心三種角色    ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/timg-1578234270981.jfif) ### Eureka Server      通過 Register、Get、Renew 等介面提供服務的註冊和發現。    ### Application Service(Service Provider)      服務提供方,把自身的服務例項註冊到 Eureka Server 中。    ### Application Client(Service Consumer)      服務呼叫方,通過 Eureka Server 獲取服務列表,消費服務。    ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578648274465.png)    ## Eureka 入門案例    ### 建立專案      我們建立聚合專案來講解 Eureka,首先建立一個 pom 父工程。 ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/image-20200213113319718.png) ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578822985788.png) ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578823080703.png)    ### 新增依賴      pom.xml ```xml ```    ### 註冊中心 eureka-server      在剛才的父工程下建立 `eureka-server` 註冊中心的專案。    #### 建立專案    ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578836332989.png) ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/image-20200213113447822.png) ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578239500169.png) ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/image-20200213113547468.png) ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578823384080.png)    #### 新增依賴      pom.xml ```xml ```    #### 配置檔案      application.yml ```yml server: port: 8761 # 埠 spring: application: name: eureka-server # 應用名稱 # 配置 Eureka Server 註冊中心 eureka: instance: hostname: localhost # 主機名,不配置的時候將根據作業系統的主機名來獲取 client: register-with-eureka: false # 是否將自己註冊到註冊中心,預設為 true fetch-registry: false # 是否從註冊中心獲取服務註冊資訊,預設為 true service-url: # 註冊中心對外暴露的註冊地址 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ ```   此時如果直接啟動專案是會報錯的,錯誤資訊:`com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect`,這是因為 Eureka 預設開啟了**將自己註冊至註冊中心**和**從註冊中心獲取服務註冊資訊**的配置,如果該應用的角色是註冊中心並是單節點的話,要關閉這兩個配置項。    #### 啟動類      EurekaServerApplication.java ```java package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication // 開啟 EurekaServer 註解 @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } ```    #### 訪問      訪問:http://localhost:8761/ ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578243640844.png)    ## 高可用 Eureka 註冊中心    ### 註冊中心 eureka-server    #### 建立專案      在剛才的父工程下再建立一個 `eureka-server02` 註冊中心的專案,如果是多機器部署不用修改埠,通過 IP 區分服務,如果在一臺機器上演示需要修改埠區分服務。    #### 新增依賴      pom.xml ```xml ```    #### 配置檔案      叢集配置下,註冊中心需要相互註冊實現資訊的同步。   eureka-server 的 application.yml ```yml server: port: 8761 # 埠 spring: application: name: eureka-server # 應用名稱(叢集下相同) # 配置 Eureka Server 註冊中心 eureka: instance: hostname: eureka01 # 主機名,不配置的時候將根據作業系統的主機名來獲取 client: # 設定服務註冊中心地址,指向另一個註冊中心 service-url: # 註冊中心對外暴露的註冊地址 defaultZone: http://localhost:8762/eureka/ ```      eureka-server02 的 application.yml ```yml server: port: 8762 # 埠 spring: application: name: eureka-server # 應用名稱(叢集下相同) # 配置 Eureka Server 註冊中心 eureka: instance: hostname: eureka02 # 主機名,不配置的時候將根據作業系統的主機名來獲取 client: # 設定服務註冊中心地址,指向另一個註冊中心 service-url: # 註冊中心對外暴露的註冊地址 defaultZone: http://localhost:8761/eureka/ ```    #### 啟動類      啟動類不變,啟動兩個 server。    #### 訪問      訪問:http://localhost:8761/ 或者 http://localhost:8762/ 都出現如下圖說明互相註冊成功。 ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578311267949.png)   `Status` 顯示方式為預設值,如果想要清晰可見每個服務的 IP + 埠需要通過以下配置來實現。    #### 顯示 IP + 埠      一個普通的 Netflix Eureka 例項註冊的 ID 等於其主機名(即,每個主機僅提供一項服務)。 Spring Cloud Eureka 提供了合理的預設值,定義如下:${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}},也就是:主機名:應用名:應用埠。   我們也可以可以自定義進行修改: ```yml eureka: instance: prefer-ip-address: true # 是否使用 ip 地址註冊 instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port ``` ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578311606022.png)    ### 服務提供者 service-provider    #### 建立專案      在剛才的父工程下建立一個 `service-provider` 服務提供者的專案。 ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578836246536.png) ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/image-20200213113447822.png) ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578288878277.png) ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/image-20200213113547468.png) ![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578824040960.png)    #### 新增依賴      pom.xml ```xml ```    #### 配置檔案      application.yml ```yml server: port: 7070 # 埠 spring: application: name: service-provider # 應用名稱(叢集下相同) # 配置 Eureka Server 註冊中心 eureka: instance: prefer-ip-address: true # 是否使用 ip 地址註冊 instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port client: service-url: # 設定服務註冊中心地址 defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/ ```    #### 實體類      Product.java ```java package com.example.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data @NoArgsConstructor @AllArgsConstructor public class Product implements Serializable { private Integer id; private String productName; private Integer productNum; private Double productPrice; } ```    #### 編寫服務      ProductService.java ```java package com.example.service; import com.example.pojo.Product; import java.util.List; /** * 商品服務 */ public interface ProductService { /** * 查詢商品列表 * * @return */