简介

按照原定的计划,我将分三个部分来分析 Eureka 的源码:

  1. Eureka 的配置体系(已经写完,见Eureka详解系列(三)--探索Eureka强大的配置体系);
  2. Eureka Client 的交互行为(已经写完,见Eureka详解系列(四)--Eureka Client部分的源码和配置 );
  3. Eureka Server 的交互行为。

今天,我们来研究第三部分的源码。

分析的思路和第二部分的一样,先明确 Eureka Server 需要具备哪些功能,再从源码层面分析如何实现这些功能,最后补充 Eureka Server 的配置解读。

项目环境

os:win 10

jdk:1.8.0_231

eureka:1.10.11

tomcat:9.0.21

Eureka Server 的功能

还是来回顾 Eureka 的整个交互过程。

首先,Eureka Server 需要和 Eureka Client 交互,所以它需要能够处理 Eureka Client 的各种请求,这些请求包括:

  1. 获取注册表(Application Client 的请求);
  2. 注册、续约、注销实例(Application Service 的请求);

除此之外,在集群中,它需要和对等节点交互,交互内容主要包括:

  1. 将自己的注册表变更操作同步到其他节点
  2. 处理其他节点同步注册表的请求

其实,一个完整的 Eureka Server 项目本身也包含了 Eureka Client 的部分,也就是说,它可以注册自己和消费包括自己在内的服务,可以在 eureka-client.properties 增加以下配置来关闭掉这两个部分的功能(不建议这么做):

# 当前实例是否注册到Eureka Server。默认true
eureka.registration.enabled=false
# 当前实例是否需要从Eureka Server获取服务注册表
eureka.shouldFetchRegistry=false

如何实现这些功能

知道了 Eureka Server 需要具备哪些功能,接下来我们就从源码的角度来看看怎样实现这些功能。

和之前一样,我更多的会从设计的层面来分析,而不会顺序地去看每个过程的代码,即重设计、轻实现。

那么,还是从一个 UML 图开始吧。有了它,相信大家看源码时会更轻松一些。

AbstractInstanceRegistry里放了一张注册表,用来存放所有的实例对象,通过它可以处理 Eureka Client 或者其他 Eureka Server 的请求,包括注册、续约、注销实例以及获取注册表等。

它的子类PeerAwareInstanceRegistryImpl提供了多节点的支持,这里以续约实例的方法为例,相同的操作还会被同步到其他节点(对等节点的请求除外)。

    public boolean renew(final String appName, final String id, final boolean isReplication) {
// 先调用父类AbstractInstanceRegistry的方法
if (super.renew(appName, id, isReplication)) {
// 再将操作同步到其他节点,最终是调用PeerEurekaNode的方法进行同步
replicateToPeers(Action.Heartbeat, appName, id, null, null, isReplication);
return true;
}
return false;
}

除此之外,PeerAwareInstanceRegistryImpl还启动了三个定时任务:

  1. 更新PeerEurekaNode列表。例如,当我们使用 DNS 配合 serviceUrl 时,对等节点的地址可能会变化,所以需要及时更新。这个定时任务用于支持集群的故障转移和扩容。
  2. 更新参数 numberOfRenewsPerMinThreshold--每分钟至少要有多少实例续约。当每分钟续约实例少于这个值时(eureka 认为是灾难性的网络故障导致的),Eureka Server 将进入自我保护模式,此时,它不会再主动淘汰实例,直到我们主动关闭该模式,或者续约实例达到了阈值。我们一般可以通过以下参数来控制。而每分钟至少要有多少实例续约,这个数值受到实例总数的影响,所以需要定时更新。
# 期望实例多久续约一次
eureka.expectedClientRenewalIntervalSeconds=30
# 续约实例的阈值,未达到将开启自我保护模式
eureka.renewalPercentThreshold=0.85
# 是否启用保护模式
eureka.enableSelfPreservation=true
  1. 丢弃未能及时续约的实例。默认情况下,实例超过 90s 未能续约的话,Eureka Server 会将其丢弃掉。

从哪里开始看源码

