微服務應用中,生產環境一般都需要保障服務註冊中心的高可用!高可用也分好幾個等級,例如:同資料中心(可用Zone區)高可用——》同地域(Region)跨資料中心(可用Zone區)高可用——》全國跨地域(Region)跨資料中心(可用Zone區)高可用——全球跨地域(Region)跨資料中心(可用Zone區)高可用,常規應用基本上中間兩種就能滿足了!當然也會有國際型應用要進行全球部署。不同部署要求,如果是自己搭建部署環境,那麼伺服器的選購就要做好規劃。下面的截圖是阿里雲ECS的選購介面,切它出來不是為了打廣告,是借用它的資料中心分佈來說明本文的主角Eureka的高可用叢集部署(我們這裡演示Eureka的 同地域(Region)跨資料中心(可用Zone區)高可用 部署;全國版也是類似的,只是將全國範圍看成一個region,再在華北、華東、華南等各選一個zone,然後每個zone內部再做多一層 同資料中心(可用Zone區)高可用 部署即可,全國版需要考慮成本和遠距離服務註冊列表資料同步延遲的問題!),截圖可以放大來看:
從阿里雲的伺服器選購介面我們可以看到:有點實力的伺服器供應商一般都會從全球範圍內建設資料中心(機房)。但打包這些伺服器供使用者選擇購買時,使用兩級標籤就能唯一確定伺服器的位置——地域(region)和可用區(zone),這個分配標準是與國際接軌的!
我們在Spring官網Eureka主題下高可用一節也看到了region和zone的概念,另外,在Eureka的Github倉庫Eureka架構圖上也看到區(zone)的概念,為了防止連線失效,我把相關內容截圖過來了:
Eureka的高可用部署架構圖官方已經給出來了,而且跟阿里雲上可用區(zone)的劃分是一樣的,那麼該怎麼來配置和使用呢?接下來我們就來實操一下!
首先用IDEA建立好Eureka工程,我這裡採用Maven多模組(module)的結構,將Eureka Server和Eureka Client端放在一個主工程下了:
這裡要用到IDEA多例項執行的功能來模擬多區(zone)部署的情況(用埠的不同來模擬分割槽),該功能預設是關閉的,按下面截圖方法開啟它:
然後我們在相應應用的主配置檔案application.yml裡修改 spring:profiles:active: <目標配置> 並啟動應用就可以了,每個目標配置裡的埠不一樣,用於模擬多機器的情況(真實環境是埠一樣,IP不一樣),先看一下效果截圖,然後我會在後面貼出所有配置檔案,配置檔案裡會有詳細的說明,就不在正文說怎麼配置了:
以下是重點內容,Eureka Server端的配置檔案:
#Eureka Server的application.yml內容 spring: application: name: EurekaServer profiles:
#多例項啟動就改下這裡(分別切換為eureka1、eureka2、eureka3) active: eureka1
#Eureka Server的application-eureka1.yml內容 server: port: 8761 #Eureka專用配置Begin eureka: instance: metadata-map: #宣告自己所屬的區 zone: zoneA #自己是zoneA區的Eureka Server節點(取個容易識別的hostname) hostname: eureka1.zonea.cn-shenzhen #自己的IP,多塊網路卡時最好指定,多網路卡自動繫結很容易出錯(例如裝了VMWare虛擬機器的情況) ip-address: 127.0.0.1 #優先使用IP prefer-ip-address: true client: #宣告自己所屬的地區Region region: cn-shenzhen #列明可用的區Zone(注意順序,優先將自己的區排前面) availability-zones: cn-shenzhen: zoneA,zoneB,zoneC service-url: #設定可用區Zone地址 zoneA: http://eureka1.zonea.cn-shenzhen:8761/eureka/ zoneB: http://eureka1.zoneb.cn-shenzhen:8762/eureka/ zoneC: http://eureka1.zonec.cn-shenzhen:8763/eureka/ #顯示設定優先考慮請求同區Zone註冊中心 prefer-same-zone-eureka: true #自己作為服務端的客戶端不需要像普通客戶端一樣去fetch服務列表,也不需要向任何服務端註冊自己 fetch-registry: false register-with-eureka: false
#Eureka Server的application-eureka2.yml內容 server: port: 8762 #Eureka專用配置Begin eureka: instance: metadata-map: #宣告自己所屬的區 zone: zoneB #自己是zoneB區的Eureka Server節點(取個容易識別的hostname) hostname: eureka1.zoneb.cn-shenzhen #自己的IP,多塊網路卡時最好指定,多網路卡自動繫結很容易出錯(例如裝了VMWare虛擬機器的情況) ip-address: 127.0.0.1 #優先使用IP prefer-ip-address: true client: #宣告自己所屬的地區Region region: cn-shenzhen #列明可用的區Zone(注意順序,優先將自己的區排前面) availability-zones: cn-shenzhen: zoneB,zoneA,zoneC service-url: #設定可用區Zone地址 zoneA: http://eureka1.zonea.cn-shenzhen:8761/eureka/ zoneB: http://eureka1.zoneb.cn-shenzhen:8762/eureka/ zoneC: http://eureka1.zonec.cn-shenzhen:8763/eureka/ #顯示設定優先考慮請求同區Zone註冊中心 prefer-same-zone-eureka: true #自己作為服務端的客戶端不需要像普通客戶端一樣去fetch服務列表,也不需要向任何服務端註冊自己 fetch-registry: false register-with-eureka: false
#Eureka Server的application-eureka3.yml內容 server: port: 8763 #Eureka專用配置Begin eureka: instance: metadata-map: #宣告自己所屬的區 zone: zoneC #自己是zoneC區的Eureka Server節點(取個容易識別的hostname) hostname: eureka1.zonec.cn-shenzhen #自己的IP,多塊網路卡時最好指定,多網路卡自動繫結很容易出錯(例如裝了VMWare虛擬機器的情況) ip-address: 127.0.0.1 #優先使用IP prefer-ip-address: true client: #宣告自己所屬的地區Region region: cn-shenzhen #列明可用的區Zone(注意順序,優先將自己的區排前面) availability-zones: cn-shenzhen: zoneC,zoneA,zoneB service-url: #設定可用區Zone地址 zoneA: http://eureka1.zonea.cn-shenzhen:8761/eureka/ zoneB: http://eureka1.zoneb.cn-shenzhen:8762/eureka/ zoneC: http://eureka1.zonec.cn-shenzhen:8763/eureka/ #顯示設定優先考慮請求同區Zone註冊中心 prefer-same-zone-eureka: true #自己作為服務端的客戶端不需要像普通客戶端一樣去fetch服務列表,也不需要向任何服務端註冊自己 fetch-registry: false register-with-eureka: false
以下是重點內容,Eureka Client端的配置檔案:
#Eureka Client的application.yml內容 spring: application: name: EurekaClient profiles:
#多例項啟動就改下這裡(分別切換為clientA、client2、client3) active: clientA main: banner-mode: console #配置SpringBoot Actuator,開啟服務資訊和健康彙報介面(方便從Eureka Server介面直接點進相應服務檢視服務資訊) management: endpoints: web: exposure: include: "*" endpoint: health: show-details: always shutdown: enabled: true
#Eureka Client的application-clientA.yml內容
server:
port: 8081
#Eureka專用配置Begin
eureka:
instance:
metadata-map:
#宣告自己所屬的區Zone
zone: zoneA
client:
#宣告自己所屬的地區Region
region: cn-shenzhen
#列明可用的區Zone(注意順序)
availability-zones:
cn-shenzhen: zoneA,zoneB,zoneC
service-url:
#設定可用區Zone地址
zoneA: http://eureka1.zonea.cn-shenzhen:8761/eureka/
zoneB: http://eureka1.zoneb.cn-shenzhen:8762/eureka/
zoneC: http://eureka1.zonec.cn-shenzhen:8763/eureka/
#顯示設定優先考慮請求同區Zone註冊中心
prefer-same-zone-eureka: true
#Eureka Client的application-clientB.yml內容
server:
port: 8082
#Eureka專用配置Begin
eureka:
instance:
metadata-map:
#宣告自己所屬的區Zone
zone: zoneB
client:
#宣告自己所屬的地區Region
region: cn-shenzhen
#列明可用的區Zone(注意順序)
availability-zones:
cn-shenzhen: zoneB,zoneA,zoneC
service-url:
#設定可用區Zone地址
zoneA: http://eureka1.zonea.cn-shenzhen:8761/eureka/
zoneB: http://eureka1.zoneb.cn-shenzhen:8762/eureka/
zoneC: http://eureka1.zonec.cn-shenzhen:8763/eureka/
#顯示設定優先考慮請求同區Zone註冊中心
prefer-same-zone-eureka: true
#Eureka Client的application-clientC.yml內容
server:
port: 8083
#Eureka專用配置Begin
eureka:
instance:
metadata-map:
#宣告自己所屬的區Zone
zone: zoneC
client:
#宣告自己所屬的地區Region
region: cn-shenzhen
#列明可用的區Zone(注意順序)
availability-zones:
cn-shenzhen: zoneC,zoneA,zoneB
service-url:
#設定可用區Zone地址
zoneA: http://eureka1.zonea.cn-shenzhen:8761/eureka/
zoneB: http://eureka1.zoneb.cn-shenzhen:8762/eureka/
zoneC: http://eureka1.zonec.cn-shenzhen:8763/eureka/
#顯示設定優先考慮請求同區Zone註冊中心
prefer-same-zone-eureka: true
客戶端配置 availability-zones 時一定要注意順序,要優先將自己所屬的區(zone)排在前面,這樣Eureka Client在發起續約(Renew)請求時,從所有可用區(zone)裡第一個拿到的就是自己所在區(zone)的目標Eureka Server,否則就變成在其他伺服器上續約,會導至自己區(zone)裡的Eureka Server的Renews (last min)值永遠達不到要求而報出以下錯誤(這個錯誤是由於前來本Eureka Server續約的服務低於指定的自我保證閾值(預設85%)了,觸發了Eureka自我保護機制,Eureka Server不再剔除服務登錄檔裡的條目):
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常用部署架構圖:
最後一張是針對官方的改進版,自己想一下這幾張圖服務端和客戶端要怎麼配!!!