eureka源码--服务的注册、服务续约、服务发现、服务下线、服务剔除、定时任务以及自定义注册中心的思路
微服务注册后,在注册中心的注册表结构是一个map: ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry,假如一个order服务部署了三台机器,那么Map的第一个key为服务名称,第二个map的key是实例编号(instance-id),
InstanceInfo该对象封装了服务的主要信息,例如ip 端口 服务名称 服务的编号等:
如图:

一、服务的注册
1.客户端源码(DiscoveryClient类里面):

2.服务端的源码(AbstractInstanceRegistry类):


二、服务的续约
1.客户端源码(DiscoveryClient类里面):通过发送心跳进行续约,告诉注册中心我还活着

2.服务端的源码(AbstractInstanceRegistry类):


三、服务的下线(客户端关闭时,主动发送消息给注册中心,注册中心从注册表中将该服务实例删除)
1.客户端源码(DiscoveryClient类里面):



2.服务端的源码(AbstractInstanceRegistry类):

四、服务的剔除:当注册中心服务器一直收不到客户端的心跳续约超过一定时间限制时,注册中心会将该服务从注册表中剔除,该功能只存在注册中心
注册中心源码(AbstractInstanceRegistry类):

五、服务的发现:客户端要向注册中心拉取注册列表
1.客户端源码(DiscoveryClient类里面):

1.1全量拉取:



1.2 增量拉取



2.服务端的源码(AbstractInstanceRegistry类):
2.1 注册中心全量拉取:



2.2 增量拉取:

