【深入理解SpringCloud微服务】深入理解Eureka核心原理

深入理解Eureka核心原理

  • Eureka整体设计
  • Eureka服务端启动
  • Eureka三级缓存
  • Eureka客户端启动

Eureka整体设计

Eureka是一个经典的注册中心,通过http接收客户端的服务发现和服务注册请求,使用内存注册表保存客户端注册上来的实例信息。

Eureka服务端接收的是http请求,通过ApplicationResource接收服务注册请求,通过ApplicationsResource接收服务发现请求,这两个类相当于Spring MVC中的Controller,Eureka使用的不是Spring MVC,而是Jersey,我们直接把他们当成Controller即可。

然后Eureka用一个内存实例注册表PeerAwareInstanceRegistry保存服务提供者注册上来的实例信息,当ApplicationResource接收到服务注册请求时,会把服务实例信息存入PeerAwareInstanceRegistry;当ApplicationsResource接收到服务发现请求时,会从PeerAwareInstanceRegistry拉取服务实例信息返回给客户端

在这里插入图片描述

public class ApplicationsResource {private final PeerAwareInstanceRegistry registry;...
}
public class ApplicationResource {private final PeerAwareInstanceRegistry registry;...
}

Eureka服务端启动

Eureka服务端启动时会初始化PeerAwareInstanceRegistry接口的实现类以及其他核心类,除了初始化PeerAwareInstanceRegistry等一些核心类之外,还会做两件事:

  1. 从集群中的其他Eureka拉取服务实例列表,注册到自己本地的服务注册表
  2. 开启服务剔除定时任务,定时扫描超过一定期限没有续约的服务实例,把它剔除出内存注册表

在这里插入图片描述

初始化PeerAwareInstanceRegistry的代码在EurekaServerAutoConfiguration中,通过@Bean往Spring容器注册一个InstanceRegistry对象,这个InstanceRegistry就是peerAwareInstanceRegistry的实现类。

	@Beanpublic PeerAwareInstanceRegistry peerAwareInstanceRegistry(ServerCodecs serverCodecs) {...return new InstanceRegistry(...);}

