服務可用性


先前在談到組態伺服器時,有沒有想過,如果組態伺服器掛了的話怎麼辦?組態伺服器也是個服務,既然已經能夠透過 Spring Cloud 來實現服務註冊、發現,那就來將組態服務也掛到服務註冊伺服器上好了,步驟上一樣地,在 build.gradle 中加入客戶端相依:

implementation('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client') 

然後在 bootstrap.properties 加上服務註冊伺服器的位址等資訊,若不需要取得註冊表的話,可以將 eureka.client.fetchRegistry 設為 false

...略
spring.application.name=configsvr
eureka.client.fetchRegistry=false
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/

需要組態的客戶端,若要從服務註冊伺服器取得組態資訊,就不是使用 spring.cloud.config.uri 了,而是要將 spring.cloud.config.discovery.enabled 設為 true,並使用 spring.cloud.config.discovery.serviceId 指定服務 ID:

spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=configsvr

現在問題又來了,現在服務全掛到服務註冊伺服器上了,那麼服務註冊伺服器掛了的話怎麼辦?方式之一,啟動多個服務註冊伺服器,然後要註冊的服務,設定多個服務註冊伺服器,將服務同時註冊上去,查找服務的客戶端也可以設定多個服務註冊伺服器:

eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/,http://localhost:8762/eureka/

方式之二是,服務註冊伺服器可以把註冊表複製給另一台服務註冊伺服器,例如:

server.port=8761
eureka.instance.hostname=eurka-server
eureka.server.waitTimeInMsWhenSyncEmpty=0
eureka.client.serviceUrl.defaultZone=http://localhost:8762/eureka/

這麼一來,在 8761 這位置註冊的服務,伺服器會複製註冊表給 8762 這個位置的伺服器,不過目前在 8762 註冊的服務,就不會複製給 8761,若 8762 的服務也要複製一份給 8761,也可以設定:

server.port=8762
eureka.instance.hostname=eurka-server
eureka.server.waitTimeInMsWhenSyncEmpty=0
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/

不過這樣無論先啟動哪一台,都會發生找不到對方的錯誤,然而伺服器會正常啟動,後續也會複製註冊表。

雖然查詢到的文件經常都是以互相複製註冊表來示範,不過我想,要採用哪種群集設定,應該是視需求而定。

根據查詢到的一些資料,在本機上測試這類 Eureka 群集設定時,各台服務器的主機名稱不能相同,然而,就目前我測試的這個時間點來說,似乎沒這個必要了,然而,根據那些資料說膽,如果必須設定不同的主機名稱對照,在 Windows 中可以修改 C:\WINDOWS\system32\drivers\etc\hosts 文件,例如加入:

127.0.0.1   eurka-server1
127.0.0.1   eurka-server2

然後,各服務註冊伺服器設定為:

server.port=8761
eureka.instance.hostname=eurka-server1
eureka.server.waitTimeInMsWhenSyncEmpty=0
eureka.client.serviceUrl.defaultZone=http://eurka-server2:8762/eureka/