Spring-Cloud Euraka是Spring Cloud集合中一個組件,它是對Euraka的集成,用於服務註冊和發現。Eureka是Netflix中的一個開源框架。它和 zookeeper、Consul同樣,都是用於服務註冊管理的,一樣,Spring-Cloud 還集成了Zookeeper和Consul。html
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- 最新版的 eureka 服務端包 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> <!-- SpringCloud依賴,起到管理版本的做用 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR9</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Release Train | Boot Version |
---|---|
2020.0.x aka Ilford | 2.4.x |
Hoxton | 2.2.x, 2.3.x (Starting with SR5) |
Greenwich | 2.1.x |
Finchley | 2.0.x |
Edgware | 1.5.x |
Dalston | 1.5.x |
@EnableEurekaServer
註解,代表這是一個Eureka服務端@SpringBootApplication @EnableEurekaServer public class SpringCloudEurekaApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudEurekaApplication.class, args); } }
server.port=8080 spring.application.name=Eureka-Server # 指定了Eureka服務端的IP eureka.instance.hostname=localhost eureka.instance.statusPageUrl=http://${eureka.instance.hostname}:${server.port}/info eureka.instance.healthCheckUrl=http://${eureka.instance.hostname}:${server.port}/health eureka.instance.homePageUrl=http://${eureka.instance.hostname}/ # 表示是否將服務註冊到Eureka服務端,因爲自身就是Eureka服務端,因此設置爲false # eureka.client.register-with-eureka=false # 表示是否從Eureka服務端獲取服務信息,由於這裏只搭建了一個Eureka服務端,並不須要從別的Eureka服務端同步服務信息,因此這裏設置爲false # eureka.client.fetch-registry=false # 指定Eureka服務端的地址,默認值爲http://localhost:8761/eureka 指定Eureka服務端的地址爲另一個Eureka服務端的地址8081 eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/ # 用於定義服務續約任務的調用間隔時間,默認30秒 eureka.client.serviceUrl.registry-fetch-interval-seconds=5
因爲尚未Eureka客戶端將服務註冊進來,因此Instances currently registered with Eureka列表是空的java
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</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-web</artifactId> </dependency> <!-- 監控管理 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies> <!-- SpringCloud依賴,起到管理版本的做用 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR9</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
@EnableDiscoveryClient
註解,代表這是一個Eureka客戶端@SpringBootApplication @EnableDiscoveryClient public class SpringCloudProviderApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudProviderApplication.class, args); } }
@RestController public class TestController { @GetMapping("/hello") public String hello() { return "hello world"; } }
# 指定了服務的端口爲8081 server.port=8082 # 指定服務名稱爲Server-Provider,後續服務消費者要獲取上面TestController中接口的時候會用到這個服務名 spring.application.name=Server-Provider # 雖然這兩個配置的默認值就是true,但這裏仍是顯式配置下,使Eureka客戶端的功能更爲直觀(即向服務端註冊服務並定時從服務端獲取服務緩存到本地) eureka.client.register-with-eureka=true eureka.client.fetch-registry=true # 指定Eureka服務端的地址,這裏爲上面定義的Eureka服務端地址 eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/,http://localhost:8081/eureka/ # 訪問路徑能夠顯示IP地址 eureka.instance.prefer-ip-address=true
Registered Applications size is zero : true Application version is -1: true Getting all instance registry info from the eureka server The response status is 200 Starting heartbeat executor: renew interval is: 30 InstanceInfoReplicator onDemand update allowed rate per min is 4 Discovery Client initialized at timestamp 1611244216061 with initial instances count: 0 Registering application SERVER-PROVIDER with eureka with status UP Saw local status change event StatusChangeEvent [timestamp=1611244216076, current=UP, previous=STARTING] DiscoveryClient_SERVER-PROVIDER/DESKTOP-7LUOFJF.lan:Server-Provider:8081: registering service... Tomcat started on port(s): 8081 (http) with context path '' Updating port to 8081 DiscoveryClient_SERVER-PROVIDER/DESKTOP-7LUOFJF.lan:Server-Provider:8081 - registration status: 204
UP表示在線的意思(若是Eureka客戶端正常關閉,那麼這裏的狀態將變爲DOWN),點擊後面的連接http://192.168.68.233:8081/actuator/info將訪問該服務的/info
接口:git
{"app":{"name":"Server-Provider"}}
這時候關閉Eureka客戶端,再次刷新http://localhost:8080/github
可看到雖然Eureka客戶端已經關閉了,可是Eureka服務端頁面的服務服務列表中依然還有該服務,而且頁面紅色文字提示web
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已經進入了保護模式。微服務在部署以後可能因爲網絡問題形成Eureka客戶端沒法成功的發送心跳給Eureka服務端,這時候Eureka服務端認定Eureka客戶端已經掛掉了,雖然實際上Eureka客戶端還在正常的運行着。而保護模式就是爲了解決這個問題,即當Eureka服務端在短期內同時丟失了過多的Eureka客戶端時,Eureka服務端會進入保護模式,不去剔除這些客戶端。由於咱們這裏只部署了一個Eureka客戶端服務,因此關閉客戶端後知足「短期內丟失過多Eureka客戶端」的條件。spring
在開發中能夠先將保護模式給關了,咱們在Eureka服務端加上一條配置緩存
eureka.server.enable-self-preservation= false
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
# 啓用監控 # 開放全部端點health,info,metrics,經過actuator/+端點名就能夠獲取相應的信息。默認打開health和info,metrics默認不開放 management.endpoints.web.exposure.include=* #未開啓actuator/health時,咱們獲取到的信息是{"status":"UP"},status的值還有多是 DOWN。開啓後打印詳細信息 management.endpoint.health.show-details=always info.app.name=Server-Provider
localhost根據本身部署的服務器IP、主機名訪問。 info、health爲默認開放,metrics默認不開放安全
ureka服務端充當了重要的角色,全部Eureka客戶端都將本身提供的服務註冊到Eureka服務端,而後供全部服務消費者使用。若是單節點的Eureka服務端宕機了,那麼全部服務都沒法正常的訪問,這必將是災難性的。爲了提升Eureka服務端的可用性,咱們通常會對其集羣部署,即同時部署多個Eureka服務端,而且能夠相互間同步服務。 服務器
在搭建Eureka服務端的時候咱們曾把下面兩個配置給關閉了網絡
eureka.client.register-with-eureka=false eureka.client.fetch-registry=false
實際上在Eureka集羣模式中,開啓這兩個參數可讓當前Eureka服務端將本身也做爲服務註冊到別的Eureka服務端,而且從別的Eureka服務端獲取服務進行同步。因此這裏咱們將這兩個參數置爲true(默認就是true),下面開始搭建Eureka服務端集羣,爲了簡單起見這裏只搭建兩個節點的Eureka服務端集羣。
兩個applications.properties配置以下
server.port=8080 spring.application.name=Eureka-Server # 指定了Eureka服務端的IP eureka.instance.hostname=localhost eureka.instance.statusPageUrl=http://${eureka.instance.hostname}:${server.port}/info eureka.instance.healthCheckUrl=http://${eureka.instance.hostname}:${server.port}/health eureka.instance.homePageUrl=http://${eureka.instance.hostname}/ # 表示是否將服務註冊到Eureka服務端,因爲自身就是Eureka服務端,因此設置爲false # eureka.client.register-with-eureka=false # 表示是否從Eureka服務端獲取服務信息,由於這裏只搭建了一個Eureka服務端,並不須要從別的Eureka服務端同步服務信息,因此這裏設置爲false # eureka.client.fetch-registry=false # 指定Eureka服務端的地址,默認值爲http://localhost:8761/eureka 指定Eureka服務端的地址爲另一個Eureka服務端的地址8081 eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8081/eureka/ # 用於定義服務續約任務的調用間隔時間,默認30秒 eureka.client.serviceUrl.registry-fetch-interval-seconds=5 # 關閉保護模式 eureka.server.enable-self-preservation=false
server.port=8081 spring.application.name=Eureka-Server # 指定了Eureka服務端的IP eureka.instance.hostname=localhost eureka.instance.statusPageUrl=http://${eureka.instance.hostname}:${server.port}/info eureka.instance.healthCheckUrl=http://${eureka.instance.hostname}:${server.port}/health eureka.instance.homePageUrl=http://${eureka.instance.hostname}/ # 表示是否將服務註冊到Eureka服務端,因爲自身就是Eureka服務端,因此設置爲false # eureka.client.register-with-eureka=false # 表示是否從Eureka服務端獲取服務信息,由於這裏只搭建了一個Eureka服務端,並不須要從別的Eureka服務端同步服務信息,因此這裏設置爲false # eureka.client.fetch-registry=false # 指定Eureka服務端的地址,默認值爲http://localhost:8761/eureka 指定Eureka服務端的地址爲另一個Eureka服務端的地址8080 eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8080/eureka/ # 用於定義服務續約任務的調用間隔時間,默認30秒 eureka.client.serviceUrl.registry-fetch-interval-seconds=5 # 關閉保護模式 eureka.server.enable-self-preservation=false
Eureka客戶端便是服務提供者,也是服務消費者,即自身的接口可能被別的服務訪問,同時也可能調用別的服務接口
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</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-web</artifactId> </dependency> </dependencies> <!-- SpringCloud依賴,起到管理版本的做用 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR9</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
@EnableDiscoveryClient
註解用於發現服務和註冊服務,並配置一個RestTemplate Bean
,而後加上@LoadBalanced
註解來開啓負載均衡@SpringBootApplication @EnableDiscoveryClient public class SpringCloudConsumerApplication { @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(SpringCloudConsumerApplication.class, args); } }
@RestController public class TestController { @Autowired private RestTemplate restTemplate; /** * 注入了RestTemplate,getInfo中使用RestTemplate對象均衡的去獲取服務並消費。 * 能夠看到咱們使用服務名稱(Server-Provider)去獲取服務的,而不是使用傳統的IP加端口的形式。 * 這就體現了使用Eureka去獲取服務的好處,咱們只要保證這個服務名稱不變便可,IP和端口再也不是咱們關心的點 * * @return */ @GetMapping("/info") public String getInfo() { return this.restTemplate.getForEntity("http://Server-Provider/hello", String.class).getBody(); } }
# 指定了服務的端口爲8083 server.port=8083 # 指定服務名稱爲Server-Consumer,後續服務消費者要獲取上面TestController中接口的時候會用到這個服務名 spring.application.name=Server-Consumer # 雖然這兩個配置的默認值就是true,但這裏仍是顯式配置下,使Eureka客戶端的功能更爲直觀(即向服務端註冊服務並定時從服務端獲取服務緩存到本地) eureka.client.register-with-eureka=true eureka.client.fetch-registry=true # 指定Eureka服務端的地址,這裏爲上面定義的Eureka服務端地址 eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/,http://localhost:8081/eureka/ # 訪問路徑能夠顯示IP地址 eureka.instance.prefer-ip-address=true
出於安全的考慮,咱們可能會對Eureka服務端添加用戶認證的功能。咱們在Eureka-Server引入Spring-Security依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
而後在application.yml中配置用戶名和密碼
spring.security.user.name=admin spring.security.user.password=123456
Eureka服務端配置了密碼以後,全部eureka.client.serviceUrl.defaultZone
的配置也必須配置上用戶名和密碼,格式爲:eureka.client.serviceUrl.defaultZone=http://${userName}:${password}@${hosetname}:${port}/eureka/
,如:
eureka.client.serviceUrl.defaultZone=http://admin:123456@${eureka.instance.hostname}:8080/eureka/
從新打包並部署後,訪問http://localhost:8080/,頁面將彈出驗證窗口,輸入用戶名和密碼後便可訪問
配置 | 含義 | 默認值 |
---|---|---|
eureka.client.enabled | 是否啓用Eureka Client | true |
eureka.client.register-with-eureka | 表示是否將本身註冊到Eureka Server | true |
eureka.client.fetch-registry | 表示是否從Eureka Server獲取註冊的服務信息 | true |
eureka.client.serviceUrl.defaultZone | 配置Eureka Server地址,用於註冊服務和獲取服務 | http://localhost:8761/eureka |
eureka.client.registry-fetch-interval-seconds | 默認值爲30秒,即每30秒去Eureka Server上獲取服務並緩存 | 30 |
eureka.instance.lease-renewal-interval-in-seconds | 向Eureka Server發送心跳的間隔時間,單位爲秒,用於服務續約 | 30 |
eureka.instance.lease-expiration-duration-in-seconds | 定義服務失效時間,即Eureka Server檢測到Eureka Client木有心跳後(客戶端意外下線)多少秒將其剔除 | 90 |
eureka.server.enable-self-preservation | 用於開啓Eureka Server自我保護功能 | true |
eureka.client.instance-info-replication-interval-seconds | 更新實例信息的變化到Eureka服務端的間隔時間,單位爲秒 | 30 |
eureka.client.eureka-service-url-poll-interval-seconds | 輪詢Eureka服務端地址更改的間隔時間,單位爲秒。 | 300 |
eureka.instance.prefer-ip-address | 表示使用IP進行配置爲不是域名 | false |
eureka.client.healthcheck.enabled | 默認Erueka Server是經過心跳來檢測Eureka Client的健康情況的,經過置爲true改變Eeureka Server對客戶端健康檢測的方式,改用Actuator的/health端點來檢測。 | false |
Eureka還有許多別的配置,具體能夠參考EurekaClientConfigBean
,EurekaServerConfigBean
和EurekaInstanceConfigBean
配置類的源碼。
[1] Spring Cloud Netflix: https://cloud.spring.io/spring-cloud-netflix/reference/html/#service-discovery-eureka-clients