Eureka Server 是作为一个 Web 应用运行的,要看源码比较难找到入口。打开Eureka详解系列(二)--如何使用Eureka(原生API,无Spring) 例子里的 web.xml,可以看到配置了一个监听器,这个类就是 Eureka Server 初始化的入口。

  <listener>
<listener-class>com.netflix.eureka.EurekaBootStrap</listener-class>
</listener>

在这个类里面,我们主要关注这一段代码(代码有删减)。

    protected void initEurekaServerContext() throws Exception {
// 下面这一段是为了初始化Eureka Client所需要的对象,上一篇博客讲过了
EurekaInstanceConfig instanceConfig = new MyDataCenterInstanceConfig();
ApplicationInfoManager applicationInfoManager = new ApplicationInfoManager(
instanceConfig, new EurekaConfigBasedInstanceInfoProvider(instanceConfig).get());
EurekaClientConfig eurekaClientConfig = new DefaultEurekaClientConfig();
eurekaClient = new DiscoveryClient(applicationInfoManager, eurekaClientConfig); // 加载eureka-server.properties的配置
EurekaServerConfig eurekaServerConfig = new DefaultEurekaServerConfig();
ServerCodecs serverCodecs = new DefaultServerCodecs(eurekaServerConfig);
// 初始化注册表对象(支持多节点)
PeerAwareInstanceRegistry registry = new PeerAwareInstanceRegistryImpl(
eurekaServerConfig,
eurekaClient.getEurekaClientConfig(),
serverCodecs,
eurekaClient
);
// 初始化PeerEurekaNodes对象
PeerEurekaNodes peerEurekaNodes = getPeerEurekaNodes(
registry,
eurekaServerConfig,
eurekaClient.getEurekaClientConfig(),
serverCodecs,
applicationInfoManager
);
// 1. 初始化PeerEurekaNode列表,
// 2. 启动定时任务:更新PeerEurekaNode列表
peerEurekaNodes.start(); // 1. 将PeerEurekaNode列表的指针给到PeerEurekaNodes对象对象
// 2. 启动定时任务:更新参数numberOfRenewsPerMinThreshold--每分钟至少要有多少实例续约,它是判断是否开启自我保护模式的依据
registry.init(peerEurekaNodes); // 从其他节点获取实例列表并注册到本地的注册表
int registryCount = registry.syncUp();
// 1. 初始化参数numberOfRenewsPerMinThreshold--每分钟要求多少实例续约
// 2. 开启定时任务:淘汰未能正常续约的实例
registry.openForTraffic(applicationInfoManager, registryCount);
}

完成初始化后,Eureka Server 就可以处理 Eureka Client 的请求了。因为 Eureka Server 使用 jersey 作 Web 框架(jersey 和 struts2、springMVC 作用差不多,没接触过也不碍事),所以,只要找到添加了javax.ws.rs.Path注解的类,就能找到这部分代码的入口。

Eureka Server 的配置解读

回顾下Eureka详解系列(三)--探索Eureka强大的配置体系的内容,在 Eureka 里,配置分成了三种:

  1. EurekaInstanceConfig:当前实例身份的配置信息,即我是谁?
  2. EurekaServerConfig:一些影响当前Eureka Server和客户端或对等节点交互行为的配置信息,即怎么交互?
  3. EurekaClientConfig:一些影响当前实例和Eureka Server交互行为的配置信息,即和谁交互?怎么交互?

这里我们来讲讲EurekaServerConfig的配置参数,对应的是 eureka-server.properties 里的配置。

