搭建服務註冊中心
首先創建一個基於Spring boot的工程,命名爲eureka-server,並在pom.xml中引入必要的內容:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
通過@EnableEurekaServer註解啓動一個服務註冊中心給其它服務,這一步非常的簡單,只需要在一個基礎的spring boot 項目主類中添加註解就可以開啓,如下:
package com.eureka.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
默認情況下該服務註冊中心會將自己作爲客戶端註冊自己,所以我們需要禁用它的客戶端行爲,只需要在application.properties配置文件中做如下配置:
server.port=9001
eureka.instance.hostname=localhost
#是否將自己註冊爲服務(不向註冊中心註冊自己)
eureka.client.register-with-eureka=false
#禁止向註冊中心檢索服務
eureka.client.fetch-registry=false
#服務地址
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka
#是否關閉自我保護機制
eureka.server.enable-self-preservation=true
- eureka.client.register-with-eureka 由於該應用是註冊中心,所以設置爲false,代表不向註冊中心註冊自己。
- eureka.client.fetch-registry 由於註冊中心的職責就是維護服務實例,它並不需要去檢索服務,所以設置爲false。
在完成上面的配置後,啓動應用並訪問http://localhost:9001/,可以看到如下圖中的Eureka信息面板,其中Instances currently registered with Eureka信息欄爲空,說明還沒用註冊任何服務。
註冊服務提供者
在完成註冊中心的搭建後,我們創建一個基礎的spring boot應用eureka-client,在pom.xml中添加服務依賴。
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<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-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
在啓動類上添加@EnableEurekaClient註解激活Eureka中的DiscoveryClient實現:
package com.eureka.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}
最後我們需要在application.properties中添加spring.application.name來爲服務命名,通過eureka.client.service-url.defaultZone來指定註冊中心的地址,完整配置如下:
spring.application.name=service-test
eureka.client.service-url.defaultZone=http://localhost:9001/eureka
啓動eureka-client服務,我們可以通過控制檯看到服務成功的註冊:
2018-12-18 20:07:12.403 INFO 7352 --- [ main] com.netflix.discovery.DiscoveryClient : Discovery Client initialized at timestamp 1545134832291 with initial instances count: 0
2018-12-18 20:07:12.407 INFO 7352 --- [ main] o.s.c.n.e.s.EurekaServiceRegistry : Registering application SERVICE-TEST with eureka with status UP
2018-12-18 20:07:12.408 INFO 7352 --- [ main] com.netflix.discovery.DiscoveryClient : Saw local status change event StatusChangeEvent [timestamp=1545134832408, current=UP, previous=STARTING]
2018-12-18 20:07:12.455 INFO 7352 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_SERVICE-TEST/yaomingyang-bjb.go-goal.com:service-test: registering service...
2018-12-18 20:07:12.514 INFO 7352 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2018-12-18 20:07:12.524 INFO 7352 --- [ main] .s.c.n.e.s.EurekaAutoServiceRegistration : Updating port to 8080
2018-12-18 20:07:12.527 INFO 7352 --- [ main] c.eureka.client.EurekaClientApplication : Started EurekaClientApplication in 6.747 seconds (JVM running for 7.312)
2018-12-18 20:07:12.879 INFO 7352 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_SERVICE-TEST/yaomingyang-bjb.go-goal.com:service-test - registration status: 204
也可以通過Eureka的信息面板Instances currently registered with Eureka一欄中看到服務的註冊信息。
自我保護
當我們在本地調試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 Server的自我保護機制;服務註冊到Eureka Server註冊中心後會維護一個心跳連接,告訴Eureka Server註冊中心我還活着。Eureka Server註冊中心會統計心跳失敗的比例在在15分鐘內是否低於85%,如果出現低於的情況(在單機調試的時候很容易滿足,實際在生產環境中通常由於網絡不穩定導致),Eureka Server會將當前的實例註冊信息保護起來,讓這些實例不會過期,儘可能保護這心註冊信息。但是, 在這段保護期間內實例若出現問題, 那麼客戶端很容易拿到實際已經不存在的服務實例, 會出現調用失敗的清況, 所以客戶端必須要有容錯機制, 比如可以使用請求重試、斷路器等機制。
由於本地調試很容易觸發註冊中心的保護機制, 這會使得註冊中心維護的服務實例不那麼準確。所以, 我們在本地進行開發的時候, 可以使用eureka.server.enable-self-preservation=false 參數來關閉保護機制, 以確保註冊中心可以將不可用的實例正確剔除。