Eureka详解系列(四)--Eureka Client部分的源码和配置
简介
按照原定的计划,我将分三个部分来分析 Eureka 的源码:
- Eureka 的配置体系(已经写完,见Eureka详解系列(三)--探索Eureka强大的配置体系);
- Eureka Client 的交互行为;
- Eureka Server 的交互行为。
今天,我们来研究第二部分的源码。
我的思路是这样子的:先明确 Eureka Client 拥有哪些功能,然后从源码角度分析如何实现,最后,我会补充 Eureka Client 的配置解读。
Eureka Client的功能
首先来回顾下 Eureka 的整个交互过程。
从用户的角度来讲,Eureka Client 要能够向 Eureka Server 注册当前实例以及获取注册表。
至于其他的功能,我们需要再思考下。
当我们把当前实例注册到了 Eureka Server 后,并非一劳永逸,如果当前实例故障了,Eureka Server 需要及时将它从注册表中剔除,那么,Eureka Server 怎么知道哪些实例故障了呢?做法比较简单,Application Service 需要定期向 Eureka Server 报告自己的健康状态,如果一直不报告,就认为是故障了。
考虑到性能和可靠性,Application Client 本地会缓存一份服务注册表,并不需要每次用到就从 Eureka Server 重新获取。但是,Application Service “来来去去”,Eureka Server 的注册表并非一成不变,所以,Application Client 还需要定期同步注册表。
最后还有一点,我们注册到 Eureka Server 的实例信息,除了实例 IP、端口、服务名等,还有实例 id、附带的元数据等,这些是可更改的,Application Service 需要及时地将这些更改同步到 Eureka Server。
通过上面的分析,我们知道一个 Eureka Client 需要具备以下功能:
- 注册当前实例到 Eureka Server;
- 获取 Eureka Server 的服务注册表;
- 定期向 Eureka Server 发送心跳;
- 定期向 Eureka Server 同步当前实例信息;
- 定期刷新本地服务注册表
如何实现这些功能
知道了 Eureka Client 需要具备哪些功能,接下来我们就从源码的角度来看看怎样实现这些功能。
和之前一样,我更多的会从设计的层面来分析,而不会顺序地去看每个过程的代码,即重设计、轻实现。如果对源码细节有疑问的,可以交流学习下。
那么,还是从一个 UML 图开始吧。有了它,相信大家看源码时会更轻松一些。
通过这个图,我们再来看 Eureka Client 的几个功能:
- 注册当前实例到 Eureka Server;--初始化
DiscoveryClient
时就会注册上去。 - 获取 Eureka Server 的服务注册表;--通过
DiscoveryClient
获取。 - 定期向 Eureka Server 发送心跳;--通过
HeartbeatThread
任务实现。 - 定期向 Eureka Server 同步当前实例信息;--通过
InstanceInfoReplicator
任务实现。 - 定期刷新本地服务注册表;--通过
CacheRefreshThread
任务实现。
我们拿Eureka详解系列(二)--如何使用Eureka(原生API,无Spring) 中的例子来分析下整个过程。
// 创建ApplicationInfoManager对象
ApplicationInfoManager applicationInfoManager = new ApplicationInfoManager(
new MyDataCenterInstanceConfig(), new EurekaConfigBasedInstanceInfoProvider(instanceConfig).get());
// 创建EurekaClient对象,这个时候完成了几件事:
// 1. 注册当前实例到Eureka Server(实例的初始状态一般是STARTING);
// 2. 开启心跳、刷缓存、同步实例信息的定时任务;
// 3. 注册状态监听器到ApplicationInfoManager(不然后面的setInstanceStatus不会生效的)
EurekaClient eurekaClient = new DiscoveryClient(applicationInfoManager, new DefaultEurekaClientConfig());
// 设置当前实例状态为STARTING(原状态也是STARTING,所以这一句没什么用)
applicationInfoManager.setInstanceStatus(InstanceInfo.InstanceStatus.STARTING);
// 设置当前实例状态为UP触发(监听器触发,执行InstanceInfoReplicator的任务)
applicationInfoManager.setInstanceStatus(InstanceInfo.InstanceStatus.UP);
// 和application client交互
// ······
// 关闭客户端,同时也会注销当前实例
eurekaClient.shutdown();
我们会发现,DiscoveryClient
初始化化时做了非常多的事情,核心的源码都在它的构造方法里,大家感兴趣的可以自行阅读。
这里提醒下,Eureka 的定时任务有点奇怪,它不是完全交给ScheduledExecutorService
来调度,举个例子,ScheduledExecutorService
只会按设定的延迟执行一次心跳任务,然后就不执行了,之所以能够实现定时调度,是因为心跳任务里又提交了一次任务,代码如下:
public void run() {
try {
// ······
} finally {
// ······
if (!scheduler.isShutdown()) {
scheduler.schedule(this, delay.get(), TimeUnit.MILLISECONDS);
}
}
}
Eureka Client的配置详解
回顾下Eureka详解系列(三)--探索Eureka强大的配置体系的内容,在 Eureka 里,配置分成了三种:
- EurekaInstanceConfig:当前实例身份的配置信息,即我是谁?
- EurekaServerConfig:一些影响当前Eureka Server和客户端或对等节点交互行为的配置信息,即怎么交互?
- EurekaClientConfig:一些影响当前实例和Eureka Server交互行为的配置信息,即和谁交互?怎么交互?
这里我们来讲讲EurekaInstanceConfig
和EurekaClientConfig
的配置参数。
EurekaInstanceConfig--我是谁?
这些参数大部分用来向 Eureka Server 表明当前实例的身份,但我们会发现,这里混进了两个“异类”--lease.renewalInterval 和 lease.duration,这个不应该放在EurekaClientConfig
里吗?
我一开始也不明白,后来发现很重要的一点,EurekaClientConfig
的参数只能影响当前实例,而不能影响 Eureka Server,它的信息不能向 Eureka Server 传递,而EurekaInstanceConfig
的就可以,所以,除了表明实例的身份,EurekaInstanceConfig
还有另外一个功能,就是向 Eureka Server 传递某些重要的交互参数。
# 同一个服务下存在多个实例,这个可以作为唯一标识区分它们。默认为当前实例的主机名
eureka.instanceId=zzs
# 服务名。默认unknown
eureka.name=SampleService
# 当前实例开放服务的端口,默认80
eureka.port=8001
# 当前实例多久向Eureka Server发送一次心跳,单位秒。默认30s
eureka.lease.renewalInterval=30
# 如果没收到心跳,Eureka Server隔多久将当前实例剔除,单位秒。默认90s
eureka.lease.duration=90
# 当前实例的虚拟主机名,通过这个可以直接访问到当前实例。默认:当前主机名+port
eureka.vipAddress=sampleservice.zzs.cn
# 绑定在当前实例的一些自定义信息,它们会被放在一个map里,其他Eureka Client可以拿来用。默认是一个空map
eureka.metadata.name=zzs
eureka.metadata.age=18
# 这几个一般不用,我就不展开了
eureka.appGroup=unknown
#eureka.asgName=
eureka.traffic.enabled=false
eureka.port.enabled=true
eureka.securePort=443
eureka.securePort.enabled=false
eureka.secureVipAddress=zzs:443
eureka.statusPageUrlPath=/Status
eureka.statusPageUrl=http://zzs:8001/Status
eureka.homePageUrlPath=/
eureka.homePageUr=http://zzs:8001/
eureka.healthCheckUrlPath=/healthcheck
eureka.healthCheckUrl=http://zzs:8001/healthcheck
eureka.secureHealthCheckUrl=https://zzs:443/healthcheck
EurekaClientConfig--和谁交互?怎么交互?
关于 Eureka Server 集群的配置,有三种方法:
- 在 serviceUrl 中写死 Eureka Server 的 IP,缺点就是每次增加、删除、更改机器都要更改配置;
- 在 serviceUrl 中配置 Eureka Server 对应的 EIP,更改机器时不需要更改,但是增加、删除机器都要更改配置;
- 采用 DNS 配置 Eureka Server 的 IP,增加、删除、更改机器都不需要更改配置。
这里还涉及到 region、zone 的概念,可以理解为:region 表示机器部署在不同的城市,zone 表示机器部署在同一个城市的不同机房里。默认情况下,Eureka Client 会优先选择自己所属 region 的 Eureka Server 来访问。
# 当前实例多久同步一次本地注册表,单位秒。默认30s
eureka.client.refresh.interval=30
# 当前实例多久同步一次实例信息,单位秒。默认30s
eureka.appinfo.replicate.interval=30
# 当前实例是否注册到Eureka Server。默认true
eureka.registration.enabled=true
# 当前实例是否需要从Eureka Server获取服务注册表
eureka.shouldFetchRegistry=true
# 当前实例可以和哪些region的Eureka Server交互
eureka.fetchRemoteRegionsRegistry=beijing,shanghai
# 当前实例所在的region
eureka.region=beijing
# region下有哪些zone
eureka.beijing.availabilityZones=zone-1,zone-2
eureka.shanghai.availabilityZones=zone-3
# zone下有哪些Eureka Server(这种配置可以通过EIP来避免写死IP,但扩展时还是要改,推荐使用DNS的方式)
eureka.serviceUrl.zone-1=http://ec2-552-627-568-165.compute-1.amazonaws.com:7001/eureka/v2/,http://ec2-368-101-182-134.compute-1.amazonaws.com:7001/eureka/v2/
eureka.serviceUrl.zone-2=http://ec2-552-627-568-170.compute-1.amazonaws.com:7001/eureka/v2/
eureka.serviceUrl.zone-3=http://ec2-500-179-285-592.compute-1.amazonaws.com:7001/eureka/v2/
# 当我们使用DNS配置serviceUrl时需要用到的配置(非常推荐使用,可以避免写死IP,且方便扩展)
eureka.shouldUseDns=true
eureka.eurekaServer.domainName=sampleservice.zzs.cn
eureka.eurekaServer.port=8001
eureka.eurekaServer.context=eureka/v2
# 这几个一般不用,我就不展开了
eureka.preferSameZone=true
eureka.appinfo.initial.replicate.time=40
eureka.serviceUrlPollIntervalMs=300
eureka.client.heartbeat.threadPoolSize=5
eureka.client.heartbeat.exponentialBackOffBound=10
eureka.client.cacheRefresh.threadPoolSize=5
eureka.client.cacheRefresh.exponentialBackOffBound=10
#eureka.eurekaServer.proxyHost=
#eureka.eurekaServer.proxyPort=
#eureka.eurekaServer.proxyUserName=
#eureka.eurekaServer.proxyPassword=
eureka.eurekaServer.gzipContent=true
eureka.eurekaServer.readTimeout=8
eureka.eurekaServer.connectTimeout=5
eureka.eurekaServer.maxTotalConnections=200
eureka.eurekaServer.maxConnectionsPerHost=50
eureka.eurekaserver.connectionIdleTimeoutInSeconds=45
#eureka.backupregistry=
eureka.shouldEnforceRegistrationAtInit=false
eureka.shouldEnforceFetchRegistryAtInit=false
eureka.shouldUnregisterOnShutdown=true
eureka.shouldFilterOnlyUpInstances=true
eureka.shouldOnDemandUpdateStatusChange=true
eureka.allowRedirects=true
eureka.printDeltaFullDiff=true
eureka.disableDelta=false
eureka.registryRefreshSingleVipAddress=false
eureka.dollarReplacement=_-
eureka.escapeCharReplacement=__
#eureka.encoderName=
#eureka.decoderName=
eureka.clientDataAccept=full
eureka.experimental.clientTransportFailFastOnInit=true
以上比较宏观地讲完了 Eureka Client 的源码和配置,感谢您的阅读。
参考资料
https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance
本文为原创文章,转载请附上原文出处链接:https://www.cnblogs.com/ZhangZiSheng001/p/14381169.html
Eureka详解系列(四)--Eureka Client部分的源码和配置的更多相关文章
- Eureka详解系列(五)--Eureka Server部分的源码和配置
简介 按照原定的计划,我将分三个部分来分析 Eureka 的源码: Eureka 的配置体系(已经写完,见Eureka详解系列(三)--探索Eureka强大的配置体系): Eureka Client ...
- Eureka详解系列(二)--如何使用Eureka(原生API,无Spring)
简介 通过上一篇博客 Eureka详解系列(一)--先谈谈负载均衡器 ,我们知道了 Eureka 是什么以及为什么要使用它,今天,我们开始研究如何使用 Eureka. 在此之前,先说明一点.网上几乎所 ...
- 详解Mybatis拦截器(从使用到源码)
详解Mybatis拦截器(从使用到源码) MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能. 本文从配置到源码进行分析. 一.拦截器介绍 MyBatis 允许你在 ...
- Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...
- Scala 深入浅出实战经典 第60讲:Scala中隐式参数实战详解以及在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Mybatis源码详解系列(四)--你不知道的Mybatis用法和细节
简介 这是 Mybatis 系列博客的第四篇,我本来打算详细讲解 mybatis 的配置.映射器.动态 sql 等,但Mybatis官方中文文档对这部分内容的介绍已经足够详细了,有需要的可以直接参考. ...
- Eureka详解系列(一)--先谈谈负载均衡器
这个系列开始研究 Eureka,在此之前,先来谈谈负载均衡器. 本质上,Eureka 就是一个负载均衡器,可能有的人会说,它是一个服务注册中心,用来注册服务的,这种说法不能说错,只是有点片面. 在这篇 ...
- Eureka详解系列(三)--探索Eureka强大的配置体系
简介 通过前面的两篇博客,我们知道了:什么是 Eureka?为什么使用 Eureka?如何适用 Eureka?今天,我们开始来研究 Eureka 的源码,先从配置部分的源码开始看,其他部分后面再补充. ...
- 深入浅出Mybatis系列(三)---配置详解之properties与environments(mybatis源码篇)
上篇文章<深入浅出Mybatis系列(二)---配置简介(mybatis源码篇)>我们通过对mybatis源码的简单分析,可看出,在mybatis配置文件中,在configuration根 ...
随机推荐
- java使用正则的例子
package com.accord.util; import java.util.ArrayList; import java.util.List; import java.util.regex.M ...
- VMware虚拟机安装黑群晖DSM6.2 (转)
安装DSM6.2.和安装5.1的过程大致相同,只是在虚拟机的配置时有所不同. 需要用到的工具 Roadkil's Disk Image – 写镜像工具:http://www.roadkil.net/p ...
- C# 中的 null 包容运算符 “!” —— 概念、由来、用法和注意事项
在 2020 年的最后一天,博客园发起了一个开源项目:基于 .NET 的博客引擎 fluss,我抽空把源码下载下来看了下,发现在属性的定义中,有很多地方都用到了 null!,如下图所示: 这是什么用法 ...
- Windows下如何玩转火热的go-zero
作者:阿啄debugIT 前言 go-zero 是一个集成了各种工程实践的 web 和 rpc 框架.通过弹性设计保障了大并发服务端的稳定性,经受了充分的实战检验. go-zero 包含极简的 API ...
- 配置 Docker 镜像加速源地址
docker 安装官方文档 根据实例的操作系统类型,参考相应的文档进行安装. 查看 linux 是 CentOS 还是 Ubuntu uname -a #查看系统信息 lsb_release -a # ...
- 【Redis】Redis基础 - Redis安装启动测试
Redis基本 - 安装 文章目录 Redis基本 - 安装 Linux下安装Redis Docker 方式 Github 源码编译方式 直接安装方式 Windows下Redis安装 记录 - Red ...
- kubernets之控制器之间的协作以及网络
一 创建一个deployment的时候整个kubernets集群的资源和事件的调用链 1.1 创建一个deployment的资源,在提交的时候,集群中的调度器,控制器以及node节点上kubele ...
- P2024 [NOI2001]食物链(种类并查集)
题目链接: https://www.luogu.org/problemnew/show/P2024 题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 ...
- pscp 从win10远程传输文件到centos7,多个虚拟机之间传文件
一.将下载的pscp.exe拷贝到C:\Windows\System32 上传文件 win10 --> linux1 C:\Users\xy>pscp C:\BaiduNetdiskDow ...
- 超精讲-逐例分析 CSAPP:实验2-Bomb!(下)
好了话不多说我们书接上文继续来做第二个实验下面是前半部分实验的连接 5. 第五关 首先感觉应该是个递归问题 /* Round and 'round in memory we go, where we ...