# 期望实例多久续约一次
eureka.expectedClientRenewalIntervalSeconds=30
# 续约实例的阈值,未达到将开启自我保护模式
eureka.renewalPercentThreshold=0.85
# 是否启用保护模式
eureka.enableSelfPreservation=true # 更新参数numberOfRenewsPerMinThreshold的定时任务多久执行一次
renewalThresholdUpdateIntervalM=900000
# 更新PeerEurekaNode列表的定时任务多久执行一次
peerEurekaNodesUpdateIntervalMs=600000
# 淘汰未能正常续约实例的定时任务多久执行一次
evictionIntervalTimerInMs=60000 # 这几个一般不用,我就不展开了。有需要的话可以
#awsAccessId=
#awsSecretKey=
eipBindRebindRetries=3
eipBindRebindRetryIntervalMsWhenUnbound=60000
eipBindRebindRetryIntervalMs=300000
waitTimeInMsWhenSyncEmpty=300000
shouldBatchReplication=false
disableDelta=false
numberRegistrySyncRetries=5
registrySyncRetryWaitMs=30000
enableReplicatedRequestCompression=false
minAvailableInstancesForPeerReplication=-1
peerEurekaStatusRefreshTimeIntervalMs=30000
peerNodeConnectTimeoutMs=1000
peerNodeReadTimeoutMs=5000
peerNodeTotalConnections=1000
peerNodeTotalConnectionsPerHost=500
numberOfReplicationRetries=5
maxElementsInPeerReplicationPool=10000
maxIdleThreadAgeInMinutesForPeerReplication=15
minThreadsForPeerReplication=5
maxThreadsForPeerReplication=20
maxTimeForReplication=30000
primeAwsReplicaConnections=true
maxIdleThreadAgeInMinutesForStatusReplication=10
minThreadsForStatusReplication=1
maxThreadsForStatusReplication=1
maxElementsInStatusReplicationPool=10000
disableDeltaForRemoteRegions=false
remoteRegionConnectTimeoutMs=2000
remoteRegionReadTimeoutMs=5000
remoteRegionTotalConnections=1000
remoteRegionTotalConnectionsPerHost=500
remoteRegionConnectionIdleTimeoutSeconds=30
remoteRegion.gzipContent=true
#remoteRegionUrlsWithName=
#remoteRegion.appWhiteList=
remoteRegion.registryFetchIntervalInSeconds=30
remoteRegion.fetchThreadPoolSize=20
#remoteRegion.trustStoreFileName=
remoteRegion.trustStorePassword=changeit
remoteRegion.disable.transparent.fallback=false
shouldUseAwsAsgApi=true
asgQueryTimeoutMs=300
asgUpdateIntervalMs=300000
asgCacheExpiryTimeoutMs=600000
retentionTimeInMSInDeltaQueue=180000
deltaRetentionTimerIntervalInMs=30000
responseCacheAutoExpirationInSeconds=180
responseCacheUpdateIntervalMs=30000
shouldUseReadOnlyResponseCache=true
syncWhenTimestampDiffers=true
auth.shouldLogIdentityHeaders=true
route53BindRebindRetries=3
route53BindRebindRetryIntervalMs=300000
route53DomainTTL=30
initialCapacityOfResponseCache=1000
jsonCodecName=com.netflix.discovery.converters.wrappers.CodecWrappers.LegacyJacksonJson
xmlCodecName=com.netflix.discovery.converters.wrappers.CodecWrappers.XStreamXml

以上比较宏观地讲完了 Eureka Server 的源码和配置,具体的细节欢迎私信交流。

最后,感谢您的阅读。

参考资料

https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance

相关源码请移步:https://github.com/ZhangZiSheng001/eureka-demo

本文为原创文章,转载请附上原文出处链接:https://www.cnblogs.com/ZhangZiSheng001/p/14395079.html

