至關於服務之間的‘通信錄’,記錄了服務和服務地址之間的映射關係。在分佈式架構中服務會註冊到這裏。當服務須要調用其餘服務時,就在註冊中心找到其餘服務的地址,進行調用java
註冊中心通常有如下的功能:mysql
Eureka是SpringCloud微服務架構中經常使用的註冊中心,其架構圖以下:web
由其架構圖能夠看出,Eureka能夠分爲三部分:Eureka服務端,Eureka服務提供者,Eureka服務消費者。spring
其中Eureka服務端須要做爲獨立的服務運行,而服務提供者、消費者則是須要使用EurekaClient嵌入咱們本身的服務中。sql
其運行原理是這樣的:api
聰明的你這個時候會察覺到。既然消費者使用的是緩存的註冊信息。那麼必定會存在一種狀況就是服務提供者這邊已經宕機。這個時候消費者根據緩存的信息沒有及時更新就會致使調用失敗,Eureka是怎麼解決這個問題的呢?且往下看。瀏覽器
這裏推薦使用 Spring Initializer 直接建立。選擇 web 和 euraka 便可。主要引入的依賴以下:緩存
<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> </dependency>
server: port: 9000 eureka: instance: hostname: localhost client: register-with-eureka: false # 是否將本身註冊到註冊中心 fetch-registry: false # 是否從Eureka中獲取註冊信息 service-url: # Eureka Client 的請求地址 defaultZone: http://#{eureka.instance.hostname}:#{server.port}/eureka/
啓動類除了常規的 @SpringBootApplication 外,還要添加 @EnableEurekaServer 表示開啓 Eureka 服務架構
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
這裏須要特別注意:Eureka客戶端配置的服務端地址使用的key是 defaultZone,不是 default_zone 若是寫錯會致使客戶端沒法註冊服務,進而致使客戶端沒法啓動app
server: port: 9001 spring: application: name: SERVICE_PROVIDER # 服務名稱 datasource: url: jdbc:mysql://192.168.25.128:3306/mysql?characterEncoding=UTF-8&useSSL=false&serverTimezone=CTT driver-class-name: com.mysql.cj.jdbc.Driver password: 521 username: keats eureka: client: service-url: defaultZone: http://localhost:9000/eureka/ # 剛剛在Eureka Server 配置的請求地址 register-with-eureka: true # 註冊到註冊中心 fetch-registry: false # 做爲服務提供者,能夠不用從Eureka獲取註冊信息。視實際狀況而定 instance: prefer-ip-address: true # 使用IP地址註冊
Euraka 客戶端默認每隔 30 S向服務端發送一次心跳請求,若是服務端 90 S沒有收到某客戶端發送的請求將視爲客戶端宕機。會將其從服務列表剔除
搭建服務消費者和提供者的步驟相似,首先是添加 eureka-client 依賴
以後配置 application.yml 以下:
server: port: 9002 spring: application: name: SERVICE_CONSUMER # 服務名稱 eureka: client: service-url: # 剛剛在Eureka Server 配置的請求地址 defaultZone: http://localhost:9000/eureka/ fetch-registry: true register-with-eureka: false
這樣該服務就具有了從Eureka獲取服務的能力,那具體怎麼使用呢?
Spring 爲咱們提供了一個Bean:DiscoveryClient (注意須要導入:org.springframework.cloud.client.discovery 包下的DiscoveryClient 而不是 netflix 包下的類)
咱們在須要獲取服務的類裏面注入該類
@Autowired private DiscoveryClient discoveryClient;
接着調用其 getInstances(String instancdName) 方法,經過服務的名稱獲取服務列表。咱們這裏只註冊了一個服務提供方沒有搭集羣因此直接使用列表第0位的服務實體。而實體提供了 getUri() 方法用於獲取服務提供者的 url。接着咱們用該方法替換硬編碼的 url 便可完成 Eureka 的使用。核心代碼以下:
網上的不少其餘教程在這裏使用的都是 getHost() + ":" + getPort() 拼接,推測多是版本比較老舊。新API既然已經提供了 getUri() 方法咱們就要積極使用。這裏建議讀者們在使用某Bean的方法時經過打點的方式閱讀一下其開放的API,大概瞭解一下
@GetMapping("teacher/users") public List<User> getAllUser(){ List<ServiceInstance> service_provider = discoveryClient.getInstances("SERVICE_PROVIDER"); ServiceInstance serviceInstance = service_provider.get(0); return restTemplate.getForObject(serviceInstance.getUri() + "/api/v1/users", List.class); }
如上圖提示,表示Eureka進入了自我保護模式。自我保護模式的介紹以下:
Eureka Server 在運行期間會去統計心跳失敗比例在 15 分鐘以內是否高於 85%,若是高於 85%,Eureka Server 會將這些實例保護起來,讓這些實例不會過時。在我看來能夠用一句古成語來形容這種模式---「三人成虎」 即當愈來愈多的服務提供者心跳不能到達時。Eureka開始不在懷疑是提供者GG,而懷疑本身了!
在開發環境中,咱們每每啓動一個Eureka服務 + 一個 Eureka 提供者,若是此時提供者正好出了問題。90S未發送心跳。但因爲知足自我保護條件(這段時間失敗比例爲100%),Eureka不會將服務剔除。會直接致使服務消費者沒法正確獲取服務。所以開發環境中建議關閉其自我保護機制,而在生產環境打開之, yml 配置以下:
eureka: server: enable-self-preservation: false # 關閉自我保護