【Spring Cloud】Eureka-Client 源码解读
一、前言
看源码:抓大放小,先主流程,再细枝末节。
用技巧连蒙带猜:
看方法名(英文名)
看注释
搭建环境:
// 定位:eureka-examples 模块下
// 修改 ExampleEurekaClient.java
// 1. 增加一个方法,用于初始化环境变量,方便调试
private static void injectEurekaConfiguration() throws UnknownHostException {
String myHostName = InetAddress.getLocalHost().getHostName();
String myServiceUrl = "http://" + myHostName + ":8080/v2/";
System.setProperty("eureka.region", "default");
System.setProperty("eureka.name", "eureka");
System.setProperty("eureka.vipAddress", "eureka.mydomain.net");
System.setProperty("eureka.port", "8080");
System.setProperty("eureka.preferSameZone", "false");
System.setProperty("eureka.shouldUseDns", "false");
System.setProperty("eureka.shouldFetchRegistry", "false");
System.setProperty("eureka.serviceUrl.defaultZone", myServiceUrl);
System.setProperty("eureka.serviceUrl.default.defaultZone", myServiceUrl);
System.setProperty("eureka.awsAccessId", "fake_aws_access_id");
System.setProperty("eureka.awsSecretKey", "fake_aws_secret_key");
System.setProperty("eureka.numberRegistrySyncRetries", "0");
}
// 2. 在 main 方法添加
public static void main(String[] args) throws UnknownHostException {
// 添加如下这行
injectEurekaConfiguration();
... ...
}
复制代码
二、从源码中学到了什么
三、直接怼源码
(1)eureka-client
如何启动(初始化)?
代码如下:
// 定位:com.netflix.eureka.ExampleEurekaClient.java
public static void main(String[] args) throws UnknownHostException {
// 1. 初始化 eureka 环境变量
injectEurekaConfiguration();
// 2. 创建 eureka 服务
ExampleEurekaClient sampleClient = new ExampleEurekaClient();
// 3. 创建服务实例管理器
ApplicationInfoManager applicationInfoManager =
initializeApplicationInfoManager(new MyDataCenterInstanceConfig());
// 4. 创建 eureka-client
EurekaClient client =
initializeEurekaClient(applicationInfoManager, new DefaultEurekaClientConfig());
... ...
}
复制代码
过程如下:
初始化
eureka
环境变量创建
eureka
服务,会有一个eureka-client
创建服务实例管理器
ApplicationInfoManager applicationInfoManager = initializeApplicationInfoManager(new MyDataCenterInstanceConfig());
复制代码构建服务实例(
InstanceInfo
)构建服务实例管理器(
ApplicationInfoManager
)创建
eureka-client
(通过构造DiscoveryClient
)处理配置
服务的注册和注册表的抓取(初始化网络通信组件)
创建几个线程池,启动调度任务
注册监控项
(2)eureka-client
如何服务注册的?
针对注册,提出问题:
什么时候进行服务注册?初始化
eureka-client
时候
eureka-client
的服务注册,是在InstanceInfoReplicator
中完成的。
服务注册做哪些操作?主要发送
HTTP
请求
针对这个两个问题,来看下源码。虽然这部分的源码写的不好,但也可以学习了解下他人的思路。
这部分源码比较难找,实际是在创建 DiscoveryClient
的 initScheduledTasks()
(初始化调度任务)
// 定位:com.netflix.discovery.DiscoveryClient.java
private void initScheduledTasks() {
// InstanceRegisterManager:实例注册管理器,专门来管理实例注册
// 传参:默认 40秒
instanceInfoReplicator.start(...);
}
复制代码
启动实例注册管理器(
InstanceRegisterManager
)
// 定位:com.netflix.discovery.InstanceInfoReplicator.java
public void start(int initialDelayMs) {
// 原子操作
if (started.compareAndSet(false, true)) {
// 1. 先设置 isDirty = true
instanceInfo.setIsDirty();
// 2. 调度器执行,将自身传入,并且调度时间默认为 40 秒
// 所以会执行 InstanceInfoReplicator.run() 方法
Future next = scheduler.schedule(this, initialDelayMs, TimeUnit.SECONDS);
scheduledPeriodicRef.set(next);
}
}
复制代码
执行
InstanceInfoReplicator.run()
// 定位:com.netflix.discovery.InstanceInfoReplicator.java
// 会发现:class InstanceInfoReplicator implements Runnable,是可创建线程的。
public void run() {
try {
// 1. 刷新了服务实例的信息,拿到服务的状态
discoveryClient.refreshInstanceInfo();
Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
if (dirtyTimestamp != null) {
// 2. 注册:因为之前已经设置 isDirty = true,所以下面直接注册
discoveryClient.register();
// 3. 设置 isDirty = false
instanceInfo.unsetIsDirty(dirtyTimestamp);
}
} catch (Throwable t) {
logger.warn("There was a problem with the instance info replicator", t);
} finally {
// 4. 再次把自己丢进调度线程中
Future next =
scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);
scheduledPeriodicRef.set(next);
}
}
复制代码
重要:注册
discoveryClient.register();
// 定位:com.netflix.discovery.DiscoveryClient.java
boolean register() throws Throwable {
EurekaHttpResponse<Void> httpResponse;
try {
// 发送 HTTP 请求
httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
... ...
}
... ...
return httpResponse.getStatusCode() == 204;
}
作者:卷卷啊
链接:https://juejin.cn/post/6968080788868825118
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论