Eureka详解系列(五)--Eureka Server部分的源码和配置的更多相关文章

  1. Eureka详解系列(四)--Eureka Client部分的源码和配置

    简介 按照原定的计划,我将分三个部分来分析 Eureka 的源码: Eureka 的配置体系(已经写完,见Eureka详解系列(三)--探索Eureka强大的配置体系): Eureka Client ...

  2. Eureka详解系列(二)--如何使用Eureka(原生API,无Spring)

    简介 通过上一篇博客 Eureka详解系列(一)--先谈谈负载均衡器 ,我们知道了 Eureka 是什么以及为什么要使用它,今天,我们开始研究如何使用 Eureka. 在此之前,先说明一点.网上几乎所 ...

  3. 详解Mybatis拦截器(从使用到源码)

    详解Mybatis拦截器(从使用到源码) MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能. 本文从配置到源码进行分析. 一.拦截器介绍 MyBatis 允许你在 ...

  4. Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...

  5. Scala 深入浅出实战经典 第60讲:Scala中隐式参数实战详解以及在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  6. Mybatis详解系列(五)--Mybatis Generator和全注解风格的MyBatis3DynamicSql

    简介 Mybatis Generator (MBG) 是 Mybatis 官方提供的代码生成器,通过它可以在项目中自动生成简单的 CRUD 方法,甚至"无所不能"的高级条件查询(M ...

  7. Eureka详解系列(一)--先谈谈负载均衡器

    这个系列开始研究 Eureka,在此之前,先来谈谈负载均衡器. 本质上,Eureka 就是一个负载均衡器,可能有的人会说,它是一个服务注册中心,用来注册服务的,这种说法不能说错,只是有点片面. 在这篇 ...

  8. Eureka详解系列(三)--探索Eureka强大的配置体系

    简介 通过前面的两篇博客,我们知道了:什么是 Eureka?为什么使用 Eureka?如何适用 Eureka?今天,我们开始来研究 Eureka 的源码,先从配置部分的源码开始看,其他部分后面再补充. ...

  9. 源码详解系列(五) ------ C3P0的使用和分析(包括JNDI)

    简介 c3p0是用于创建和管理连接,利用"池"的方式复用连接减少资源开销,和其他数据源一样,也具有连接数控制.连接可靠性测试.连接泄露控制.缓存语句等功能.目前,hibernate ...

随机推荐

  1. linux命名小技巧(持续更新)

    一   向某个文件批量加入内容 1.1 向/etc/wxm文件添加一大段内容可以使用这个命令 [root@registry easyrsa3]# cat <<EOF >varsset ...

  2. leetcode 357. 计算各个位数不同的数字个数(DFS,回溯,数学)

    题目链接 357. 计算各个位数不同的数字个数 题意: 给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10n . 示例: 输入: 2 输出: 91 解释: 答 ...

  3. leetcode 321. 拼接最大数(单调栈,分治,贪心)

    题目链接 https://leetcode-cn.com/problems/create-maximum-number/ 思路: 心都写碎了.... 也许就是不适合吧.... 你是个好人... cla ...

  4. C语言中左值和右值的区别(C语言学习笔记)

    重要的内容要重复强调: C语言的术语Ivalue指用于识别或定位一个存储位置的标识符.( 注意:左值同时还必须是可改变的) 其实rvalue的发明完全是为了搭配lvalue , rvalue你可以理解 ...

  5. 使用yaml配置文件管理资源

    [root@k8s-master ~]# vim nginx-deployment.yaml apiVersion: apps/v1beta2 kind: Deployment metadata: n ...

  6. 通过电脑浏览器调试真机h5兼容问题

    前言 在h5开发过程中,起初我们使用PC浏览器的手机模式打开开发中的页面,并使用控制台进行调试,但实际真机兼容性问题无法调试到:在这种情况下,我们通常使用vConsole(即移动端的控制台)来调试,但 ...

  7. 单台服务器-利用docker搭建Redis哨兵集群模式

    前言:只有一台华为云服务器,所以打算创建三个容器来模拟三个服务器了. 一:拉取redis镜像 二:拉取redis.conf文件 放在自定义的目录下:wget -c http://download.re ...

  8. Seata RPC 模块的重构之路

    简介: RPC 模块是我最初研究 Seata 源码开始的地方,因此我对 Seata 的 RPC 模块有过一些深刻研究,在我研究了一番后,发现 RPC 模块中的代码需要进行优化,使得代码更加优雅,交互逻 ...

  9. Service Mesh架构的持续演进 单体模块化 SOA 微服务 Service Mesh

    架构不止-严选Service Mesh架构的持续演进 网易严选 王育松 严选技术团队 2019-11-25 前言同严选的业务一样,在下层承载它的IT系统架构一样要生存.呼吸.增长和发展,否则过时的.僵 ...

  10. Service Locator Pattern 服务定位

    https://www.geeksforgeeks.org/service-locator-pattern/ Service Locator Pattern Last Updated: 06-03-2 ...