springcloud-Eureka-服務註冊與發現核心元件
Eureka元件
Eureka是Netfilx開源的服務發現元件,本身是一個基於rest的服務,它包含client和server兩部分。
Spirng Cloud將它整合在子專案Spirng Cloud Netfilx中,從而實現服務的註冊和發現
client註冊到Server什麼?
client註冊後還會在本地做一個快取,防止Server宕機後服務無法呼叫,如果提供服務的service宕機,此時呼叫不就出錯了嗎?所以要做Server的叢集,後文會提到。
1.eureka中的server和client的介紹及特點
- Eureka Server:提供服務發現的能力,各個微服務啟動時,會向Eureka Server註冊自己的資訊例如(IP,埠號,服務名稱等),Eureka會儲存這些資訊。
- Eureka Client:是一個java的客戶端用來簡化Eureka Server的互動。
- 微服務啟動後會週期性的(預設30秒)向Eureka Server傳送心跳,如果Eureka在規定的時間沒有收到心跳,則會登出該例項(預設90秒)。
- Eureka Client會快取服務登錄檔中的資訊。這種方式有一定的優勢首先可以降低Eureka Server的壓力,其次當所有的Eureka Server宕機服務呼叫方依然可以完成呼叫。
2.服務註冊與服務發現
- 服務註冊:當微服務client啟動時,向Eureka Server發起註冊,並上報該節點的相關資訊
- 服務發現:client從Eureka Server獲取註冊資訊,然後發起呼叫
3.Eureka Server開發
測試環境使用springcloud的Dalston版本。由IDEA快速構建出springboot專案,再引入相關依賴。
1.引入springcloud的相關依賴
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--eureka server--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> <!--依賴管理,所引入的jar都是沒有版本號的,全部都是Dalston版本--> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.RC1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!--倉庫--> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
2.入口類的開發
//啟用EurekaServer
@EnableEurekaServer
@SpringBootApplication
public class EurekaServer {
public static void main(String[] args) {
SpringApplication.run(EurekaServer.class,args);
}
}
3.配置檔案
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
#不能向自身註冊
eureka.client.register-with-eureka=false
#關閉自我發現
eureka.client.fetch-registry=false
#本例項名稱
spring.application.name=eureka
#使用埠號
server.port=8761
注意:Eureka本身既是Server又是Client,作為Server不能向自身註冊,自我發現關閉。
檢視Server的狀態,Eureka提供了一個web介面檢視當前Server上的註冊例項以及其他資訊
地址:http://127.0.0.1:8761/
這裡忘記截圖了,假裝沒有例項註冊,將就看下
2.Eureka Client的開發
1.jar包和Server不同
將spring-cloud-starter-eureka-server改為spring-cloud-starter-eureka
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
2.入口類
//該註解可以將client註冊到以zookeeper為server的服務中心
@EnableDiscoveryClient
//該註解註冊到Eureka @EnableEurekaClient
@SpringBootApplication
public class HiApplication {
public static void main(String[] args) {
SpringApplication.run(HiApplication.class, args);
}
}
3.配置檔案
#指定Eureka Server的地址
eureka.client.service-url.default-zone=http://localhost:8761/eureka
server.port=8762
spring.application.name=eureka-client
3.Eureka client之間的相互呼叫測試
準備兩個client,一個作為消費者,一個作為服務者。
服務者
1.匯入相關的jar
同上Client
2.入口類同上
3.配置檔案
eureka.client.service-url.default-zone=http://localhost:8761/eureka
server.port=8762
spring.application.name=eureka-provider
編寫一個作為測試用的Controller
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/test1")
public String test(String name){
return "xixixi 8763 :"+name;
}
}
消費者
1.jar不變
2.入口類不變
3.配置檔案
eureka.client.service-url.default-zone=http://localhost:8761/eureka
server.port=8763
spring.application.name=eureka-client
4.使用java配置RestTemplate
@Configuration
public class RestTemplateConf {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
關於RestTemplate的說明:類似於HTTPClient,在程式中發起http請求,RestTemplate是對HTTPClient的封裝。
5.寫個簡單的控制器
@RestController
@RequestMapping("/query")
public class ClientController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/test")
public String test(String name){
String template = restTemplate.getForObject("http://EUREKA-PROVIDER/test/test1?name=" + name, String.class);
return template;
}
}
方法說明:getForObject("http://EUREKA-PROVIDER/test/test1?name=" + name, String.class); EUREKA-PROVIDER是註冊過的例項名稱,可以在Eureka Server的web介面看到的,大小寫都可以,是有對應的對映的地址的。
6.測試
啟動Eureka Server,兩個Client,檢視Eureka Server 中註冊的例項是否有兩個Client,兩個則正常;
位址列發起請求:http://localhost:8763/query/test?name=xixi
檢視結果呼叫成功。
4.Eureka的自我保護機制
Eureka進入自我保護機制的最直接體現,是Eureka首頁輸出警告如圖:
預設情況下,如果Eureka Server在一定時間內沒有接受到服務例項的心跳,Eureka將會登出該例項(預設90秒).但是當網路分割槽發生故障時,微服務和Eureka Server 無法正常通訊.以上行為可能變得特別危險了-因為微服務本身是健康的,此時不能登出該服務例項.
Eureka通過自我保護機制來解決這個問題,當Eureka Server在短時間丟失過多的服務例項(可能發生了網路分割槽的故障,那麼這個節點進入自我保護模式,一旦進入此模式,Eureka Server將會保護服務登錄檔中的資訊,不再刪除服務登錄檔中的資料(也就是不再登出任何的服務例項),當網路故障恢復後,Eureka會自動退出自我保護模式。
綜上,自我保護模式是一種應對網路故障的安全保護措施,它的架構哲學是寧可同時保留所有的微服務,也不盲目登出任何健康的微服務,使用自我保護模式可以讓Eureka,更加健壯,穩定。
在springcloud中可以通過
#關閉自我保護機制 預設開啟
eureka.server.enable-self-preservation=false
如果想及時剔除eureka的服務除了關閉自我保護機制外,可以調低eureka的心跳值
eureka-server服務端
配置檔案中新增如下配置
#關閉保護機制,以確保註冊中心將不可用的例項正確剔除
eureka.server.enable-self-preservation=false
#(代表是5秒,單位是毫秒,清理失效服務的間隔 )
eureka.server.eviction-interval-timer-in-ms=5000
客戶端
配置檔案中新增如下配置
# 心跳檢測檢測與續約時間
# 測試時將值設定設定小些,保證服務關閉後註冊中心能及時踢出服務
# 配置說明
# lease-renewal-interval-in-seconds 每間隔10s,向服務端傳送一次心跳,證明自己依然”存活“
# lease-expiration-duration-in-seconds 告訴服務端,如果我20s之內沒有給你發心跳,就代表我“死”了,將我踢出掉。
eureka.instance.lease-renewal-interval-in-seconds=10
eureka.instance.lease-expiration-duration-in-seconds=20
5.client的高可用
搭建Client的叢集十份簡單,只需要保證例項名稱一致,比如都叫做:client-provider,但是埠不能衝突。
保證埠號不一致(測試環境)
保證例項名一致!!!
示例配置
eureka.client.service-url.defaultZone=http://peer:8761/eureka
spring.application.name=eureka-provider
server.port=8764
eureka.client.service-url.defaultZone=http://peer:8761/eureka
spring.application.name=eureka-provider
server.port=8763
最終在Eureka Server的web介面可以看到如下一個叢集
6.Eureka Server的高可用
單節點的Eureka Server 不適合線上的生產環境,Eureka Client會定時連線Eureka Server,獲取服務登錄檔中的資訊並快取在本地,微服務消費遠端API總是使用本地快取的資料,因此一般來說既是Eureka Server發生宕機,也不會影響到服務的呼叫,但是如果Eureka Server宕機時某些微服務也出現了不可用的情況,Eurek Client中的快取若不被更新,可能會影響到服務的呼叫,甚至影響到整個系統的高可用性,因此在生產環境會部署一個高可用的Eureka Server叢集。
Eureka可以通過執行多個例項並互相註冊實現高可用部署,Eureka Server例項會彼此同步資訊。
Server1向Server2註冊
server.port=8761
eureka.client.service-url.defaultZone=http://peer1:8765/eureka
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.instance.hostname=peer1
server.port=8762
eureka.client.service-url.defaultZone=http://peer:8761/eureka
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
spring.application.name=peer
注:peer是hosts對映本地127.0.0.1,http://peer1:8761/eureka,peer1作為Eureka複製集的名稱
注意:在client註冊到eureka server時 需要填寫所有eureka server的地址
eureka.client.service-url.defaultZone=http://peer:8761/eureka,http://peer1:8765/eureka
7.Eureka的健康監測
服務有時候也會出現異常情況,我們也需要知道某個服務的健康狀況。我們可以通過新增如下依賴,開啟某個服務的健康檢查。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
我們來訪問一下這個介面http://localhost:port/health,看到了一個很簡短的健康報告:
{"description":"Spring Cloud Eureka Discovery Client","status":"UP"}
類似的還有
- info 顯示任意的應用資訊
- metrics 展示當前應用的指標資訊 true
- mappings 顯示所有@RequestMapping路徑的整理列表
- trace 顯示trace資訊(預設為最新的一些HTTP請求)
- health 展示應用的健康資訊
- beans 顯示一個應用中所有Spring Beans的完整列表
這其中有一些是敏感資訊,出於安全考慮,一般使用者無法訪問,如果內網情況下可以
eureka.client.healthcheck.enabled=true
#關掉認證(公網下的生產環境不建議,內網部署可以)
management.security.enabled=false
8.http VS rpc
應用間通訊方式主要是HTTP和RPC,在微服務架構中兩大配方的主角分別是:
- Dubbo RPC框架
基於dubbo開發的應用還是要依賴周邊的平臺生態, 相比其它的RPC框架, dubbo在服務治理與服務整合上可謂是非常完善, 不僅提供了服務註冊,發現還提供了負載均衡,叢集容錯等基礎能力同時,還提供了面向開發測試節點的Mock和泛化呼叫等機制。 在spring cloud 出現之前dubbo在國內應用十分廣泛,但dubbo定位始終是一個RPC框架。
- SpringCloud 微服務框架(HTTP通訊)
Spring Cloud 的目標是微服務架構下的一棧式解決方案,自dubbo復活後dubbo官方表示要積極適配到spring cloud的生態方式,比如作為springcloud的二進位制通訊方案來發揮dubbo的效能優勢,或者通過dubbo的模組化以及對http的支援適配到Spring Cloud,但是到目前為止dubbo與spring cloud 還是不怎麼相容,spring cloud 微服務架構下微服務之間使用http的RestFul方式進行通訊,Http RestFul 本身輕量易用適用性強,可以很容易跨語言,跨平臺,或者與已有的系統整合。