三、Eurake 服務註冊與發現
3、 Eurake 服務註冊與發現
3.1 基於Springboot構建Eurake服務
在第二節中《Springboot專案構建》中的第三步 中選擇如下元件:左側選擇cloud Discovery在其子元件中選擇EurakeServer,我們在這裡面還可以看到EurakeDiscovery、ZookeeperDiscovery等元件。 其中EurakeDiscovery就是我們後面,將服務提供方的服務註冊到EurakeServer 中時需要引入的元件。
專案構建成功後我們會在pom.xml發現如下依賴:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency>
說明我們已經成功引入了EurakeServer。 不過我們還需要進行下面配置 雖然我們已經引入了EurakeServer 元件,但我們還需要啟用他(後面很多元件也需要類似的方式去啟用):
@SpringBootApplication
@EnableEurekaServer
public class EurekaserverApplication {
public static void main(String[] args) { SpringApplication.run(EurekaserverApplication.class, args); } }
我們通過@EnableEurekaServer去啟用Eurake
在resources/application.properties中新增如下配置:
server.port=8761 eureka.client.register-with-eureka=false #是否將自己註冊到EurrkeServer,預設為true eureka.client.fetch-registry=false #表示是否從EurekaServer獲取註冊資訊,預設為true,表示需要從其他server同步資訊 eureka.client.service-url.defaultZone= http://localhost:8761/eureka/#設定與EurekaServer 互動的地址,查詢服務和註冊服務都依賴這個地址
至此,我們的Eurake已經配置完成了,是不是很簡單。 啟動服務,開啟http://localhost:8761/我們看看見如下頁面:
目前還沒有服務註冊進來。
Now that we’ve stood up a service registry, let’s stand up a client that both registers itself with the
registry and uses the Spring Cloud DiscoveryClient abstraction to interrogate the registry for it’s own host and port. The @EnableDiscoveryClient activates the Netflix Eureka DiscoveryClient implementation. There are other implementations for other service registries like Hashicorp’s Consul or Apache Zookeeper.
現在,我們已經註冊了一個服務註冊中心,讓我們再使用登錄檔註冊自己的客戶端,並使用Spring Cloud DiscoveryClient抽象來詢問登錄檔本身的主機和埠。@EnableDiscoveryClient啟用Netflix Eureka DiscoveryClient實現。還有其他服務註冊的實現,比如Hashicorp的領事或Apache Zookeeper。
3.2 基於Springboot 構建服務提供方
在第二節中《Springboot專案構建》中的第三步 中選擇如下元件:
左側選擇cloud Discovery在其子元件中選擇EurakeDiscovery
專案構建成功後我們會在pom.xml發現如下依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
其實與構建EurakeServer 的依賴一樣。
啟用服務發現:
@SpringBootApplication
@EnableDiscoveryClient
public class AppApplication {
public static void main(String[] args) {
SpringApplication.run(AppApplication.class, args);
}
}
在resources/application.properties中新增如下配置:
server.port=8802 #應用埠號
spring.application.name=app-8801 #服務名稱
eureka.client.service-url.defalutZone= http://localhost:8761/eureka/ #EurekaServer服務地址
turbine.combine-host-port=true #同一主機上的服務,以不同埠號區分,預設情況下是以host來區分,後面服務監控時是將到
eureka.instance.prefer-ip-address=true #表示將自己的IP註冊到EurekaServer 上,如果不配置或者將其設定為false,則表示將微服務所在系統的hostname註冊到EurekaServer上
啟動服務,我們再次開啟http://localhost:8761/我們發現多了一條服務:
我們通過不同埠再次啟動該服務 我們發現有多了一條服務:
我們發現這兩個服務 屬於一個共同的application:APP-8801 ,當服務呼叫端Client去呼叫該服務是,只需知道服務名稱 APP-8801 ,Eurake會通過Ribbon進行負載均衡 隨機請求兩個服務中的一個服務,服務在均衡的策略是可以配置的。在《4、Ribbon 客戶端負載均衡》我會具體介紹,如何去設計負載均衡的策略。
3.3 EurakeServer 高可用
單點的Eurake server 在生產環境下並不適用,一旦發生宕機,會造成所有服務之間的呼叫無法適用,在3.1中配置EurakeServer時 有如下兩個屬性:
eureka.client.register-with-eureka=false #是否將自己註冊到EurrkeServer,預設為true
eureka.client.fetch-registry=false #表示是否從EurekaServer獲取註冊資訊,預設為true,表示需要從其他server同步資訊
我關閉了 eurakaServer 將自己註冊的功能,和sever之間的同步功能, 他們是預設開啟的。 我們只要將這兩個設定為true,就可以實現Eurake的高可用了。
Eureka自我保護性
預設情況下Eureka 在90內沒有獲取的服務的心跳,將登出該服務。但是有時候是網路分割槽故障的問題導致Eureka無法收到心跳,服務本身是健壯的,如果刪除此服務,這會導致服務不可用。當開啟了Eureka自我保護後,Eureka會保護此服務在登錄檔中的資訊,使其不會被刪除,等網路恢復後,Eureka節點會自動退出自我保護模式。 Eureka 的自我保護模式預設是允許開啟的,如要禁用可在application.properties 中新增如下配置:
eureka.server.enable-self-preservation=false
3.4 EurakeSever 認證
在生產環境下,我們不可能允許什麼服務都能註冊到Eurake 中,為此需要新增EurakeServer的身份認證。
我們需要在EurakeSever中新增如下依賴:org.springframework.bootspring-boot-starter-security
並在application.properties 中新增如下資訊:
#新增basic認證
security.basic.enabled=true
security.user.name=user
security.user.password=password
此時我們已經為EurakeSever 開啟了Basic 認證
為此,我們也修改服務端,我們只需要將服務提供端application.properties 中原來的
eureka.client.service-url.defalutZone= http://localhost:8761/eureka/
變為: eureka.client.service-url.defalutZone= http://user:[email protected]:8761/eureka/
3.5 Eureka Server Rest 端點
非java編寫的服務可以利用這些Rest端點去操作Eureka。
操作 | HTTP | action | 描述 |
---|---|---|---|
註冊新的應用例項 | POST | /eureka/v2/apps/appID | 接受JSON/XML格式請求,返回204響應碼錶示成功 |
傳送應用例項心跳 | PUT | /eureka/v2/apps/appID/instanceID | 返回響應碼200表示成功,404表示instanceID不存在 |
查詢所有例項 | GET | /eureka/v2/apps | 返回響應碼200表示成功,響應內容格式JSON/XML |
為所有appID例項做查詢(Query for all appID instances) | GET | /eureka/v2/apps/appID | 返回響應碼200表示成功,響應內容格式JSON/XML |
為特定的appID/instanceID做查詢 | GET | /eureka/v2/apps/appID/instanceID | 返回響應碼200表示成功,響應內容格式JSON/XML |
為特定的instanceID做查詢 | GET | /eureka/v2/instances/instanceID | 返回響應碼200表示成功,響應內容格式JSON/XML |
停止服務例項(Take instance out of service) | PUT | /eureka/v2/apps/appID/instanceID/status?value=OUT_OF_SERVICE | 返回響應碼200表示成功,500失敗。 |
將例項恢復到服務(移除覆蓋) | DELETE | /eureka/v2/apps/appID/instanceID/status?value=UP | (value=UP是可選的,它被建議用於fallback狀態,由於取消了覆蓋) 返回響應碼200表示成功,500失敗。 |
更新元資料 | PUT | /eureka/v2/apps/appID/instanceID/metadata?key=value | 返回響應碼200表示成功,500失敗。 |
查詢特定vip address 下的所有例項 | GET | /eureka/v2/vips/vipAddress | 返回響應碼200表示成功,響應內容格式:JSON/XML,返回404表示vipAddress不存在 |
查詢特定secure vip address下所有例項 | GET | /eureka/v2/svips/svipAddress | 返回響應碼200表示成功,響應內容格式:JSON/XML,返回404表示svipAddress不存在 |
如我請求查詢所有例項:http://localhost:8761/eureka/apps獲取到如下結果:
對於我們使用java編寫的應用,基於Springcloud EurekaDiscovery 中已經分裝這些功能。下面對原始碼進行分析一下。
我們可以發現Springcloud 定義了 DiscoveryClient 介面,來抽象Rest端,其下面有三實現類,我們關注的是基於Eureka實現的EurekaDiscoveryClient。檢視此類的實現:此類中引入了com.netflix.discovery包下的EurakeClient 介面。實現此介面的類是com.netflix.discovery包下的DiscovClient 類。