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

Eureka Client Heartbeat mechanism process

A man of strong will can knead the world in his hand like a lump of mud

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

Core flow chart

Where to start

The logic for the client to send the heartbeat is specified when the client initializes. When it initializes the scheduling task [initScheduledTasks()], a 30-second thread pool is created, which initiates a heartbeat every 30 seconds with renew()

if (clientConfig.shouldRegisterWithEureka()) {
        /** Sends a heartbeat by default for 30s */
        int renewalIntervalInSecs = instanceInfo.
            getLeaseInfo().getRenewalIntervalInSecs();
        int expBackOffBound = clientConfig.
            getHeartbeatExecutorExponentialBackOffBound();
        // Heartbeat timer
        heartbeatTask = new TimedSupervisorTask(
                "heartbeat",
                scheduler,
                heartbeatExecutor,
                renewalIntervalInSecs,
                TimeUnit.SECONDS,
                expBackOffBound,
                new HeartbeatThread()
        );
        /** Scheduling thread pool */
        scheduler.schedule(heartbeatTask, renewalIntervalInSecs, TimeUnit.SECONDS);
}
Copy the code

A new HeartbeatThread() task is defined to run every 30s for heartbeat requests

Heartbeat request core process

Create the core sending heartbeat thread task

private class HeartbeatThread implements Runnable {
    public void run(a) {
        // Core renewal method
        if(renew()) { lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis(); }}}Copy the code

The renew() method is called, which is the core method for renewing the heartbeat. If the renewal is successful, reset the latest heartbeat success timestamp to the current system time

Heartbeat renewal method

Through eurekaTransport. Heart of registrationClient request sendHeartBeat (), This request is walking AbstractJersey2EurekaHttpClient sendHeartBeat () method

boolean renew(a) {
    EurekaHttpResponse<InstanceInfo> httpResponse;
    httpResponse = eurekaTransport.registrationClient.sendHeartBeat
        (instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null);
    if (httpResponse.getStatusCode() == Status.NOT_FOUND.getStatusCode()) {
        long timestamp = instanceInfo.setIsDirtyWithTime();
        boolean success = register();
        if (success) {
            instanceInfo.unsetIsDirty(timestamp);
        }
        return success;
    }
    return httpResponse.getStatusCode() == Status.OK.getStatusCode();
}
Copy the code

Sending a Heartbeat Request

Construct a send request to the Eureka-core project to find the renewLease method in the InstanceResource class that is the actual core renewal request logic

@Override
public EurekaHttpResponse<InstanceInfo> sendHeartBeat(String appName, String id, InstanceInfo info, InstanceStatus overriddenStatus) {
    String urlPath = "apps/" + appName + '/' + id;
    Response response = null;
    WebTarget webResource = jerseyClient.target(serviceUrl)
            .path(urlPath)
            .queryParam("status", info.getStatus().toString())
            .queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().
                        toString());
    Builder requestBuilder = webResource.request();
    addExtraProperties(requestBuilder);
    addExtraHeaders(requestBuilder);
    requestBuilder.accept(MediaType.APPLICATION_JSON_TYPE);
    / / put request
    response = requestBuilder.put(Entity.entity("{}", 
                     MediaType.APPLICATION_JSON_TYPE)); 
    EurekaHttpResponseBuilder<InstanceInfo> eurekaResponseBuilder = 
        anEurekaHttpResponse(response.getStatus(), InstanceInfo.class).
        headers(headersOf(response));
    if (response.hasEntity()) {
        eurekaResponseBuilder.entity(response.readEntity(InstanceInfo.class));
    }
    return eurekaResponseBuilder.build();
}
Copy the code

Heartbeat Request Processing

Core of the request processing method is a method that through the registry renew PeerAwareInstanceRegistryImpl # renew, this method is the real contract processing logic, really want to know is walk into the registry method for processing the heart request, Because this is a set of logic maintained locally by the registry, it has to be synchronized to other service nodes

@PUT
public Response renewLease(
        @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication,
        @QueryParam("overriddenstatus") String overriddenStatus,
        @QueryParam("status") String status,
        @QueryParam("lastDirtyTimestamp") String lastDirtyTimestamp) {
    boolean isFromReplicaNode = "true".equals(isReplication);
    /** * Heartbeat renewal */
    boolean isSuccess = registry.renew(app.getName(), id, isFromReplicaNode);
    response = Response.ok().build();
    return response;
}
Copy the code

The renew method in the registry goes to the renew method in the parent class AbstractInstanceRegistry. If the renewal succeeds, the node will be synchronized to other nodes for operation. If the renewal fails, the node will initiate registration request after receiving the result

public boolean renew(final String appName, final String id, final boolean isReplication) {
    if (super.renew(appName, id, isReplication)) {
        replicateToPeers(Action.Heartbeat, appName, id, null.null, isReplication);
        return true;
    }
    return false;
}
Copy the code

Get the current instance information in the registry, if it is not empty then fetch to renew the heartbeat, if it is empty then return can not find the instance, let it register, but here we assume that can find, because we are sending heartbeat request logic

public boolean renew(String appName, String id, boolean isReplication) {
    RENEW.increment(isReplication);
    Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
    Lease<InstanceInfo> leaseToRenew = null;
    if(gMap ! =null) {
        leaseToRenew = gMap.get(id);
    }
    // Omit some code
    renewsLastMin.increment();
    /** * Heartbeat renewal method */
    leaseToRenew.renew();
    return true;
    }
Copy the code

See leaseToRenew. Renew (); Duration is set to 90s by default, so the heartbeat is renewed successfully, so the subsequent operation is synchronized to other service nodes. The synchronized Action is the Heartbeat of the Action and we’ll do a follow-up article on cluster synchronization

public void renew(a) {
    lastUpdateTimestamp = System.currentTimeMillis() + duration;
}
Copy the code

Here we put the whole heartbeat of the operation of the renewal of the explanation

summary

  1. A heartbeat request thread task is created during client initialization
  2. Renew () is the real heartbeat renewal method
  3. Sending a Heartbeat Request
  4. Heartbeat Request Processing
  5. Heartbeat cluster synchronization, which will be explained later

thumbnails

In fact, the registry has the current instance information, each time the heartbeat renewal check whether the current instance information in the registry, if yes, then the heartbeat timestamp update operation, if not, then the instance registration operation