Make writing a habit together! This is the 7th day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details

Analysis of Eureka Client offline process

If life is compared to the artistic conception of creation, then reading is like sunshine — Chi Li

Eureka Server startup process analysis diagram + source code explain Eureka Client startup process analysis diagram + source code explain Eureka Server registry cache logic diagram + source code explain Eureka Client Eureka Client service registration process diagram + source code explain Eureka Client heartbeat mechanism process

Core flow chart

Where to start

DiscoveryClient is basically a client-specific class, and it’s supposed to have all the registration methods, all the logout methods, all the heartbeat methods, so let’s take a look at the main methods of this class. Okay

Core method logic

Shatdown logout method

This method is the core method for bringing an instance offline. It contains methods such as unregistering listeners, unscheduling tasks, setting an instance to be offline, unregistering subsequent methods, handling subsequent unwanted resources, and unregistering monitoring operations

public synchronized void shutdown(a) {
    if (isShutdown.compareAndSet(false.true)) {
        logger.info("Shutting down DiscoveryClient ...");
    if(statusChangeListener ! =null&& applicationInfoManager ! =null) {
        applicationInfoManager.
            unregisterStatusChangeListener(statusChangeListener.getId());
    }
    /** * Cancel scheduling tasks such as heartbeat and registry cache */
    cancelScheduledTasks();
    / * * * if the application has been registered * clientConfig shouldRegisterWithEureka () && clientConfig. ShouldUnregisterOnShutdown () to true * / default
    if(applicationInfoManager ! =null && clientConfig.shouldRegisterWithEureka() 
        && clientConfig.shouldUnregisterOnShutdown()) {
        /** * Sets the instance status to offline */
        applicationInfoManager.setInstanceStatus(InstanceStatus.DOWN);
        /** * Sends the offline logic to the eureka-server to indicate that the current instance is offline */
        unregister();
    }
    /** * Process subsequent unneeded resources */
    if(eurekaTransport ! =null) {
        eurekaTransport.shutdown();
    }
    heartbeatStalenessMonitor.shutdown();
    registryStalenessMonitor.shutdown();
    /** * Cancel monitoring registration */
    Monitors.unregisterObject(this);
    logger.info("Completed shut down of DiscoveryClient"); }}Copy the code

CancelScheduledTasks cancelScheduledTasks

In this case, the unscheduled tasks are those scheduled tasks initialized when the client initializes operations, such as heartbeat tasks, cache operations, and so on

private void cancelScheduledTasks(a) {
    // Instance replication stopped
    if(instanceInfoReplicator ! =null) {
        instanceInfoReplicator.stop();
    }
   // The heartbeat actuator is closed
    if(heartbeatExecutor ! =null) {
        heartbeatExecutor.shutdownNow();
    }
   // The cache executor is closed
    if(cacheRefreshExecutor ! =null) {
        cacheRefreshExecutor.shutdownNow();
    }
    // The scheduler is closed
    if(scheduler ! =null) {
        scheduler.shutdownNow();
    }
     // Cancel the cache refresh task
    if(cacheRefreshTask ! =null) {
        cacheRefreshTask.cancel();
    }
     // Cancel the heartbeat task
    if(heartbeatTask ! =null) { heartbeatTask.cancel(); }}Copy the code

Unregister logic

If the instance is not null, the status of the instance is set to offline first, after the unregister () method, through eurekaTransport. RegistrationClient client cancel method for instance

void unregister(a) {
    // It can be null if shouldRegisterWithEureka == false
    if(eurekaTransport ! =null&& eurekaTransport.registrationClient ! =null) {
            logger.info("Unregistering ..."); EurekaHttpResponse<Void> httpResponse = eurekaTransport.registrationClient. cancel(instanceInfo.getAppName(), instanceInfo.getId()); }}Copy the code

Through AbstractJersey2EurekaHttpClient cancel operation for instance offline, Construct a send request to the Eureka-core project to find the cancelLease method in the InstanceResource class. This method is the real loff request logic

