Eureka client 源码解析(一)

676 阅读1分钟
  • 入口

image.png

  • 分析

image.png

  • @AutoConfigureBefore:EurekaClientAutoConfiguration在其之前加载
  • @AutoConfigureAfter:EurekaClientAutoConfiguration在其之后加载
EurekaClient 相关入口

image.png springboot 封装了netflix的相关代码

image.png com.netflix.discovery.DiscoveryClient#DiscoveryClient(com.netflix.appinfo.ApplicationInfoManager, com.netflix.discovery.EurekaClientConfig, com.netflix.discovery.AbstractDiscoveryClientOptionalArgs, javax.inject.Provider<com.netflix.discovery.BackupRegistry>)

初始化定时任务

image.png 其中com.netflix.discovery.TimedSupervisorTask 就是核心的线程执行类

public void run() {
    Future<?> future = null;
    try {
        future = executor.submit(task);
        threadPoolLevelGauge.set((long) executor.getActiveCount());
        future.get(timeoutMillis, TimeUnit.MILLISECONDS);  // block until done or timeout
        delay.set(timeoutMillis);
        threadPoolLevelGauge.set((long) executor.getActiveCount());
    } catch (TimeoutException e) {
        logger.warn("task supervisor timed out", e);
        timeoutCounter.increment();

        long currentDelay = delay.get();
        long newDelay = Math.min(maxDelay, currentDelay * 2);
        delay.compareAndSet(currentDelay, newDelay);

    } catch (RejectedExecutionException e) {
        if (executor.isShutdown() || scheduler.isShutdown()) {
            logger.warn("task supervisor shutting down, reject the task", e);
        } else {
            logger.warn("task supervisor rejected the task", e);
        }

        rejectedCounter.increment();
    } catch (Throwable e) {
        if (executor.isShutdown() || scheduler.isShutdown()) {
            logger.warn("task supervisor shutting down, can't accept the task");
        } else {
            logger.warn("task supervisor threw an exception", e);
        }

        throwableCounter.increment();
    } finally {
        if (future != null) {
            future.cancel(true);
        }

        if (!scheduler.isShutdown()) {
            scheduler.schedule(this, delay.get(), TimeUnit.MILLISECONDS);
        }
    }
}

其中这一块,我觉的可以借鉴一下,以后自己写延迟可以用

try {
    future = executor.submit(task);
    threadPoolLevelGauge.set((long) executor.getActiveCount());
    // future 获取结果的时候会阻塞住,知道超时或者完成
    future.get(timeoutMillis, TimeUnit.MILLISECONDS);  
    delay.set(timeoutMillis);
    threadPoolLevelGauge.set((long) executor.getActiveCount());
} catch (TimeoutException e) {
//超时的话就会执行这里
    logger.warn("task supervisor timed out", e);
    timeoutCounter.increment();
    //获取上一次的延迟时间
    long currentDelay = delay.get();
    //在设置的阈值内进行比较,未超过就按变成上一次的两倍
    long newDelay = Math.min(maxDelay, currentDelay * 2);
    //防止多线程操作
    delay.compareAndSet(currentDelay, newDelay);

}
.....省略相关代码
 finally {
    if (future != null) {
        future.cancel(true);
    }

    if (!scheduler.isShutdown()) {
    // 重新设置新的延迟执行时间
        scheduler.schedule(this, delay.get(), TimeUnit.MILLISECONDS);
    }
}

具体的任务实现

image.png com.netflix.discovery.DiscoveryClient.CacheRefreshThread

image.png 核心代码

image.png

image.png 使用http调用服务端代码

image.png

image.png http://localhost:3000/eureka/apps 完成调用获取全部的注册应用

  • 在这里调用 image.png 调用此方法

image.png 调用参数

image.png

预告

下期,缓存的读取与删除