Eureka 目前的狀態:Eureka 目前 1.x 版本還在更新,可是應該不會更新新的功能了,只是對現有功能進行維護,升級併兼容所需的依賴。 Eureka 2.x 已經胎死腹中了。可是,這也不表明 Eureka 就是不能用了。若是你須要一個簡便易於部署的註冊中心,Eureka 仍是一個很好的選擇。雲服務環境中,基本上全部實例地址和微服務名稱都在不斷變化,也並不太須要 Eureka 所缺乏的持久化特性。當你的集羣屬於中小規模的時候(節點小於 1000 個), Eureka 依然是一個不錯的選擇。當你的集羣很大的時候,Eureka 的同步機制可能就限制了他的表現。java
Eureka 的設計比較小巧,沒有複雜的同步機制,也沒有複雜的持久化機制,集羣關係只是簡單的將收到的客戶端請求轉發到集羣內的其餘 Eureka 實例。Eureka 自己也只有註冊中心的功能,不像其餘種類的註冊中心那樣,將註冊中心和配置中心合在一塊兒,例如 Consul 和 nacos。node
Eureka 的交互流程以下:git
首先,Service A 經過 Eureka Client 發送註冊請求(Register)到同一可用區的 Eureka Server 1。以後經過發送心跳請求(Renew)到這個 Eureka Server 1. Eureka Server 1 收到這些請求的時候,會處理這些請求並將這些請求轉發到其餘的集羣內的 Eureka Server 2 和 Eureka Server 3. Eureka Server 2 和 Eureka Server 3 不會再轉發收到的 Eureka Server 1 轉發過來的請求。而後,Service B 還有 Service C 經過 Eureka 獲取到了 Service A 的位置,最後調用了 Service A。github
對於本地沒有查詢到的微服務,Eureka Server 還會從遠程 Region 的 Eureka Server 去獲取,例如這裏對於 Service D,本地沒有查到,Eureka Server 會返回遠程 Region 的 Service D 的實例。因爲本地有 Service A,因此確定不會返回遠程 Region 的 Service A 的實例。而且,本地是定時拉取的遠程 Region 的 Service 列表,並非每次查詢的時候現查詢的。spring
通常的,微服務之間的互相調用,並不通過 Eureka,也不會涉及到 Eureka 客戶端了,而是經過負載均衡器調用,這個咱們後面就會提到。apache
這裏咱們忽略全部的 AWS 相關的術語以及配置還有相關邏輯處理。緩存
Eureka 中的術語:服務器
spring.application.name
指定的服務名稱。eureka: instance: #通常不用咱們本身設置,EurekaInstanceConfigBean 的構造器會經過 InetUtils 獲取 ip 地址 #ip-address: #通常不用咱們本身設置,EurekaInstanceConfigBean 的構造器會經過 InetUtils 獲取 hostname #hostname: #註冊到 eureka 上面供其餘實例訪問的地址使用 ip 進行註冊,其餘實例會經過 ip 進行訪問 prefer-ip-address: true #不用設置 non-secure-port,自動使用 server.port 做爲 non-secure-port #non-secure-port: #若是 secure-port-enabled 是 true,則會自動使用 server.port 做爲 secure-port;咱們通常內部調用不用 ssl,因此不須要配置 secure-port #secure-port: #默認是啓用 non-secure-port 的 non-secure-port-enabled: true #默認是不啓用 secure-port 的,咱們通常內部調用不用 ssl secure-port-enabled: false #個性化的實例id,包括 ip:微服務名稱:端口 instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} # app名稱,不填寫在 Spring-cloud-netflix 體系下默認就是 spring.application.name appname: ${spring.application.name} #app組名稱歸類用的,目前也沒什麼用 app-group-name: common #實例命名空間,目前也沒什麼用 namespace: public
eureka: instance: # 健康檢查地址,默認是 /actuator/health health-check-url-path: /actuator/health # 實例狀態地址,默認是 /actuator/info status-page-url-path: /actuator/info # 首頁地址,默認是 / home-page-url-path: /
eureka: instance: # 服務過時時間配置,超過這個時間沒有接收到心跳EurekaServer就會將這個實例剔除 # 注意,EurekaServer必定要設置eureka.server.eviction-interval-timer-in-ms不然這個配置無效 # 這個配置通常爲服務刷新時間配置的三倍 # 默認90s lease-expiration-duration-in-seconds: 15 #服務刷新時間配置,每隔這個時間會主動心跳一次 #默認30s lease-renewal-interval-in-seconds: 5 registry: #請參考 wait-time-in-ms-when-sync-empty 配置說明 default-open-for-traffic-count: 1 #初始指望發送心跳請求的實例個數,默認爲1,在有新實例註冊的時候,會 +1,有註銷的時候會 -1,初始默認爲 1 通常由於本身也註冊到 eureka 上 expected-number-of-clients-sending-renews: 1 #實例註冊後是否馬上開始服務,默認爲 false,通常註冊後還須要作一些操做,因此註冊實例的狀態是 STARTING。後面改變狀態後會更新爲 UP instance-enabled-onit: false
eureka: instance: #元數據map,咱們能夠本身使用,放一些個性化的元數據,目前只有 configPath 和 zone 比較有用。 configPath 是使用 spring-cloud-config 的時候會設置 metadata-map: # spring cloud 體系中,可用區的配置放入元數據中,key 爲 zone zone: zone1
Eureka 客戶端配置:網絡
eureka: instance: # 可用區列表,key 爲 region,value 爲 zone availability-zones: region1: zone1, zone2 region2: zone3 # 所在區域,經過這個讀取 availability-zones 獲取 zone,而後經過 zone 讀取 service-url 獲取對應的 eureka url # 這裏的邏輯對應的類是 ConfigClusterResolver 和 ZoneAffinityClusterResolver region: region1 # key 爲 zone,value 爲 eureka 連接,以逗號分隔 service-url: # 默認eureka集羣,這裏必須是defaultZone,不能用-替換大寫,與其餘的配置不同,由於實在EurekaClientConfigBean裏面寫死的 defaultZone: http://127.0.0.1:8211/eureka/ zone1: http://127.0.0.1:8212/eureka/ zone2: http://127.0.0.1:8213/eureka/ zone3: http://127.0.0.1:8214/eureka/ # 若是上面 eureka server 地址相關配置更新了,多久以後會從新讀取感知到 eureka-service-url-poll-interval-seconds: 300 # 是否使用 dns 獲取,若是指定了則經過下面的 dns 配置獲取,而不是上面的 service-url use-dns-for-fetching-service-urls: false # dns 配置 # eureka-server-d-n-s-name: # dns 配置的 eureka server 的 port # eureka-server-port: # dns 配置的 eureka server 的 port 後面的 uri 前綴 context # eureka-server-u-r-l-context: # 若是設置爲 true,則同一個 zone 下的 eureka 會跑到前面優先訪問。默認爲 true prefer-same-zone-eureka: true
拉取服務實例信息相關配置:app
eureka: instance: # 是否從 eureka 上面拉取實例 fetch-registry: true # 若是隻想獲取一個特定 virtual host name 的實例列表,就配置 registry-refresh-single-vip-address #registry-refresh-single-vip-address: # 客戶端請求頭指定服務端返回的實例信息是壓縮的信息仍是完整信息,默認是完整信息 # full, compact client-data-accept: full # eureka client 刷新本地緩存時間 # 默認30s registry-fetch-interval-seconds: 5 # eureka client 刷新本地緩存(定時拉取 eureka 實例列表)線程池大小,默認爲 2 cache-refresh-executor-thread-pool-size: 2 # eureka client 刷新本地緩存(定時拉取 eureka 實例列表)線程池任務最大延遲時間,這個配置是定時拉取任務延遲(registry-fetch-interval-seconds)的倍數,默認 10 倍 cache-refresh-executor-exponential-back-off-bound: 10 # 是否禁用增量拉取,若是網絡條件很差,能夠禁用,每次都會拉取全量 disable-delta: false # 只保留狀態爲 UP 的實例,默認爲 true filter-only-up-instances: true #能夠指定也從某些 region 拉取服務實例 #fetch-remote-regions-registry: # 是否打日誌記錄每次拉取實例信息與當前緩存內的實例信息變化 log-delta-diff: true #在spring cloud 環境中,DiscoveryClient 用的其實都是 CompositeDiscoveryClient,這個 CompositeDiscoveryClient 邏輯其實就是多個 DiscoveryClient 共存,先訪問一個,沒找到就經過下一個尋找 #這個order決定了順序,默認爲 0 order: 0
eureka: instance: # 是否將本身註冊到 eureka 上面 register-with-eureka: true # 是否在初始化的時候就註冊到 eureka,通常設置爲 false,由於實例還不能正常提供服務 should-enforce-registration-at-init: false # 是否在關閉的時候註銷實例,默認爲 true should-unregister-on-shutdown: true # 是否對於實例狀態改變動新進行限流,默認爲 true on-demand-update-status-change: true # 實例信息同定時同步到 Eureka Server 的間隔時間。每隔這麼長時間,檢查實例信息(即eureka.instance配置信息)是否發生變化,若是發生變化,則同步到 Eureka Server,默認 30s # 主要檢查兩類信息,分別是服務地址相關信息,以及服務過時時間與刷新時間配置信息 instance-info-replication-interval-seconds: 30 # 實例信息同定時同步到 Eureka Server 的初始延遲時間,默認 40s initial-instance-info-replication-interval-seconds: 40
eureka: instance: # 代理相關配置 # proxy-host: # proxy-port: # proxy-user-name: # proxy-password: # 是否對於發往 Eureka Server 的 http 請求啓用 gzip,目前已通過期了,只要 Eureka Server 啓用了 gzip,請求就是 gzip 壓縮的 g-zip-content: true # httpclient 的連接超時,默認 5s eureka-server-connect-timeout-seconds: 5 # httpclient 的讀取超時,默認 5s eureka-server-read-timeout-seconds: 8 # httpclient 的空閒鏈接超時,默認 30s eureka-connection-idle-timeout-seconds: 30 # httpclient 的總鏈接數量,默認 200 eureka-server-total-connections: 200 # httpclient 的每一個 host 的鏈接數量 eureka-server-total-connections-per-host: 50 # tls 相關配置,默認沒有啓用 # tls: # enabled: false # key-password: # key-store: # key-store-password: # key-store-type: # trust-store: # trust-store-password: # trust-store-type:
eureka: server: #主動檢查服務實例是否失效的任務執行間隔,默認是 60s eviction-interval-timer-in-ms: 3000 #這個配置在兩個地方被使用: #若是啓用用了自我保護,則會 renewal-threshold-update-interval-ms 指定的時間內,收到的心跳請求個數是否小於實例個數乘以這個 renewal-percent-threshold #定時任務檢查過時實例,每次最多過時 1 - renewal-percent-threshold 這麼多比例的實例 renewal-percent-threshold: 0.85
eureka: server: #注意,最好全部的客戶端實例配置的心跳時間相關的配置,是相同的。這樣使用自我保護的特性最準確。 #關閉自我保護 #咱們這裏不使用自我保護,由於: #自我保護主要針對集羣中網絡出現問題,致使有不少實例沒法發送心跳致使不少實例狀態異常,可是實際實例還在正常工做的狀況,不要讓這些實例不參與負載均衡 #啓用自我保護的狀況下,就會中止對於實例的過時 #可是,若是出現這種狀況,其實也表明不少實例沒法讀取註冊中心了。 #而且還有一種狀況就是,Eureka 重啓。雖然不常見,可是對於鏡像中其餘的組件更新咱們仍是很頻繁的 #我傾向於從客戶端對於實例緩存機制來解決這個問題,若是返回實例列表爲空,則使用上次的實例列表進行負載均衡,這樣既能解決 Eureka 重啓的狀況,又能處理一些 Eureka 網絡隔離的狀況 #自我保護模式基於每分鐘須要收到 renew (實例心跳)請求個數,若是啓用了自我保護模式,只有上一分鐘接收到的 renew 個數,大於這個值,實例過時纔會被註銷 enable-self-preservation: false # 每分鐘須要收到 renew (實例心跳)請求個數是須要動態刷新的,這個刷新間隔就是 renewal-threshold-update-interval-ms #更新流程大概是:計算當前一共有多少實例,若是大於以前指望的實例量 * renewal-percent-threshold(或者沒開啓自我保護模式),則更新指望的實例數量爲當前一共有多少實例 #以後根據指望的實例數量,計算指望須要收到的實例心跳請求個數 = 指望的實例數量 * (60 / expected-client-renewal-interval-seconds) * renewal-percent-threshold #公式中 60 表明一分鐘,由於公式用到了 expected-client-renewal-interval-seconds,也就是實例平均心跳間隔,爲了使這個公式準確,最好每一個實例配置同樣的心跳時間 #默認 900000ms = 900s = 15min renewal-threshold-update-interval-ms: 900000 #上面提到的實例平均心跳間隔,或者說是指望的心跳間隔,爲了使這個公式準確,最好每一個實例配置同樣的心跳時間 #默認 30s expected-client-renewal-interval-seconds: 30 #這個配置在兩個地方被使用: #若是啓用用了自我保護,則會 renewal-threshold-update-interval-ms 指定的時間內,收到的心跳請求個數是否小於實例個數乘以這個 renewal-percent-threshold #定時任務檢查過時實例,每次最多過時 1 - renewal-percent-threshold 這麼多比例的實例 renewal-percent-threshold: 0.85
eureka: server: #Eureka Server 從配置中更新同一區域內的其餘 Eureka Server 實例列表間隔,默認10分鐘 peer-eureka-nodes-update-interval-ms: 600000 #啓動時從其餘 Eureka Server 同步服務實例信息的最大重試次數,直到實例個數不爲 0,默認爲 0,這樣其實就是不一樣步 registry-sync-retries: 0 #啓動時從其餘 Eureka Server 同步服務實例信息重試間隔 registry-sync-retry-wait-ms: 30000 #集羣內至少有多少個 UP 的 Eureka Server 實例數量,當前 Eureka Server 狀態爲 UP。默認 -1,也就是 Eureka Server 狀態不考慮 UP 的集羣內其餘 Eureka Server 數量。 min-available-instances-for-peer-replication: -1 #請求其餘實例任務的最大超時時間,默認 30 秒 max-time-for-replication: 30000 #用來處理同步任務的線程數量,有兩個線程池,一個處理批量同步任務,默認大小爲20 max-threads-for-peer-replication: 20 #另外一個處理非批量任務(若是沒用 AWS Autoscaling 對接相關特性則沒有啥用),默認大小爲20 max-threads-for-status-replication: 20 #處理批量任務的線程池隊列長度,默認爲 10000 max-elements-in-peer-replication-pool: 10000 #處理非批量任務的線程池隊列長度,默認爲 10000 max-elements-in-status-replication-pool: 10000 #Eureka Server 經過 httpclient 訪問其餘 Eureka Server 同步實例,httpclient 的鏈接超時,默認 200ms peer-node-connect-timeout-ms: 200 #httpclient 的讀取超時,默認 200ms,通常不用太長 peer-node-read-timeout-ms: 200 #httpclient 的最大總鏈接數量,默認 1000 peer-node-total-connections: 1000 #httpclient 的對於某一 host 最大總鏈接數量,默認 500 peer-node-total-connections-per-host: 500 #httpclient 的鏈接空閒保持時間,默認 30s peer-node-connection-idle-timeout-seconds: 30
eureka: server: #請求其餘 Region 的 httpclient 的鏈接超時,默認 1000ms remote-region-connect-timeout-ms: 1000 #請求其餘 Region 的 httpclient 的讀取超時,默認 1000ms remote-region-read-timeout-ms: 1000 #請求其餘 Region 的 httpclient 的最大總鏈接數量,默認 1000 remote-region-total-connections: 1000 #請求其餘 Region 的 httpclient 的對於某一 host 最大總鏈接數量,默認 500 remote-region-total-connections-per-host: 500 #請求其餘 Region 的 httpclient 的鏈接空閒保持時間,默認 30s remote-region-connection-idle-timeout-seconds: 30 #請求其餘 Region 的 http 請求是否開啓 gzip,對於其餘 Region 咱們認爲網絡鏈接是比較慢的,因此默認開啓壓縮 g-zip-content-from-remote-region: true # remote-region-urls-with-name: # region2eureka1: http://127:0:0:1:8212/eureka/ # region2eureka2: http://127:0:0:1:8213/eureka/ # remote-region-app-whitelist: #若是須要從其餘 Region 獲取實例信息,這個獲取間隔,默認爲 30s remote-region-registry-fetch-interval: 30 #若是須要從其餘 Region 獲取實例信息,這個任務的線程池,默認爲 20個 remote-region-fetch-thread-pool-size: 20
啓動一個 Eureka 註冊中心服務器很是簡單,咱們這裏使用的是 Spring Cloud 封裝好的啓動包。Eureka 1.x 的 Eureka Server 是純基於 servlet 的應用。爲了與 Spring Cloud 結合使用,須要粘合模塊,這就是 spring-cloud-netflix-eureka-server。在 spring-cloud-netflix-eureka-server 中,也有一個和 com.netflix.eureka.EurekaBootStrap
代碼很相似的啓動類,即 org.springframework.cloud.netflix.eureka.server.EurekaServerBootstrap
。在咱們啓動 EurekaServer 實例的時候,只用加入對於 spring-cloud-starter-eureka-server 的依賴便可。以後經過 @EnableEurekaServer 註解便可啓動一個 Eureka 服務器實例。
Eureka Server 的依賴:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>spring-cloud-iiford</artifactId> <groupId>com.github.hashjang</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>spring-cloud-iiford-eureka-server</artifactId> <dependencies> <dependency> <groupId>com.github.hashjang</groupId> <artifactId>spring-cloud-iiford-service-common</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-eureka-server</artifactId> </dependency> </dependencies> </project>
Eureka Server 的配置:
參考咱們上面的配置便可:application.yml
Eureka Server 的啓動類:EurekaServerApplication.java
package com.github.hashjang.iiford.eureka.server; 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); } }