@DELETE
public Response cancelLease(@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) 
                        String isReplication) {
  registry.cancel(app.getName(), id, "true".equals(isReplication));
  return Response.ok().build();
}
Copy the code

Execution is the registry PeerAwareInstanceRegistryImpl cancel method, after the synchronization to other service node, all need to logoff the current instance

@Override
public boolean cancel(final String appName, final String id,
                      final boolean isReplication) {
    // Cancel the instance operation
    if (super.cancel(appName, id, isReplication)) {
        // Cluster synchronization method
        replicateToPeers(Action.Cancel, appName, id, null.null, isReplication);

        return true;
    }
    return false;
}

Copy the code

Execute the registry’s internalCancel method, which contains a number of core methods

Removes the current offline instance information from the local read/write cache

If the local read/write cache is not empty, the instance is removed from the read/write cache

public boolean cancel(String appName, String id, boolean isReplication) {
    return internalCancel(appName, id, isReplication);
}

protected boolean internalCancel(String appName, String id, boolean isReplication) {
    CANCEL.increment(isReplication);
    Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
    Lease<InstanceInfo> leaseToCancel = null;
    if(gMap ! =null) {
       // Remove the service instance from the eureka Server map registryleaseToCancel = gMap.remove(id); }...return true;
}
Copy the code

Put the offline instance into the nearest offline queue

Put the most recently offline instance into the most recently offline queue

  /** * The queue whose instance went offline recently */
    recentCanceledQueue.add(new Pair<Long, String>(System.currentTimeMillis(), 
                                                   appName + "(" + id + ")"));
    /** * Lease's cancel() method is called and evictionTimestamp */ is the time when the service instance was cleared and the service instance went offline
    leaseToCancel.cancel();
  
Copy the code

Add to the queue that changed recently

Set the current instance to offline and put it in the recently changed queue

InstanceInfo instanceInfo = leaseToCancel.getHolder();
String vip = null;
String svip = null;
if(instanceInfo ! =null) {
    // Set the operation type of the instance to delete
    instanceInfo.setActionType(ActionType.DELETED);
    // The instance goes offline to the change queue
    recentlyChangedQueue.add(new RecentlyChangedItem(leaseToCancel));
    instanceInfo.setLastUpdatedTimestamp();
    vip = instanceInfo.getVIPAddress();
    svip = instanceInfo.getSecureVipAddress();
}

Copy the code

Invalid local cache

ReadWriteCacheMap and readOnlyCacheMap are synchronized every 30 seconds. The next time all eureka clients pull delta registries, ReadOnlyCacheMap doesn't exist, readWriteCacheMap doesn't exist, and the delta registry is fetched from the registry, and the recentCHangedQuuee is returned */
invalidateCache(appName, vip, svip);
Copy the code

Update expected heartbeats

// Offline the expected heartbeat operation
synchronized (lock) {
    if (this.expectedNumberOfClientsSendingRenews > 0) {
        this.expectedNumberOfClientsSendingRenews = 
            this.expectedNumberOfClientsSendingRenews - 1; updateRenewsPerMinThreshold(); }}protected void updateRenewsPerMinThreshold(a) {
        / / serverConfig. GetExpectedClientRenewalIntervalSeconds () the default 30 s
        / / 60.0 / serverConfig. GetExpectedClientRenewalIntervalSeconds () = = 2,
        // serverConfig.getRenewalPercentThreshold())
        // 2*0.85 is the expected number of instances *2*0.85 heartbeats per minute
        this.numberOfRenewsPerMinThreshold = (int)
                (this.expectedNumberOfClientsSendingRenews * 
                 (60.0 / serverConfig.getExpectedClientRenewalIntervalSeconds())
                 * serverConfig.getRenewalPercentThreshold());
 }
Copy the code

summary

  1. Service Offline Operation
  2. Removes the current instance from the local cache
  3. Add to the nearest offline queue and change queue
  4. Invalid local cache
  5. When the service is removed, the number of instance heartbeats per minute needs to be updated, and when an instance is dropped, two heartbeats are lost