Diagrama + código fuente Eureka Client análisis de procesos fuera de línea

¡Acostúmbrate a escribir juntos! Este es el séptimo día de mi participación en el "Nuggets Daily New Plan·Desafío de actualización de abril", haz clic para ver los detalles del evento

Análisis de procesos fuera de línea de Eureka Client

Si la vida se compara con la concepción artística de la creación, entonces la lectura es como la luz del sol - Chi Li

Artículos relacionados
Diagrama + explicación del código fuente Diagrama de análisis del proceso de inicio del servidor Eureka + explicación del código fuente Diagrama
de análisis del proceso de inicio del cliente Eureka + explicación del código fuente Diagrama
lógico de la memoria caché del registro del servidor Eureka + explicación del código fuente Diagrama
de flujo del registro de extracción del cliente Eureka
+ explicación del código fuente Servicio del cliente Eureka proceso de registro
Diagrama + código fuente para explicar el proceso del mecanismo de latido del cliente Eureka

Diagrama de flujo central

imagen.png

Dónde comenzar su análisis

    La clase DiscoveryClient es en realidad una clase relacionada con el cliente. Es lógico que el método de registro, el método fuera de línea y el método de latido estén todos aquí, así que echemos un vistazo a los métodos principales de esta clase.
imagen.png

lógica del método central

método fuera de línea shadown

    Este método es el método principal de la instancia fuera de línea, que incluye algunos métodos, como cancelar la operación de escucha, cancelar la operación de la tarea de programación, configurar la instancia como un método fuera de línea, cancelar el registro de métodos posteriores, procesar recursos innecesarios posteriores y cancelar registro Supervisión de operaciones

public synchronized void shutdown() {
    if (isShutdown.compareAndSet(false, true)) {
        logger.info("Shutting down DiscoveryClient ...");
    if (statusChangeListener != null && applicationInfoManager != null) {
        applicationInfoManager.
            unregisterStatusChangeListener(statusChangeListener.getId());
    }
    /**
     * 取消调度任务比如心跳、注册表缓存
     */
    cancelScheduledTasks();
    /**
     * 如果应用程序被注册过
     * clientConfig.shouldRegisterWithEureka() &&
     clientConfig.shouldUnregisterOnShutdown() 默认都为true
     */
    if (applicationInfoManager != null && clientConfig.shouldRegisterWithEureka() 
        && clientConfig.shouldUnregisterOnShutdown()) {
        /**
         * 设置实例状态为下线
         */
        applicationInfoManager.setInstanceStatus(InstanceStatus.DOWN);
        /**
         * 发送下线逻辑给eureka-server端提示当前实例下线处理
         */
        unregister();
    }
    /**
     * 处理后续不需要的资源
     */
    if (eurekaTransport != null) {
        eurekaTransport.shutdown();
    }
    heartbeatStalenessMonitor.shutdown();
    registryStalenessMonitor.shutdown();
    /**
     * 取消监控注册
     */
    Monitors.unregisterObject(this);
    logger.info("Completed shut down of DiscoveryClient");
    }
}
复制代码

Cancelar tareas programadas cancelScheduledTasks

    La cancelación de tareas de programación aquí son en realidad aquellas tareas de programación que se inicializan cuando el cliente inicia operaciones, como tareas de latido, tareas de operación de caché, etc.

private void cancelScheduledTasks() {
    // 实例复制停止
    if (instanceInfoReplicator != null) {
        instanceInfoReplicator.stop();
    }
   // 心跳执行器关闭
    if (heartbeatExecutor != null) {
        heartbeatExecutor.shutdownNow();
    }
   // 缓存执行器关闭
    if (cacheRefreshExecutor != null) {
        cacheRefreshExecutor.shutdownNow();
    }
    // 调度执行器关闭
    if (scheduler != null) {
        scheduler.shutdownNow();
    }
     // 取消缓存刷新任务
    if (cacheRefreshTask != null) {
        cacheRefreshTask.cancel();
    }
     // 取消心跳任务
    if (heartbeatTask != null) {
        heartbeatTask.cancel();
    }
}
复制代码

anular el registro de la lógica

    Si la instancia no está vacía, primero establezca el estado de la instancia en el estado fuera de línea, luego realice la operación del método unregister() y elimine la instancia a través del método cancel del cliente eurekaTransport.registrationClient.

