TIPS
This article is based on Spring Cloud Hoxton, supporting all versions of Spring Cloud in theory.
This article explores how to customize the InstanceId registered with Consul for microservices.
Consul uses InstanceId as its unique identity, while Spring Cloud Consul defaults to InstanceId of ${spring.application.name}-${server.port}.
The problem with this is that even if there are multiple instances of a microservice, as long as the ports are the same, only one data will remain on Consul!To solve this problem, you only need to have different InstanceId s for different instances.
Mode 1: Stitching random values
Add Configuration:
spring: cloud: consul: discovery: instance-id: ${spring.application.name}-${server.port}-${random.long}
So are some articles on the market today.However, in some scenarios there is still a minor problem.
For example, suppose a microservice instance crashes and then within a short period of time (Consul hasn't had time to delete this instance); a restart of the application results in two pieces of data on Consul, but it actually represents one instance (although after a while, Consul deletes unused instances, two pieces of data still appear bizarre over time).
TIPS
${random.long}
yes Spring Boot With its own Extended Configuration, there are many positions to use.The documentation is detailed https://docs.spring.io/spring-boot/docs/2.2.0.M5/reference/html/spring-boot-features.html#boot-features-external-config-random-values
Mode 2: Unique identification of stitching machine
Talking about this, smart classmates must think that a reasonable instanceid should meet the following two needs:
- Different instanceid s;
- The instanceid should be the same if the same instance is started multiple times.
To fulfill these two demands, simply add the unique identifier of the machine on the instanceid to OK, such as IP or hostname.
spring: cloud: consul: discovery: instance-id: ${spring.application.name}-${server.port}-${spring.cloud.client.hostname}
Or:
spring: cloud: consul: discovery: instance-id: ${spring.application.name}-${server.port}-${spring.cloud.client.ip-address}
TIPS
Here, ${spring.cloud.client.hostname} and ${spring.cloud.client.ip-address} make use of the Spring Boot configuration file to read environment variables.
Your application can view all environment variables through/actuator/env by integrating Spring Boot Actuator!Key values for environment variables can be written to the configuration file.
Mode 3: Code extension
If the above two methods still don't meet your needs, you can also extend them by writing code.
Code:
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()); } }
To configure:
@Configuration public class XXXConfiguration { @Bean public 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
- This is a more flexible way to play as you like.You can stitch mac addresses or anything else on InstanceId...However, just to customize a unique label, it's a bit expensive to play with, I suggest: If you don't have to work hard, you can toss around.
- This is how my personal project, Spring Cloud Wii (now Spring Cloud Alibaba Sidecar), customizes InstanceId.But Wii does this because Wii itself extends WiiConsulAutoRegistration and customizes InstanceId just by hand.The code is interesting to see here: https://github.com/eacdy/spring-cloud-wii/blob/master/spring-cloud-wii/src/main/java/com/itmuch/wii/consul/WiiConsulAutoRegistration.java
Future...
If this Pull Request is merged in the future, you won't have to worry about it...See: https://github.com/spring-cloud/spring-cloud-consul/pull/570
Beginning of this article
Use Consul to implement service discovery: instance-id customization