前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图个源码系列 · Eureka Client启动注册,Server如何处理的全流程剖析

图个源码系列 · Eureka Client启动注册,Server如何处理的全流程剖析

作者头像
简熵
发布2023-03-06 21:43:46
3890
发布2023-03-06 21:43:46
举报
文章被收录于专栏:逆熵逆熵

目录

1、Eureka Client的初始化

2、Eureka Client启动,第一次如何发起注册?

3、Eureka server是如何处理client的注册请求呢?

本文分析EurekaClient是如何初始化,启动,并向eureka server发起注册的流程。分析的入口就是com.netflix.discovery.DiscoveryClient,我们从他的构造函数入手,剖析整个初始化,启动,发起注册的流程。

1、Eureka Client的初始化

首先们先关注DiscoveryClient的构造函数执行逻辑:

  • 保存传入的applicationInfoManager,eurekaClientConfig,instanceINfo对象赋值给自己的成员变量
  • 根据是否注册-(config.shouldRegisterWithEureka),是否抓取注册表-config.shouldFetchRegistry,默认都是true。
  • 然后初始化了一些统计相关的对象registryStalenessMonitor等,
  • 如果既不抓取,也不注册,就不用走后面一些处理逻辑了,直接返回。这里默认是抓取注册表的。
  • 接下来就是创建注册或者抓取注册表相关的一些流程。
  • 创建一些线池相关的,
    1. schedule调度线程池
    2. 心跳线程池heartbeatExecutor,
    3. 缓存刷新线程池cacheRefreshExecutor
  • 创建了EurekaTransport。这个就是client和server通信有关的传输对象。
  • scheduleServerEndpointTask方法,创建通信client的工厂类 Jersey2ApplicationClientFactory,可以创建http通信组件Jersey2ApplicationClient,后续客户端去注册,取消,发送心跳都是从这个对象去发送http请求。
  • 初始化了一些通信组件的东东,支持底层的eureka client跟eureka server进行网络通信的组件,对网络通信组件进行了一些初始化的操作。
  • 如果配置了抓取注册表,就会去抓取注册表 fetchRegistry(false),否则不注册
  • initScheduledTasks(); 初始化所有的调度方法。
  1. 初始化调度任务:如果要抓取注册表的话,就会注册一个定时任务,按照你设定的那个抓取的间隔,每隔一定时间(默认是30s),去执行一个CacheRefreshThread,给放那个调度线程池里去了;
  2. 如果要向eureka server进行注册的话,会搞一个定时任务,每隔一定时间发送心跳,执行一个HeartbeatThread;
  3. 创建了服务实例副本传播器,将自己作为一个定时任务进行调度;
  4. 创建了服务实例的状态变更的监听器,如果你配置了监听,那么就会注册监听器

如下图,就是整个初始化的大概流程图。

02

Eureka Client启动时发起注册的

Eureka Client是如何发起注册的呢?这个就要将这个类InstanceInfoReplicator实例信息复制对象作为入口,传入DiscoveryClient,instanceInfo,默认每次复制间隔时间(默认30秒),burstSize(破裂时间,猜测和限流相关)参数作为构造参数。

instanceInfoReplicator.start();初始化延迟启动时间,默认值40秒。

  1. 先设置当前的instanceInfo的数据是dirty,脏数据状态。
  2. scheduler调度执行,延迟40秒执行。一旦执行就会执行instanceInfoReplicator.run()方法
  1. 在这个方法DiscoveryClient.refreshInstanceInfo()中,检查实例的hostname,续约等配置是否变化,如果变化就更新下值和实例数据状态是否为脏状态。 紧接着就是检查状态,看看状态是否下线,并把最新的状态赋值给服务实例管理器。 判断服务实例变脏的时间戳是否为空,前面设置了脏状态,所以这里会调用discoveryClient.register()方法进行注册。
  2. AbstractJersey2EurekaHttpClient#register()方法。

构造请求URL,http://localhost:8080/v2/apps/ServiceA

第一次注册就完成了,延迟40秒之后执行注册请求。

03

eureka server处理client的注册请求

  1. 由上一篇我们可以知道,client发起注册是由Jersey2ApplicationClient.register()发起注册,请求restful请求,http://localhost:8080/v2/apps/ServiceA经过jersey的统一拦截器就会路由到指定的web controller处理,在eureka-core工程目录下的resources目录下有一堆的resource,这些resource相当于是spring web mvc的controller,用来接收这个http请求的。resources相当于是jersey里面的controller吧。
  2. 所有的请求都会发送到eureka server的web应用,最后都会走jersey的servlet,jersey的servlet会根据请求的路径,将请求转发给eureka core里面的resource(相当于是转发给某个controller)。
  3. 我们关注点就是在ApplicationResource中,addInstance(),
    1. ApplicationResource.java,进入方法有大量的check检查,防御性编程,对服务实例对象instance进行检查
    2. 紧接着调用 PeerAwareInstanceRegistry.registry()方法进行注册。
  1. 先根据传入的服务实例的续约对象中的续约时间进行判断,如果不存在就用默认值,90秒。
  2. 调用父类方法的register()方法进行注册。
  1. 这里采用了读写锁,ConcurrentHashMap内存注册表,ConcurrentLinkedQueue最近三分钟队列来保证线程安全。首先从map中获取key为AppName的服务实例对应的数据结构Map<String, Lease<InstanceInfo>> ,如果不存在就重新创建,并设置给注册表。
  2. 然后根据服务实例Id来匹配对应的Lease<InstanceInfo>,此时如果我们是第一次注册,肯定是找不到的,进入else分支,一上来就加了重量级锁synchronized,这里处理的是有关于自我保护逻辑中每分钟预期收到心跳的数量 (当前服务实例数+2) *0.85
  3. 封装Lease.java对象,他持有了InstanceInfo对象,将lease对象设置到注册表结构中
  4. 对服务实例的状态做一些操作InstanceStatus,设置服务上线时间
  5. 添加本次注册的服务实例到最近三分钟队列中去,类型是ADD。设置服务实例更新时间。
  6. 过期多级缓存中的数据
  7. 返回到子类方法

3.复制本次操作的服务实例信息到其他server节点,这个后面单独分析。

c. 完成注册,返回204

  1. 一旦完成了服务注册之后,咱们平时访问的eureka控制台,其实就是个jsp,status.jsp 在jsp代码中,拿到了EurekaServerContext,所以之前为什么要将这个东东放到一个Holder里面去,就是随时都要从这个里面去获取一些数据
  1. 然后会从EurekaServerContext,获取到注册表,PeerAwareInstanceRegistry,注册表,从里面获取所有的服务信息,从底层的map数据结构中,获取所有的服务注册的信息,遍历,封装到一个叫Application的东西里去,一个Application就代表了一个服务,里面包含很多个服务实例。
  2. 然后就是将每个服务实例的信息,处理一下,形成一个服务的完整的这么一份信息,比如说有几个服务实例,每个服务实例的url地址是什么。

04

总结

以上就是分析了eureka client初始化,启动,并向eureka server发起注册的流程剖析,并对server端如何处理进行了一步步的画图加文字分析,文中若有不当之处,欢迎指出,谢谢大家阅读。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 逆熵架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档