Eureka has a delayed registration function, that is, it does not register to Eureka Server immediately after the service is successfully started, but delays registration for a period of time. The main purpose of this is because although the service is started successfully, there may be some frameworks or The code of the business is not initialized, which may cause an error in the call, so it is necessary to delay the registration.
However, it was found that it was not the case, it seemed that the delayed registration did not take effect, and the investigation was also started.
late registration
First of all, the function of delayed registration mainly depends on these two parameters, eureka.client.initial-instance-info-replication-interval-seconds
represents the time interval of the first initialized delayed registration, eureka.client.instance-info-replication-interval-seconds
represents the time interval of subsequent synchronous registration.
eureka.client.initial-instance-info-replication-interval-seconds=40 //默认40秒
eureka.client.instance-info-replication-interval-seconds=30 //默认30秒
Let's first look at how to delay registration from the source code, first look at the DiscoveryClient
of initScheduledTasks
, where a timed task for synchronous registration to Eureka Server is created.
Then call the start
method to create a timed task, and delay the execution for 40 seconds, which is the effect of delayed registration we achieved.
The default first registration, that is, the delayed registration time is 40 seconds, after which the registration information will be synchronized every 30 seconds.
However, even if we configure these two properties, it seems that it is useless. Next, we have to investigate why?
first question
I found that in InstanceInfoReplica
there is such a section that terminates the current thread pool task and directly calls the run method. I guess the failure is that the direct call causes the delayed task to not take effect, because the direct call of this method causes delayed registration at all. It doesn't work.
It seems that he has two calls, the first one is registerHealthCheck
, when there is this health check or something, it will call onDemandUpdate
.
After investigation, we found that as long as ---07d695caaf3f7ffd287d45d3c91f5388--- is configured, an instance of HealthCheckHandler
eureka.client.healthcheck.enabled=true
will be created. By default, it is false
, so it should not be for us. affected.
Here we need to specifically explain the role of eureka.client.healthcheck.enabled
. By default, Eureka determines the status of the application according to the heartbeat. If this property is configured as true
, it will be determined according to the Spring Boot Actuator. rather than a heartbeat.
For example, we can implement the HealthIndicator
interface and write our own Controller
to dynamically change the status of the service
@RestController
public class ControllerTest {
@Autowired
private HealthChecker healthChecker;
@RequestMapping("/change")
public String test(Boolean flag) {
healthChecker.setUp(new AtomicBoolean(flag));
return "success";
}
}
Implement HealthChecker
, so you will find that the status of Eureka Server will not become Down when starting and offline services. Only by manually changing the application status by calling the interface will the status of the Server change. You can test it yourself.
@Component
public class HealthChecker extends EurekaHealthIndicator implements HealthIndicator {
private AtomicBoolean up = new AtomicBoolean(true);
public HealthChecker(EurekaClient eurekaClient, EurekaInstanceConfig instanceConfig, EurekaClientConfig clientConfig) {
super(eurekaClient, instanceConfig, clientConfig);
}
@Override
public Health health() {
if(up.get()){
return Health.up().build();
}else{
return Health.down().build();
}
}
second question
We found the first problem and found that it was not the root cause of our problem, so we continued to investigate.
It is found that the second call is registered in DiscoveryClient
to monitor the state event change. If the state changes, it will also call onDemandUpdate, which affects the effect of delayed registration.
There is a configuration item onDemandUpdateStatusChange
, the default is true
, so he should be right.
Enter StatusChangeListener
and find a call.
It is an event notification triggered by the setInstanceStatus
method.
There are 6 calls here, check them one by one, find and find through the source code, and finally locate the place where the service starts automatic assembly, and modify the service status here to UP
, and then trigger the event notification to start start
method call register
method.
Continue to call and modify the application to go online UP
status.
From this, we know that as long as the service starts successfully, an event notification will be triggered, so this basically means that it will register with the Eureka Server immediately after the startup is successful, which will lead to the failure of the delayed registration, which can also be seen intuitively from the startup log. this effect.
verify
In order to verify my guess, I configured these two configurations at the same time as false
, and adjusted the delay registration time to be very large.
eureka.client.healthcheck.enabled=false
eureka.client.onDemandUpdateStatusChange=false
eureka.client.initial-instance-info-replication-interval-seconds=9999999 //默认40秒
eureka.client.instance-info-replication-interval-seconds=999999 //默认30秒
But, but! ! !
I found that after dozens of seconds, I still registered to the server, I was really drunk. . .
Then keep reading.
Looking at the registration method again, there may be calls in more than one place. We found that it was the case, and the registration method was called in 3 places.
When the first call is injected in DiscoveryClient
, look at this, clientConfig.shouldEnforceRegistrationAtInit()
The default is false
, the method will not come in, ignore him.
Then continue to look at the second call, you can see the second call renew
method, we can see it by looking at it, isn't this the heartbeat? !
If sending a heartbeat returns NOT_FOUND
, it will go to register.
I feel that it is close to the truth. Go to the source code of the server's heartbeat. According to the calling path, find the source code located in InstanceResource
.
You can see that the instance information obtained from the registry is empty when you register for the first time, so if false is returned directly, NOT FOUND will be returned.
Look at the registry.renew
method, which will eventually be called to AbstractInstanceRegistry
. During initialization, the registry registry
must have no information about the current instance, so it is empty and returns If false, it finally returns NOT_FOUND
.
Therefore, although we set these two parameters to false
, but because the heartbeat is every 30 seconds by default, we finally found that the configured super delay registration time did not fully take effect.
Summarize
OK, at this point, the reason why the delayed registration does not take effect has been found, and we will make a summary.
By default, the configured delay registration time will not take effect, because the default event listener is true
, and the service will be registered to Eureka Server immediately after it starts.
If you need to delay the registration to take effect, it must be eureka.client.healthcheck.enabled
, eureka.client.onDemandUpdateStatusChange
are all false
.
Even if we block all channels, the thread sending the heartbeat will still register, so the delay registration time will not exceed 30 seconds at most, even if the configured delay time exceeds 30 seconds.
OK, that's it, this is the end, I'm Ai Xiaoxian, welcome to Paizhuan.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。