void unregister() {
    // 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());
    }
}
复制代码

    La instancia está fuera de línea a través de la operación de cancelación de AbstractJersey2EurekaHttpClient, y se construye una solicitud de envío para ir al proyecto eureka-core para encontrar el método cancelLease en la clase InstanceResource.Este método es la lógica real de solicitud fuera de línea.

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

    Ejecute el método de cancelación de PeerAwareInstanceRegistryImpl en el registro y luego sincronice con otros nodos de servicio, todos necesitan desconectar la instancia actual

@Override
public boolean cancel(final String appName, final String id,
                      final boolean isReplication) {
    // 取消实例操作
    if (super.cancel(appName, id, isReplication)) {
        // 集群同步方法
        replicateToPeers(Action.Cancel, appName, id, null, null, isReplication);

        return true;
    }
    return false;
}

复制代码

    Ejecute el método internalCancel en el registro, que contiene muchos métodos básicos

Eliminar la información actual de la instancia sin conexión de la memoria caché local de lectura y escritura

    Si la memoria caché local de lectura y escritura no está vacía, es decir, cuando se obtiene la instancia actual, elimine su instancia de la memoria caché de lectura y escritura.

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) {
       //  将服务实例从eureka server的map结构的注册表中移除掉
        leaseToCancel = gMap.remove(id);
    }
    ......
    return true;
}
复制代码

Coloque la instancia fuera de línea en la cola recientemente fuera de línea

    Ponga la instancia recientemente fuera de línea en la cola recientemente fuera de línea

  /**
     * 最近有实例下线的队列
     */
    recentCanceledQueue.add(new Pair<Long, String>(System.currentTimeMillis(), 
                                                   appName + "(" + id + ")"));
    /**
     * 调用了Lease的cancel()方法,里面保存了一个evictionTimestamp
     * 就是服务实例被清理掉,服务实例下线的时间戳
     */
    leaseToCancel.cancel();
  
复制代码

Añadir a la cola modificada recientemente

    Establezca la instancia actual para la operación sin conexión y luego colóquela en la cola de cambios recientes

InstanceInfo instanceInfo = leaseToCancel.getHolder();
String vip = null;
String svip = null;
if (instanceInfo != null) {
    // 设置实例的操作类型是删除操作
    instanceInfo.setActionType(ActionType.DELETED);
    // 实例下线进入改变队列
    recentlyChangedQueue.add(new RecentlyChangedItem(leaseToCancel));
    instanceInfo.setLastUpdatedTimestamp();
    vip = instanceInfo.getVIPAddress();
    svip = instanceInfo.getSecureVipAddress();
}

复制代码

Invalidar caché local

/**
 * 实例下线无效本地缓存,中清理掉
 * 就是有一个定时的任务,每隔30秒,将readWriteCacheMap和readOnlyCacheMap进行一个同步
 * 下次所有的eureka client来拉取增量注册表的时候,都会发现readOnlyCacheMap里没有,
 * 会找readWriteCacheMap也会发现没有,
 * 然后就会从注册表里抓取增量注册表,此时就会将上面那个recentCHangedQuuee中的记录返回
 */
invalidateCache(appName, vip, svip);
复制代码

Actualizar el número esperado de latidos

// 下线期待的每次心跳操作
synchronized (lock) {
    if (this.expectedNumberOfClientsSendingRenews > 0) {
        this.expectedNumberOfClientsSendingRenews = 
            this.expectedNumberOfClientsSendingRenews - 1;
        updateRenewsPerMinThreshold();
    }
}
 protected void updateRenewsPerMinThreshold() {
        // serverConfig.getExpectedClientRenewalIntervalSeconds() 默认 30s
        // 60.0 / serverConfig.getExpectedClientRenewalIntervalSeconds() == 2、
        // serverConfig.getRenewalPercentThreshold())
        // 2 * 0.85 也就是期待一分钟内 实例数量*2*0.85个心跳
        this.numberOfRenewsPerMinThreshold = (int)
                (this.expectedNumberOfClientsSendingRenews * 
                 (60.0 / serverConfig.getExpectedClientRenewalIntervalSeconds())
                 * serverConfig.getRenewalPercentThreshold());
 }
复制代码

resumen

  1. Operación fuera de línea del servicio
  2. Eliminar la instancia actual del caché local
  3. Agregar a la cola sin conexión reciente y cambiar la cola
  4. Invalidar caché local
  5. Si se elimina el servicio, se debe actualizar el número de latidos de la instancia por minuto. Si se descarta una instancia, el latido se reducirá dos veces.

Supongo que te gusta

Origin juejin.im/post/7083667521022197797
Recomendado
Clasificación