注册流程
如果需要注册,肯定需要一个注册的实例端
在EurekaClientAutoConfiguration中寻找EurekaClient
@Bean(destroyMethod = "shutdown")
// @ConditionalOnMissingBean如果spring中没有该bean则创建,反之不创建
@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config) {
return new CloudEurekaClient(manager, config, this.optionalArgs,
this.context);
}
点进去可以看到它是一个接口
public interface EurekaClient extends LookupService
查看它的实现类DiscoveryClient,先是进行一堆初始化赋值,然后创建了三个线程池,最后初始化了所有定时任务
@Inject
DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
Provider<BackupRegistry> backupRegistryProvider) {
// .. 一些的初始化赋值
try {
// default size of 2 - 1 each for heartbeat and cacheRefresh
// 定时任务
scheduler = Executors.newScheduledThreadPool(2,
new ThreadFactoryBuilder()
.setNameFormat("DiscoveryClient-%d")
.setDaemon(true)
.build());
// 心跳检测
heartbeatExecutor = new ThreadPoolExecutor(
1, clientConfig.getHeartbeatExecutorThreadPoolSize(), 0, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
new ThreadFactoryBuilder()
.setNameFormat("DiscoveryClient-HeartbeatExecutor-%d")
.setDaemon(true)
.build()
); // use direct handoff
// 缓存刷新
cacheRefreshExecutor = new ThreadPoolExecutor(
1, clientConfig.getCacheRefreshExecutorThreadPoolSize(), 0, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
new ThreadFactoryBuilder()
.setNameFormat("DiscoveryClient-CacheRefreshExecutor-%d")
.setDaemon(true)
.build()
); // use direct handoff
// ...
} catch (Throwable e) {
throw new RuntimeException("Failed to initialize DiscoveryClient!", e);
}
//...
// 初始化了所有定时任务
initScheduledTasks();
//...
}
继续追踪initScheduledTasks()方法,看看心跳检测初始化时都干了些什么
/**
* Initializes all scheduled tasks.
*/
private void initScheduledTasks() {
// ...
// Heartbeat timer
scheduler.schedule(
new TimedSupervisorTask(
"heartbeat",
scheduler,
heartbeatExecutor,
renewalIntervalInSecs,
TimeUnit.SECONDS,
expBackOffBound,
new HeartbeatThread()
),
renewalIntervalInSecs, TimeUnit.SECONDS);
// ...
}
调用了renew()方法,继续跟踪看看它做了什么
/**
* The heartbeat task that renews the lease in the given intervals.
*/
private class HeartbeatThread implements Runnable {
public void run() {
if (renew()) {
lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis();
}
}
}
InstanceInfo顾名思义,实例信息,先是创建一个实例集合,请求一次服务,如果该服务状态值是404,则计数器+1并调用注册方法
/**
* Renew with the eureka service by making the appropriate REST call
*/
boolean renew() {
// 定义一个实例信息集合
EurekaHttpResponse<InstanceInfo> httpResponse;
try {
// 请求服务
httpResponse = eurekaTransport.registrationClient.sendHeartBeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null);
logger.debug("{} - Heartbeat status: {}", PREFIX + appPathIdentifier, httpResponse.getStatusCode());
if (httpResponse.getStatusCode() == 404) {
// 如果没有注册过,则计数器+1
REREGISTER_COUNTER.increment();
logger.info("{} - Re-registering apps/{}", PREFIX + appPathIdentifier, instanceInfo.getAppName());
// 调用注册方法
return register();
}
return httpResponse.getStatusCode() == 200;
} catch (Throwable e) {
logger.error("{} - was unable to send heartbeat!", PREFIX + appPathIdentifier, e);
return false;
}
}
继续追踪register()方法
将实例信息放入了集合中,通过适当的REST调用向eureka进行服务注册,返回是否成功
/**
* Register with the eureka service by making the appropriate REST call.
*/
boolean register() throws Throwable {
logger.info(PREFIX + appPathIdentifier + ": registering service...");
// 定义一个集合
EurekaHttpResponse<Void> httpResponse;
try {
// 向eureka服务注册
httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
} catch (Exception e) {
logger.warn("{} - registration failed {}", PREFIX + appPathIdentifier, e.getMessage(), e);
throw e;
}
if (logger.isInfoEnabled()) {
logger.info("{} - registration status: {}", PREFIX + appPathIdentifier, httpResponse.getStatusCode());
}
// 返回操作是否成功
return httpResponse.getStatusCode() == 204;
}
总结
EurekaClient的实现类DiscoveryClient中,DiscoveryClient方法初始化了三个线程池,定时任务的,心跳的,缓存的.
在初始化心时任务中,初始化了心跳检测的线程,并创建了HeartbeatThread执行了renew()更新方法
通过该方法,请求Eureka服务,如果返回404,则计数器+1,再通过REST调用向eureka服务注册并返回是否注册成功.如果不是404,则返回请求是否成功的状态值.