六 、定时器
1.客户端会定时向注册中心发送心跳进行续约以及定时去注册中心拉取最新的注册列表信息
客户端源码(DiscoveryClient类的构造器里):省略部分无关代代码:
@Inject
DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
Provider<BackupRegistry> backupRegistryProvider, EndpointRandomizer endpointRandomizer) {
//此处省略了部分代码
try {
//创建一个线程调度器
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 //此处省略部分无关代码
initScheduledTasks(); //调用该方法,该方法会执行对应的线程池 }
*/
private void initScheduledTasks() {
if (clientConfig.shouldFetchRegistry()) {
// registry cache refresh timer
int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds();
int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound();
cacheRefreshTask = new TimedSupervisorTask(
"cacheRefresh",
scheduler,
cacheRefreshExecutor,
registryFetchIntervalSeconds,
TimeUnit.SECONDS,
expBackOffBound,
new DiscoveryClient.CacheRefreshThread() //该方法里面会调用拉取注册表的方法
);
scheduler.schedule(
cacheRefreshTask,
registryFetchIntervalSeconds, TimeUnit.SECONDS); //开启定时任务
} if (clientConfig.shouldRegisterWithEureka()) {
int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs();
int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound();
logger.info("Starting heartbeat executor: " + "renew interval is: {}", renewalIntervalInSecs); // Heartbeat timer
heartbeatTask = new TimedSupervisorTask(
"heartbeat",
scheduler,
heartbeatExecutor,
renewalIntervalInSecs,
TimeUnit.SECONDS,
expBackOffBound,
new HeartbeatThread();//该线程会去调用发送心跳方法
);
scheduler.schedule(
heartbeatTask,
renewalIntervalInSecs, TimeUnit.SECONDS); //开启心跳定时任务
//此处省略部分无关代码
}
//拉取注册列表的线程:

//发送心跳的线程:

2. 注册中心服务剔除定时器(注册中心源码(AbstractInstanceRegistry类))


总结:eureka注册中心是去化的,注册表是存在内存中的,并且客户端拉取一份注册表后,会存在本地缓存中,因此即使注册中心挂了,一样不影响客户端相互调用
附加: 客户端如何获取服务实例demo


综上所述,其实我们也可以自己写个简单的注册中心,思路如下:
1.创建一个springboot项目,写个controller类,提供注册,续约,下线,获取服务列表四个接口
2. 定义一个实例对象Instance,该对象封装ip,端口 还有更新时间
3.客户端调用注册接口,将Instance作为参数传过来,注册中心取到对应实例,存到Map<String,Map<String,Instance>> 中
4.客户端弄个定时器,每个一段时间,调用注册中心的续约方法,将更新实例的修改时间
5.客户端弄个定时器,每隔一段时间向注册中心拉取服务,其实就是拉取Map<String,Map<String,Instance>>
6.注册中心弄个定时器,每隔一段时间遍历Map<String,Map<String,Instance>>,找出每个实例中的更新时间,加上过期时间,然后跟当前时间比较,看看有没过期,如果过期就剔除,也就是在map中删除
eureka源码--服务的注册、服务续约、服务发现、服务下线、服务剔除、定时任务以及自定义注册中心的思路的更多相关文章
- Spring Cloud Eureka源码分析之服务注册的流程与数据存储设计!
Spring Cloud是一个生态,它提供了一套标准,这套标准可以通过不同的组件来实现,其中就包含服务注册/发现.熔断.负载均衡等,在spring-cloud-common这个包中,org.sprin ...
- 【SpringCloud Eureka源码】从Eureka Client发起注册请求到Eureka Server处理的整个服务注册过程(下)
目录 一.Spring Cloud Eureka Server自动配置及初始化 @EnableEurekaServer EurekaServerAutoConfiguration - 注册服务自动配置 ...
- 【一起学源码-微服务】Nexflix Eureka 源码六:在眼花缭乱的代码中,EurekaClient是如何注册的?
前言 上一讲已经讲解了EurekaClient的启动流程,到了这里已经有6篇Eureka源码分析的文章了,看了下之前的文章,感觉代码成分太多,会影响阅读,后面会只截取主要的代码,加上注释讲解. 这一讲 ...
- 微服务之SpringCloud实战(四):SpringCloud Eureka源码分析
Eureka源码解析: 搭建Eureka服务的时候,我们会再SpringBoot启动类加上@EnableEurekaServer的注解,这个注解做了一些什么,我们一起来看. 点进@EnableEure ...
- 【一起学源码-微服务】Nexflix Eureka 源码十:服务下线及实例摘除,一个client下线到底多久才会被其他实例感知?
前言 前情回顾 上一讲我们讲了 client端向server端发送心跳检查,也是默认每30钟发送一次,server端接收后会更新注册表的一个时间戳属性,然后一次心跳(续约)也就完成了. 本讲目录 这一 ...
- 【一起学源码-微服务】Nexflix Eureka 源码十一:EurekaServer自我保护机制竟然有这么多Bug?
前言 前情回顾 上一讲主要讲了服务下线,已经注册中心自动感知宕机的服务. 其实上一讲已经包含了很多EurekaServer自我保护的代码,其中还发现了1.7.x(1.9.x)包含的一些bug,但这些问 ...
- 【一起学源码-微服务】Nexflix Eureka 源码十二:EurekaServer集群模式源码分析
前言 前情回顾 上一讲看了Eureka 注册中心的自我保护机制,以及里面提到的bug问题. 哈哈 转眼间都2020年了,这个系列的文章从12.17 一直写到现在,也是不容易哈,每天持续不断学习,输出博 ...
- 【一起学源码-微服务】Nexflix Eureka 源码十三:Eureka源码解读完结撒花篇~!
前言 想说的话 [一起学源码-微服务-Netflix Eureka]专栏到这里就已经全部结束了. 实话实说,从最开始Eureka Server和Eureka Client初始化的流程还是一脸闷逼,到现 ...
- 【一起学源码-微服务】Nexflix Eureka 源码二:EurekaServer启动之配置文件加载以及面向接口的配置项读取
前言 上篇文章已经介绍了 为何要读netflix eureka源码了,这里就不再概述,下面开始正式源码解读的内容. 如若转载 请标明来源:一枝花算不算浪漫 代码总览 还记得上文中,我们通过web.xm ...
随机推荐
- ElasticSearch生命周期管理-索引策略配置与操作
概述 本文是在本人学习研究ElasticSearch的生命周期管理策略时,发现官方未提供中文文档,有的也是零零散散,此文主要是翻译官方文档Policy phases and actions模块. 注: ...
- 淘宝ios端弹窗-2020年3月25日
- android MVVM(1)用LiveData关联VM 与 V
1.官方文档 MVVM 官方文档: https://developer.android.com/jetpack/docs/guide ViewModel 文档: https://developer.a ...
- HDU - 1019-Least Common Multiple(求最小公倍数(gcd))
The least common multiple (LCM) of a set of positive integers is the smallest positive integer which ...
- 答应我,用了这个jupyter插件,别再重复造轮子了
1 简介 在使用Python.R等完成日常任务的过程中,可能会经常书写同样或模式相近的同一段代码,譬如每次使用matplotlib绘制图像的时候可以在开头添加下面两行代码来解决中文乱码等显示问题: p ...
- webstorm编写vue、react 将大驼峰组件命名转换成短横杠命名
大家好!我是木瓜太香,精通 webstorm 与常见前端技术的工程师,偶尔也在b站搞一些 webstorm 技巧教学,今天给大家带来的是大驼峰小驼峰快速转换短横杠命名或者下划线命名的方式. 开发中我们 ...
- JVM学习第三天(JVM的执行子系统)之类加载机制补充
昨晚没看完,今天继续 系统的类加载器 对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间.这句话可以表达得更通俗一些: ...
- 异步(async)编程
思考:为什么要使用异步编程? 我们先看看同步方法和异步方法之前在程序中执行的逻辑: 1. 同步方法 static void Main(string[] args) { Console.WriteLin ...
- ElasticsSearch初装 环境Win10
步骤: 1.从 http://how2j.cn/frontdownload?bean.id=1694 下载6.22 版本 2.双击elasticsearch.bat启动ElasticsSearch [ ...
- wfuzz 安装
wfuzz 安装 win10 下的wfuzz安装 fuzz下载 https://github.com/xmendez/wfuzz 安装遇到的问题 0x1报错 解决方法: 更新pip python -m ...