Eureka原理剖析
Eureka作为微服务中的注册中心,为微服务集群间各个服务进行调用提供寻址的功能,有了它集群间的服务只需要指定服务名称就可以了,无需再去关心服务具体部署的服务器IP,即可正常调用。下面来对其中我们开发中会接触的主要机制的实现原理进行剖析。一些具体细节这里不做详细的分析,只关注如下2个大方向的东西:1.注册相关的机制、2.客户端和服务端的启动流程。
Eureka服务端启动流程
首先需要说明的是eureka server(后面简称服务端)是在eureka client(后面简称客户端)的基础上进一步封装的一个东西;也就是说客户端有的东西服务端也有。服务端额外多的东西就是对注册表的处理部分。它的启动流程如下:
- 初始化环境配置;这个我们在日常开发中几乎都是使用的默认的;
- 读取服务端的配置信息,也就是读取eureka-server.properties配置文件;由于eureka中对这种配置类采用的是面向接口的方式,因此非常好扩展,在spring中是重新实现了这些配置类接口的。
- 构建应用管理器;读取eureka-client.properties配置文件,选择其中的部分配置,基于构造者模式创建服务实例交给应用管理器。
- 读取eureka-client.properties配置文件构建客户端信息;这里的操作和客户端的启动流程几乎就是一样的,因此这里就不做详细说明了。
- 创建注册表感知器registry,这个也可以称为注册表管理器。这里会维护注册表信息。
- 创建服务端集群节点信息管理器;也就是我们配置的集群地址信息,默认10分钟检查一次。
- 基于上面的信息创建服务端的上下文信息;这里在进行初始化的时候会对相关资源进行初始化;启动相关的定时。
- 从其他服务端节点上拉取注册表信息;这就是为什么服务端即使配置fetchRegistry为false,依然可以正常拿到注册表信息。
- 启动注册表感知器registry的定时;这个定时主要就是检查注册表中是否有过期的注册信息。
- 最后进行监听器的绑定。
相关的流程图如下:
Eureka客户端启动流程
eureka客户端的启动主要就是几个定时和之后进行注册表维护的网络请求资源初始化。
- 构建应用管理器;读取eureka-client.properties配置文件,选择其中的部分配置,基于构造者模式创建服务实例交给应用管理器。
- 读取eureka-client.properties配置信息构建客户端的配置信息;
- 根据上面的配置信息和应用管理器构建客户端;
- 创建心跳、缓存等需要的线程池;
- 创建网络通信组件;后面发送注册信息、心跳信息这些请求都是通过它来处理的;
- 判断是否需要拉取注册表信息,若是则会全量拉取一次注册表信息;
- 启动相关的定时任务:注册表更新任务(默认30s执行一次)、心跳定时任务(默认30s执行一次)、创建服务状态更新定时任务(默认30s执行一次,这个就是留个我们自定义服务上下线状态的判断逻辑的);
- 启动服务状态更新定时任务(第一次延迟40s执行);这里面就是向服务端发送注册信息的实现。
- 最后进行监听器的绑定。
相关的流程图如下:
Eureka注册表的原理
eureka的注册表中保存中服务的注册信息,下面我们通过如下几个点来对其原理进行简析。
注册表抓取和缓存机制
其基本流程图如下:
注册表的数据结构和缓存机制
eureka server中对注册表的信息进行多重缓存,分为:
- 只读缓存(ConcurrentMap):会有定时任务默认每隔30s主动的去和读写缓存里面的信息同步一次;
- 读写缓存(guava的LoadingCache):在创建LoadingCache的时候默认设置的过期时间是180s;
- 注册表:这个就是实时的本地注册信息,每次客户端的注册信息更新后,都会实时的保存在这里;同时在更新它的时候会将读写缓存中的值设置为失效状态。
注册表信息读取流程
注册表的拉取分为全量和增量;在初次拉取时使用的是全量,后面使用的都是增量拉取的。
全量拉取流程:
- 服务端收到客户端的请求后,会直接从只读缓存里面取值,如果有就返回,否则进行下一步;
- 只读缓存里面没有时,会从读写缓存里面取值,如果有就返回,同时将其设置达到只读缓存里面;否则进行下一步;
- 读写缓存里面没有时,会触发LoadingCache的load方法,这里面会从本地注册表中取值返回。
增量拉取流程:
- 服务端收到客户端的请求后,会直接从只读缓存里面取增量信息,如果有就返回,否则进行下一步;
- 只读缓存里面没有时,会从读写缓存里面取增量信息,如果有就返回,同时将其设置达到只读缓存里面;否则进行下一步;
- 读写缓存里面没有时,会触发LoadingCache的load方法,这里面会增量队列中获取变化的信息然后返回;
服务端集群间的注册信息如何同步的
要回答这个问题,我们就需要先了解客户端发送注册信息和心跳信息的整个流程,看了下面的注册和心跳流程这个问题也就可以解释了。
注册的流程来说明:
- 客户端在启动的最后一步启动服务状态更新定时任务时,里面的定时任务就会向服务端发送注册信息;
- 客户端会选从置的服务服务注册地址中选择第一个进行尝试,如果成功后面都会用这个,直到失败才会切换到下一个;
- 服务端收到注册请求后,更新本地注册表中注册信息,将读写缓存中的缓存设置为失效状态;同时将注册表的变更信息保存到最近变更队列中;
- 将注册请求信息转发给eureka server集群中的其他节点。
心跳的请求也是在服务端自己处理完成后,会自动将这个请求转发给集群中的其他节点。心跳的操作就是更新注册信息中的租约时间,这里就不详细说明了。
注意这种通知集群中其他节点的操作在失败后会不断的重试,同时正式由于有这个操作,因此服务端的fetchRegistry配置为false,集群间的注册信息依然可以正常同步的原因。
客户端的注册信息什么时候会被摘除
客户端的注册信息被摘除主要是这2种情况:1.客户端服务主动下线;2.服务异常。
客户端服务主动下线
客户端服务下线:主动取消注册信息,这种服务端直接接收请求然后删除即可;其流程图如下:
服务异常
客户端异常:没有发送取消请求或者是服务端没有正常接收和处理取消请求的情况下,此时就需要服务端自己定制一套注册信息过期机制,这也就是发送心跳的作用。
服务端中注册表信息过期检查的定时任务默认每隔60s检查一次,其大致流程如下:
- 判断的过期的依据是:当前时间戳 > (上一次发送租约的时间戳 + 过期时间(默认90s) + 补充时间(就是距离上一次执行任务的时间超过定时任务配置的60s执行一次的周期时间));但是由于在设置上一次发送租约的时间戳时候额外加上了一个过期时间;因此最终注册表的过期时间就至少是180s。
- 选择15%的过期注册信息,然后调用取消操作来删除注册信息;同时会通知集群中其他的节点。
Eureka源码阅读建议
spring-cloud-eureka中的server和client是对netflix的eureka进行了封装,加了一些注解来对spring boot进行支持。因此在阅读eureka源码时,应该先从netflix eureka开始看起,之后再去查看spring cloud封装的eureka的源码就会轻松许多。eureka源码地址:https://github.com/Netflix/eureka 、spring-cloud-eureka源码地址:https://github.com/spring-cloud/spring-cloud-netflix 。
建议不要直接从github仓库里面去拉取,直接去下载对应版本的压缩包即可。
网上对eureka源码分析的文章有很多,这里推荐2篇写得非常不错的博文:
Eureka原理剖析的更多相关文章
- ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件)
ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件) Startup Class 1.Startup Constructor(构造函数) 2.Configure ...
- ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行
ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行 核心框架 ASP.NET Core APP 创建与运行 总结 之前两篇文章简析.NET Core 以及与 .NET Framew ...
- 【Xamarin挖墙脚系列:Xamarin.IOS机制原理剖析】
原文:[Xamarin挖墙脚系列:Xamarin.IOS机制原理剖析] [注意:]团队里总是有人反映卸载Xamarin,清理不完全.之前写过如何完全卸载清理剩余的文件.今天写了Windows下的批命令 ...
- 【Xamarin 跨平台机制原理剖析】
原文:[Xamarin 跨平台机制原理剖析] [看了请推荐,推荐满100后,将发补丁地址] Xamarin项目从喊口号到现在,好几个年头了,在内地没有火起来,原因无非有三,1.授权费贵 2.贵 3.原 ...
- iPhone/Mac Objective-C内存管理教程和原理剖析
http://www.cocoachina.com/bbs/read.php?tid-15963.html 版权声明 此文版权归作者Vince Yuan (vince.yuan#gmail.com)所 ...
- 【Xamain 跨平台机制原理剖析】
原文:[Xamain 跨平台机制原理剖析] [看了请推荐,推荐满100后,将发补丁地址] Xamarin项目从喊口号到现在,好几个年头了,在内地没有火起来,原因无非有三,1.授权费贵 2.贵 3.原生 ...
- Python字符串原理剖析------万恶的+号
字符串原理剖析pyc文件,执行python代码时,如果导入了其他的.py文件,那么执行过程中会自动生成一个与其同名的.pyc文件,该文件就是python解释器变异之后产生的字节码 PS:代码经过编译可 ...
- MapReduce/Hbase进阶提升(原理剖析、实战演练)
什么是MapReduce? MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算.概念"Map(映射)"和"Reduce(归约)",和他们 ...
- ASP.NET Core 运行原理剖析
1. ASP.NET Core 运行原理剖析 1.1. 概述 1.2. 文件配置 1.2.1. Starup文件配置 Configure ConfigureServices 1.2.2. appset ...
随机推荐
- nginx反向代理、负载均衡以及分布式下的session保持
[前言]部署服务器用到了nginx,相比较于apache并发能力更强,优点也比其多得多.虽然我的项目可能用不到这么多性能,还是部署一个流行的服务器吧! 此篇博文主要学习nginx(ingine x)的 ...
- MySQL:事务机制
为什么需要事务处理? 在执行SQL语句的时候,某些业务要求,一系列操作必须全部执行,而不能仅执行一部分. MySQL5.0后引入了事务机制,MySQL支持几种基本的数据库引擎,并非所有引擎都支持事务处 ...
- powerdesigner 16.6破解版下载,支持hive,数据模型hql导出
powerdesigner 16是一款业内领先的建模工具,是一款开发人员常用的数据库建模工具. 在大数据数据仓库建设过程中,离线数仓往往以hive为基础,但数仓建模过程中老版本不支持hive,这个模型 ...
- 记录mysql查询数据遇到的一个小问题
今天在测试的时候,需要使用mysql对插入的数据进行检验,但是写完查询语句的时候执行会报错.原因很简单,这个表名是order(订单),在MySQL语言中order是用来排序的关键字,原则上讲是不能作为 ...
- docker nacos 集群部署
1.准备机器3台 192.168.101.14 192.168.101.15 192.168.101.16 2.初始化sql(如果我们要搭建集群的话,那么肯定是不能用内嵌的数据库,不然数据无法共享.集 ...
- git的工作管理和基础操作
git的工作管理和基础操作 在本地创建git仓库管理我们的代码 初次使用git,先在本地配置一些基础信息 $ git config -l $ git config --global user.name ...
- 任务3 PHP配置 1. PHP基础配置
查看PHP配置文件得位置 #/ucsr/local/php/bin/php -i |grep -i "loaded configuration file" # cp /usr/lo ...
- POJ_2752 Seek the Name, Seek the Fame 【KMP】
一.题目 POJ2752 二.分析 比较明显的KMP运用. 但是这题不是只找一个,仔细看题后可以发现相当于是在找到最大的满足条件的后缀后,再在这个后缀里面找满足条件的后缀. 可以不断的运用KMP得出答 ...
- 走进docker-初识
什么是Docker容器? 容器是打包代码及其所有依赖项的软件的标准单元,因此应用程序可以从一个计算环境快速可靠地运行到另一个计算环境.Docker容器映像是一个轻量级的,独立的,可执行的软件软件包,其 ...
- Benjio0-Curriculum Learning 2009
Curriculum Learning 2009 核心思想: 相比于随机选取训练样本对模型进行训练,使用由易到难的样本(更加复杂,包含更多信息)训练模型可以取得更好的训练效果. 由于这种训练模式类似于 ...