EurekaServerAutoConfiguration还会通过@Import注解导入一个EurekaServerInitializerConfiguration,这个EurekaServerInitializerConfiguration的start()方法会触发集群同步和启动服务剔除定时任务。

	@Overridepublic void start() {new Thread(new Runnable() {@Overridepublic void run() {try {// EurekaServerAutoConfiguration导入的EurekaServerBootstrap// 启动Eureka服务eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);...}catch (...) {...}}}).start();}
	public void contextInitialized(ServletContext context) {try {//初始化Eureka运行环境initEurekaEnvironment();//初始化Eureka服务上下文initEurekaServerContext();...}catch (...) {...}}

重点是initEurekaServerContext()方法:

protected void initEurekaServerContext() throws Exception {...// 集群同步(从集群中的其他Eureka实例拉取服务实例列表)int registryCount = this.registry.syncUp();// 启动服务提测定时任务this.registry.openForTraffic(this.applicationInfoManager, registryCount);...}

Eureka三级缓存

Eureka处理服务发现请求时,其实并不是直接读取内存注册表的,而是读的缓存。Eureka除了内存注册表以外,还有两个缓存,一个是读写缓存readWriteCacheMap,一个是只读缓存readOnlyCacheMap。内存注册表、readWriteCacheMap、readOnlyCacheMap三个组成了Eureka的三级缓存。其中readWriteCacheMap和readOnlyCacheMap被包装在一个ResponseCache对象中。整个三级缓存的结果就是这样:

在这里插入图片描述

public class PeerAwareInstanceRegistryImpl extends AbstractInstanceRegistry implements PeerAwareInstanceRegistry {...
}
public abstract class AbstractInstanceRegistry implements InstanceRegistry {...protected volatile ResponseCache responseCache;...

当ApplicationsResource接收到服务发现请求时:

  1. 先从只读缓存中取
  2. 如果只读缓存中没有,则从读写缓存获取并且回写只读缓存
  3. 如果读写缓存中也没有,则从内存注册表中获取并回写到读写缓存。

Eureka会开启一个定时任务,每隔30s从读写缓存同步数据到只读缓存。

在这里插入图片描述

ResponseCacheImpl#getValue:

    Value getValue(final Key key, boolean useReadOnlyCache) {Value payload = null;try {if (useReadOnlyCache) {// 从只读缓存取final Value currentPayload = readOnlyCacheMap.get(key);if (currentPayload != null) {payload = currentPayload;} else {// 只读缓存没有,则从读写缓存取,回写只读缓存payload = readWriteCacheMap.get(key);readOnlyCacheMap.put(key, payload);}} else {payload = readWriteCacheMap.get(key);}} catch (...) {...}return payload;}

readWriteCacheMap的类型是LoadingCache,LoadingCache是Guava库提供的一个本地缓存实现。当LoadingCache缓存缺失时,LoadingCache会触发CacheLoader的load方法,加载数据到缓存中,此时就会从内存注册表中加载数据到readWriteCacheMap中。关于LoadingCache的使用、作用、原理等知识,可以参考讲解Guava缓存相关的资料。

当ApplicationResource接收到服务注册请求时,会把服务实例信息写入内存注册表,并失效掉读写缓存,然后把新注册上来的实例信息异步同步到集群中的其他Eureka节点。

在这里插入图片描述

PeerAwareInstanceRegistryImpl#register

    @Overridepublic void register(final InstanceInfo info, final boolean isReplication) {...super.register(info, leaseDuration, isReplication);// 同步到集群中的其他Eureka节点replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, null, isReplication);}

AbstractInstanceRegistry#register:

    public void register(InstanceInfo registrant, ...) {try {...// 失效读写缓存invalidateCache(registrant.getAppName(), registrant.getVIPAddress(), registrant.getSecureVipAddress());...} finally {...}}private void invalidateCache(String appName, @Nullable String vipAddress, @Nullable String secureVipAddress) {// invalidate cacheresponseCache.invalidate(appName, vipAddress, secureVipAddress);}

Eureka客户端启动

Eureka的客户端启动时会创建一个DiscoveryClient对象,它是Eureka的客户端对象,它会创建两个定时任务,一个异步延时任务。

两个定时任务:

  1. 定时拉取服务实例列表(服务发现
  2. 定时发送心跳(服务续约

一个延时任务:服务注册

DiscoveryClient的构造方法:

    @InjectDiscoveryClient(...) {...initScheduledTasks();...}

DiscoveryClient#initScheduledTasks

    private void initScheduledTasks() {if (clientConfig.shouldFetchRegistry()) {...// 开启服务发现定时任务scheduler.schedule(new TimedSupervisorTask(...new CacheRefreshThread()),registryFetchIntervalSeconds, TimeUnit.SECONDS);}if (clientConfig.shouldRegisterWithEureka()) {...// 开启服务续约(定时发送心跳)定时任务scheduler.schedule(new TimedSupervisorTask(...new HeartbeatThread()),renewalIntervalInSecs, TimeUnit.SECONDS);instanceInfoReplicator = new InstanceInfoReplicator(...);...// 服务注册instanceInfoReplicator.start(...);} else {...}}

它们都是通过Jersey客户端向Eureka服务端发起http请求。

其中服务发现的定时任务在首次拉取是会全量拉取,后续会进行增量拉取。增量拉取返回的服务实例列表会合并到Eureka客户端的本地缓存中,然后根据本地缓存的服务实例列表计算一个hashCode,与Eureka服务端返回的hashCode进行比较,如果不一致,还要再进行一次全量拉取。

在这里插入图片描述

以上就是Eureka全部的核心原理,下面放一张源码图,对源码有兴趣的可以跟一跟,没有兴趣的可以直接忽略。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/47958.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FPGA-ROM IP核的使用

1.理论 ROM全称:Read-Only Memory,也就是只读型固态半导体存储器,即一旦存储信息,无法再改变,信息也不会因为电源关闭消失。但在FPGA中,实际使用的ROM IP核并不是真正的ROM,其实都是内部的RAM资…

spring security如何适配盐存在数据库中的密码

19.token认证过滤器代码实现_哔哩哔哩_bilibili19.token认证过滤器代码实现是SpringSecurity框架教程-Spring SecurityJWT实现项目级前端分离认证授权-挑战黑马&尚硅谷的第20集视频,该合集共计41集,视频收藏或关注UP主,及时了解更多相关视…

24年支付行业概况与未来

​ 一、行业背景介绍 支付行业作为现代金融体系的基石,正经历着前所未有的变革。随着科技的发展和人们对便捷支付方式的需求不断提高,支付行业在近年来得到了迅猛发展。在我国,支付行业经过多年的发展和市场竞争,已经形成了多元化…

Navicat 17 新特性 | Navicat BI 功能革新升级,助力企业深度挖掘数据潜能

随着 Navicat 17 的发布,在业界引起了广泛的共鸣与热议。我们曾深入剖析其众多革新特性,包括模型设计创新与优化、高效的查询与配置、用户界面交互体验再升级,原生适配国产平台和操作系统和数据字典提升数据结构清晰度,这些新特性…

【第12章】Spring Cloud之集成 Spring Cloud Gateway

文章目录 前言一、新建项目1. 项目结构2. 引入依赖3. 启动类4. 基本配置 二、新建配置三、新建服务1. 提供者2. 消费者 四、单元测试1. 启动网关服务2. 提供者3. 消费者 总结 前言 Spring Cloud Gateway是一个基于Spring Framework 5、Spring Boot 2和Project Reactor等技术构…

python的csv库常用操作

csv 模块是 Python 标准库中的一个模块,用于处理 CSV(逗号分隔值)文件。它提供了简单易用的功能来读取和写入 CSV 文件。以下是一些常用的操作: 一、读取 CSV 文件 新建文件data.csv,内容如下: 使用 csv.…

浪潮自研交换机系列常见问题处理

CN61108PC-V-H 不能PING通任何地址,也不能被PING 输入ip traceroute enable既可。注意视图 交换机通过console口远程登录至其他交换机,掉线后console口无法使用 例如有2台交换机A和B,在A交换机上插上console线登录后,在A通过SSH…

nodejs安装及环境配置建材商城管理系统App

✌网站介绍:✌10年项目辅导经验、专注于计算机技术领域学生项目实战辅导。 ✌服务范围:Java(SpringBoo/SSM)、Python、PHP、Nodejs、爬虫、数据可视化、小程序、安卓app、大数据等设计与开发。 ✌服务内容:免费功能设计、免费提供开题答辩P…

如何应对Android面试官 -> 常用数据结构如何进行优化

前言 本章我们开始讲解性能优化相关的话题,首先我们来看下数据结构如何优化: 性能优化 性能优化的本质:线上 APM 的性能监控,而性能监控通常是以下技术点 ByteCode、Hook(PLT Hook)、JS注入(采…

tslib 库-I.MX6U嵌入式Linux C应用编程学习笔记基于正点原子阿尔法开发板

tslib 库 tslib 简介 tslib 库,这是 Linux 系统下,专门为触摸屏开发的应用层函数库,开源 功能与作用:作为触摸屏驱动和应用层之间的适配层,封装了读取和解析触摸屏数据的复杂过程,提供API接口 数据处理&…

c++ 高精度加法(只支持正整数)

再给大家带来一篇高精度,不过这次是高精度加法!话不多说,开整! 声明 与之前那篇文章一样,如果看起来费劲可以结合总代码来看 定义 由于加法进位最多进1位,所以我们的结果ans[]的长度定义为两个加数中最…

零基础学SpringBoot(一)--初识SpringBoot

1. SpringBoot简介 SpringBoot 是Spring家族中的一个全新的框架,它用来简化Spring应用程序的创建和开发过程,也可以说Spring Boot能简化我们之前采用SSM(SpringMVC Spring MyBatis)框架进行开发的过程。 以前我们采用SSM框架进行开发的时候&#xff0c…

vue3前端开发-小兔鲜项目-二级分类页面无限加载的实现

vue3前端开发-小兔鲜项目-二级分类页面无限加载的实现!实际的项目开发中,经常会遇到这需求。产品内容庞大,但是用户不可能一次性全部都加载请求的。当客户向下滚动,触碰到插件的底部时,会再次申请下一页内容。这样就会…

Adobe国际认证详解-动漫制作专业就业方向和前景

动漫制作专业的就业方向和前景随着创意产业的蓬勃发展而愈发广阔。这一专业涵盖了从角色设计、场景绘制到动画制作、特效合成等多个环节,是创意与技术相结合的典型代表。随着数字媒体和互联网的普及,动漫制作专业人才的需求正不断增长,为该专…

2024 杭电多校第一场

目录 目录 树 博弈 传送 树 给一棵根为 1 的有根树,点 i 具有一个权值 Ai 。 定义一个点对的值 f(u,v)max(Au,Av)|Au−Av| 。 你需要对于每个节点 i ,计算 ansi∑u∈subtree(i),v∈subtree(i)f(u,v) ,其中 subtree(i) 表示 i 的子树。 请…

Vscode离线下载对应版本的ms-python.vsix

一、查看vscode的版本号和发行时间 vscode界面中Help-About查看版本号和发行时间,ms-python的发行时间需要和这个时间相近: 二、在github仓库中查看ms-python有什么版本,以及发行时间 github仓库路径 https://github.com/microsoft/vsco…

虚幻引擎,体积雾、体积光、镜头泛光

1、体积雾 这里介绍的是用于地面的体积雾效果,效果如图1-1: 图1-1 首先,需要场景中存在指数级高度雾并开启体积雾(如图1-2)。然后创建材质,材质域选择“体积”,混合模式选择“Additive”。材质节…

shell脚本中for循环和while循环

目录 for循环 while 循环 前面说完了if判断语句,现在该来学习shell脚本中的另一个重点内容了,那就是循环语句。循环语句分为 for 循环和 while 循环,二者本质上来说是没有太大区别,但针对不同的情况,使用不同的语句可…

【Git-常用命令】一文搞懂学会git的常用命令以及使用技巧

【Git-常用命令】一文搞懂学会git的常用命令以及使用技巧 本次修炼方法请往下查看 🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地! 🎇 免费获取相关内容文档关注&…

Lua 语法学习笔记

Lua 语法学习笔记 安装(windows) 官网:https://www.lua.org/ 下载SDK 解压&修改名称(去除版本号) 将lua后面的版本号去掉,如lua54.exe->lua.ext 配置环境变量 数据类型 数据类型描述nil这个最简单,只有值n…