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原理剖析的更多相关文章

  1. ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件)

    ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件) Startup Class 1.Startup Constructor(构造函数) 2.Configure ...

  2. ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行

    ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行 核心框架 ASP.NET Core APP 创建与运行 总结 之前两篇文章简析.NET Core 以及与 .NET Framew ...

  3. 【Xamarin挖墙脚系列:Xamarin.IOS机制原理剖析】

    原文:[Xamarin挖墙脚系列:Xamarin.IOS机制原理剖析] [注意:]团队里总是有人反映卸载Xamarin,清理不完全.之前写过如何完全卸载清理剩余的文件.今天写了Windows下的批命令 ...

  4. 【Xamarin 跨平台机制原理剖析】

    原文:[Xamarin 跨平台机制原理剖析] [看了请推荐,推荐满100后,将发补丁地址] Xamarin项目从喊口号到现在,好几个年头了,在内地没有火起来,原因无非有三,1.授权费贵 2.贵 3.原 ...

  5. iPhone/Mac Objective-C内存管理教程和原理剖析

    http://www.cocoachina.com/bbs/read.php?tid-15963.html 版权声明 此文版权归作者Vince Yuan (vince.yuan#gmail.com)所 ...

  6. 【Xamain 跨平台机制原理剖析】

    原文:[Xamain 跨平台机制原理剖析] [看了请推荐,推荐满100后,将发补丁地址] Xamarin项目从喊口号到现在,好几个年头了,在内地没有火起来,原因无非有三,1.授权费贵 2.贵 3.原生 ...

  7. Python字符串原理剖析------万恶的+号

    字符串原理剖析pyc文件,执行python代码时,如果导入了其他的.py文件,那么执行过程中会自动生成一个与其同名的.pyc文件,该文件就是python解释器变异之后产生的字节码 PS:代码经过编译可 ...

  8. MapReduce/Hbase进阶提升(原理剖析、实战演练)

    什么是MapReduce? MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算.概念"Map(映射)"和"Reduce(归约)",和他们 ...

  9. ASP.NET Core 运行原理剖析

    1. ASP.NET Core 运行原理剖析 1.1. 概述 1.2. 文件配置 1.2.1. Starup文件配置 Configure ConfigureServices 1.2.2. appset ...

随机推荐

  1. SpringBoot(十一): Spring Boot集成Redis

    1.在 pom.xml 中配置相关的 jar 依赖: <!-- 加载 spring boot redis 包 --> <dependency> <groupId>o ...

  2. DCL之单例模式

    所谓的DCL 就是 Double Check Lock,即双重锁定检查,在了解DCL在单例模式中如何应用之前,我们先了解一下单例模式.单例模式通常分为"饿汉"和"懒汉&q ...

  3. ASP.NET Core扩展库之日志

        上一篇我们对Xfrogcn.AspNetCore.Extensions扩展库功能进行了简单的介绍,从这一篇文章开始,我将逐步介绍扩展库中的核心功能.     日志作为非业务的通用领域基础功能, ...

  4. FreeBSD 发布 2020 年 Q3 季度报告

    FreeBSD 几日前发布 Q3 季度报告,介绍了在过去第三季度里 FreeBSD 完成的工作和相关项目,涉及到架构支持.内核改进.持续集成和驱动程序优化等. 列举部分如下: FreeBSD 基金会目 ...

  5. FreeBSD 入门导言

    →→→→→导言: 导言,这一部分通常也被称作"前言"."导论"."概论"."楔子"."写在前面".& ...

  6. FreeBSD 12.2 阿里云镜像使用说明

    目前直接从阿里云 12.1 升级 12.2 会导致错误.镜像非本人制作.FreeBSD 12.2 阿里云镜像使用说明镜像下载地址: http://t.cn/A6taB5jO修改内容:对 /usr/sr ...

  7. 最简单的JVM内存结构图

    JVM内存结构图 大家好,好几天没有更新了,今天的内容有点多,我们详细介绍下JVM内部结构图,还是和之前一样,案例先行,方便大家理解记忆. /** * @author :jiaolian * @dat ...

  8. AbstractQueuedSynchronizer之AQS

    一.可重入锁 可参考:可重入锁和递归锁 1,定义 指的是同一线程外层函数获得锁后,再进入该线程的内层方法会自动获取锁(前提:锁对象是同一个对象). Java中的ReentranLock(显示锁)和Sy ...

  9. 新的颜色对比度算法-感知对比度算法APCA

    目录 对比度 在控制台查看 插件或网站 感知对比度算法(APCA) APCA Math 原理 js 实现的 SAPC 最后 灵感的源泉来源于不断的接受新鲜事物. Chrome 89 新功能一览,性能提 ...

  10. 面试现场:说说char 和 varchar的区别你了解多少?

    Hi,大家好!我是白日梦!本文是MySQL专题的第 26 篇. 下文还是白日梦以自导自演的方式,围绕"说说char 和 varchar的区别你了解多少?"展开本话题.看看你能抗到第 ...