Diagram + source code to explain the Eureka Client service registration process

Get into the habit of writing together! This is the 5th day of my participation in the "Nuggets Daily New Plan·April Update Challenge", click to view the details of the event

Eureka Client service registration process

Determination is the beginning of success

Related articles
Diagram + source code explanation Eureka Server startup process analysis
diagram + source code explanation Eureka Client startup process analysis
diagram + source code explanation Eureka Server registry cache logic
diagram + source code explanation Eureka Client pull registry process

Registration core flow chart

image.png

Where to start your analysis

When the client is initialized, clientConfig.shouldEnforceRegistrationAtInit() Whether to enable mandatory registration when initializing, this value is false by default, so it will not be registered. It is registered in the renew() method in the subsequent 30s sending heartbeat mechanism task.

if (clientConfig.shouldRegisterWithEureka() && 
    // clientConfig.shouldEnforceRegistrationAtInit() 默认是false
    clientConfig.shouldEnforceRegistrationAtInit()) {
    if (!register()) {
        throw new IllegalStateException("Registration error at startup. Invalid server response.");
    }
}
复制代码

core logic

    When the heartbeat is sent through renew(), it returns that the instance information cannot be found, so the registration operation is performed again, and the heartbeat request operation is performed through the eurekaTransport.registrationClient client.

1. Initiate registration through heartbeat timing tasks

boolean renew() {
EurekaHttpResponse<InstanceInfo> httpResponse;
    httpResponse = eurekaTransport.registrationClient.
        sendHeartBeat(instanceInfo.getAppName(), 
                      instanceInfo.getId(), instanceInfo, null);
    if (httpResponse.getStatusCode() == Status.NOT_FOUND.getStatusCode()) {
        REREGISTER_COUNTER.increment();
        long timestamp = instanceInfo.setIsDirtyWithTime();
        boolean success = register(); // 注册实例
        if (success) {
            instanceInfo.unsetIsDirty(timestamp);
        }
        return success;
    }
    return httpResponse.getStatusCode() == Status.OK.getStatusCode();
}
复制代码

    Instance registration is performed through the register() method, and registration method access is performed through eurekaTransport.registrationClient, which accesses the register method of AbstractJersey2EurekaHttpClient

boolean register() throws Throwable {
    EurekaHttpResponse<Void> httpResponse;
    httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
    ....
}
复制代码

    The register method of AbstractInstanceRegistry under the eureka-core project is accessed through the jersey2 framework

public void register(InstanceInfo registrant, int leaseDuration,
                     boolean isReplication) {
    /**
     * 通过服务名字从本地的 gMap 中获取一个服务实例信息
     */
    Map<String, Lease<InstanceInfo>> gMap = registry.get(registrant.getAppName());
    if (gMap == null) {
        // 如果本地gMap中没有当前要注册的实例的话创建一个 gNewMap 
        // 也就是 registry 中的一个服务实例
        final ConcurrentHashMap<String, Lease<InstanceInfo>> gNewMap = 
            new ConcurrentHashMap<String, Lease<InstanceInfo>>();
        // 将当前服务名字为key并且服务名字,value就是当前要注册的 gNewMap
        gMap = registry.putIfAbsent(registrant.getAppName(), gNewMap);
        if (gMap == null) {
            gMap = gNewMap;
        }
    }
    // 说白了上面就是创建了一个gMap中的一个实例
    gMap.put(registrant.getId(), lease);
}
复制代码

2. Put the current instance into the queue

    This registration queue and change queue are created when the service is initialized. The recently changed state can be monitored through this recently changed queue. The newly registered queue and the offline queue are mainly for display on the page . The recently changed queue It is used when obtaining incremental registration instance information.

/**
 * 将当前实例放入到最近注册的队列
 */
recentRegisteredQueue.add(new Pair<Long, String>(System.currentTimeMillis(),
             registrant.getAppName() + "(" + registrant.getId() + ")"));
// 设置类型为添加类型
registrant.setActionType(ActionType.ADDED);
/**
 * 添加也属于改变所以创建一个最近的改变对象【RecentlyChangedItem】放入到最近的改变队列中,
 * 时间戳是当前的系统时间
 */
recentlyChangedQueue.add(new RecentlyChangedItem(lease));
复制代码

3. Invalidate local cache

/**
 * 当有新实例过来的时候无效当前读写缓存
 */
invalidateCache(registrant.getAppName(), registrant.getVIPAddress(),
                registrant.getSecureVipAddress());
复制代码

    Invalidating the local cache operation is to remove some keys in the cache from the cache through the invalidate method of ResponseCacheImpl, and remove the key value in the read-write cache.

public void invalidate(Key... keys) {
    for (Key key : keys) {
        // 移除读写缓存中的key
        readWriteCacheMap.invalidate(key);
        Collection<Key> keysWithRegions = regionSpecificKeys.get(key);
        if (null != keysWithRegions && !keysWithRegions.isEmpty()) {
            for (Key keysWithRegion : keysWithRegions) {
                readWriteCacheMap.invalidate(keysWithRegion);
            }
        }
    }
}
复制代码

summary

  1. Initiate registration via heartbeat
  2. Put the current instance into the registration queue and the recent changes queue
  3. Invalidate server-side cache

Guess you like

Origin juejin.im/post/7082929115703017486