使用Consul实现服务发现:instance-id自定义(3种方式)
本文探討如何自定義微服務(wù)注冊(cè)到Consul的InstanceId。
Consul把InstanceId作為唯一標(biāo)識(shí),而Spring Cloud Consul默認(rèn)的InstanceId是?${spring.application.name}-${server.port}?。
這樣導(dǎo)致的問(wèn)題是:某個(gè)微服務(wù)即使有多個(gè)實(shí)例,只要端口相同,那么Consul上依然只會(huì)保留1條數(shù)據(jù)!要想解決這個(gè)問(wèn)題,只需要讓不同實(shí)例,擁有不同的InstanceId即可。
方式1:拼接隨機(jī)值
添加配置:
spring:cloud:consul:discovery:instance-id: ${spring.application.name}-${server.port}-${random.long}目前市面上的一些文章也是這么玩的。但這樣做,在一些場(chǎng)景下還是有一點(diǎn)小問(wèn)題的。
舉個(gè)例子:假設(shè)某個(gè)微服務(wù)實(shí)例崩潰了,然后在很短的時(shí)間內(nèi)(Consul還沒(méi)來(lái)得及把這個(gè)實(shí)例刪除);應(yīng)用重啟了,就會(huì)導(dǎo)致Consul上出現(xiàn)兩條數(shù)據(jù),但其實(shí)代表的是一個(gè)實(shí)例(雖然過(guò)段時(shí)間后,Consul會(huì)把沒(méi)用的實(shí)例刪除,但在一段時(shí)間內(nèi)出現(xiàn)2條數(shù)據(jù)還是很詭異的)。
TIPS
${random.long}?是Spring Boot自帶的“擴(kuò)展配置”,還有很多的使用姿勢(shì)。文檔可詳見(jiàn) https://docs.spring.io/spring-boot/docs/2.2.0.M5/reference/html/spring-boot-features.html#boot-features-external-config-random-values
方式2:拼接機(jī)器唯一標(biāo)識(shí)
講到這里,聰明的同學(xué)一定會(huì)想到,一個(gè)合理的instanceid應(yīng)該滿足以下兩點(diǎn)需求:
-
不同實(shí)例的instanceid不同;
-
相同實(shí)例啟動(dòng)多次,instanceid應(yīng)該相同。
要想實(shí)現(xiàn)這兩點(diǎn)訴求,只要在instanceid上加上機(jī)器的唯一標(biāo)示就OK了,比如IP或者是主機(jī)名等等。
spring:cloud:consul:discovery:instance-id: ${spring.application.name}-${server.port}-${spring.cloud.client.hostname}或者:
spring:cloud:consul:discovery:instance-id: ${spring.application.name}-${server.port}-${spring.cloud.client.ip-address}TIPS
這里,${spring.cloud.client.hostname}?以及?${spring.cloud.client.ip-address}?,是利用了Spring Boot配置文件可以讀取環(huán)境變量的特點(diǎn)。
你的應(yīng)用只要集成Spring Boot Actuator?,就可以通過(guò)?/actuator/env?查看所有環(huán)境變量啦!環(huán)境變量的Key值,都可以寫(xiě)到配置文件中。
方式3:代碼擴(kuò)展
如果上面兩種方式依然滿足不了你的需求,那么你還可以通過(guò)寫(xiě)代碼的方式去擴(kuò)展。
代碼:
public class WiiConsulAutoRegistration extends ConsulAutoRegistration {public WiiConsulAutoRegistration(NewService service, AutoServiceRegistrationProperties autoServiceRegistrationProperties, ConsulDiscoveryProperties properties, ApplicationContext context, HeartbeatProperties heartbeatProperties, List<ConsulManagementRegistrationCustomizer> managementRegistrationCustomizers) {super(service, autoServiceRegistrationProperties, properties, context, heartbeatProperties, managementRegistrationCustomizers);}public static String getInstanceId(WiiProperties wiiProperties,Environment environment) {return String.format("%s-%s-%s",environment.getProperty("spring.application.name"),wiiProperties.getIp(),wiiProperties.getPort());} }配置:
@Configuration public class XXXConfiguration {@Beanpublic ConsulAutoRegistration consulRegistration(AutoServiceRegistrationProperties autoServiceRegistrationProperties,ConsulDiscoveryProperties properties,ApplicationContext applicationContext,ObjectProvider<List<ConsulRegistrationCustomizer>> registrationCustomizers,ObjectProvider<List<ConsulManagementRegistrationCustomizer>> managementRegistrationCustomizers,HeartbeatProperties heartbeatProperties) {return WiiConsulAutoRegistration.registration(autoServiceRegistrationProperties,properties, applicationContext, registrationCustomizers.getIfAvailable(),managementRegistrationCustomizers.getIfAvailable(), heartbeatProperties);} }TIPS
-
這種方式更加靈活,你想怎么玩就怎么玩。你可以在InstanceId上拼接mac地址或者其他什么玩意兒……不過(guò),只是為了定制個(gè)唯一標(biāo)示而已,這么玩成本有點(diǎn)高了,我建議:如果沒(méi)有不得已的苦衷,就甭折騰了。
-
我的個(gè)人項(xiàng)目?Spring Cloud Wii?(也就是現(xiàn)在的Spring Cloud Alibaba Sidecar)就是使用的這種方式自定義InstanceId的。但Wii之所以采用這種方式,是因?yàn)閃ii本身就要擴(kuò)展?WiiConsulAutoRegistration?,定制一下InstanceId只是順手而為。相關(guān)代碼在這里,有興趣可以看下:?https://github.com/eacdy/spring-cloud-wii/blob/master/spring-cloud-wii/src/main/java/com/itmuch/wii/consul/WiiConsulAutoRegistration.java
未來(lái)...
未來(lái)如果這個(gè)Pull Request被合并,就不用折騰了……詳見(jiàn):https://github.com/spring-cloud/spring-cloud-consul/pull/570
總結(jié)
以上是生活随笔為你收集整理的使用Consul实现服务发现:instance-id自定义(3种方式)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 我是一个内向的人,也是一个不善交际的人
- 下一篇: StringBuffer 和 Strin