04、Eureka源码分析:服务注册

前言

本文讲解**“服务注册”这个功能模块,这个模块涉及到client主动请求server进行服务注册**,和server端对client端的请求进行处理。

client向server请求注册服务

client端服务注册的代码入口很难找,方法调用链路如下:

  • DiscoveryClient#DiscoveryClient

    • DiscoveryClient#initScheduledTasks

      • InstanceInfoReplicator#start

        • DiscoveryClient#register

真正的实现在com.netflix.discovery.InstanceInfoReplicator#start

*

InstanceInfoReplicator实例信息复制器(吐槽一下这个类名,做的是注册的事情,为什么不叫注册器,而是叫复制器呢*)实现了Runnable接口。start方法里最终会调用一个jdk的定时调度线程池,默认40s后执行本类的run方法,并且每次执行完之后,会循环调度run方法。

这里说一下eureka对循环调用的实现:他没有用jdk线程的循环调度方法,而是每次都在任务中再次执行下一次的调度任务。感觉也挺巧妙的,但是不知道和原生提供的方法相比,有什么不同之处。

run方法内部会检查实例信息是否是脏数据,即是否变更,如果变更的话,重新将实例信息注册到server。我们第一次服务注册的时候,在start方法中已经手动将数据置为脏数据,所以也会进行注册。服务注册的具体实现在DiscoveryClient#register方法中。

饶了一大圈,绕回了DiscoveryClient类。这里有两点疑问:

1、 为什么DiscoveryClient源码要把服务注册这么重要的功能,代码隐藏的这么深,感觉在存心难为读者;
2、 为什么第一次注册要延迟40s注册呢?;

疑问先放在这吧,感觉不是特别重要,去看DiscoveryClient#register方法:

*

其实就是包装当前实例信息,发送http请求给server的REST接口,eureka的网络框架使用的是Jersey2,我们不对这个框架进行深究,直接给出发送请求的实现:com.netflix.discovery.shared.transport.jersey2.AbstractJersey2EurekaHttpClient#register

*

总结:其实client向server请求注册服务的逻辑比较简单,就是延迟40s向eureka-server发送一个http请求,请求中携带自己的服务实例信息instanceInfo。每个四十秒会检查一次实例信息是否有更新,如果有更新,再次将实例信息注册到服务端

server端处理client的服务注册请求

server端请求”服务注册“的方法在 com.netflix.eureka.resources.ApplicationsResource#getApplicationResource

这里设计到eureka使用的mvc框架——jersey,这里不会对这个框架进行详细的讲解,能找到请求入口,不耽误我们找到eureka的核心源码就达到目的了。

调用链路:

  • ApplicationsResource#getApplicationResource

    • ApplicationResource#addInstance

    • 参数校验

    • 判断是否在aws云上

      • PeerAwareInstanceRegistryImpl#register

这里吐槽一下ApplicationResource#addInstance方法的实现,参数校验和aws云等不重要的逻辑就平铺在方法中,都不抽个子方法,个人认为挺不清晰的

*

com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#register方法内部才是真正执行“服务注册”的地方:

*

这个方法内部会调用注册表父类AbstractInstanceRegistry进行服务注册,父类方法:

*

父类的服务注册方法分为五步:

1、 从原始注册表中取出目标应用的所有实例信息;
2、 判断是第一次来注册还是再次注册,处理各自分支的逻辑;

1、 如果是第一次来注册的话,设置两个和服务踢除有关的属性;
3、 将注册信息封装到gMap中,放入原始注册表;
4、 如果来注册的实例是UP状态,更新信息并添加到最近变更队列,[和拉取增量注册表有关];
5、 清缓存,缓存与拉取注册表有关;

其中我们现阶段要关注的重点,是第三步,即将要注册的实例放入server端的一个map中,我们来看一下这个map:

*

这个维护在AbstractInstanceRegistry对象内部的嵌套Map,就是我们常说的eureka注册中心的原始注册表。之所以称为原始注册表是因为eureka-server会维护缓存注册表,为了区分开,将最底层的注册表成为原始注册表

将嵌套map展开,类似这样的数据结构:

Over.

总结

*

对象清单

AbstractInstanceRegistry#registry 服务端原始注册表

数据结构:ConcurrentHashMap<String, Map<String, Lease>>

InstanceInfo实例对象,主要包含租约信息leaseInfo:心跳续约时间等

*

Application 注册的应用

即注册到eureka的应用,一个应用一个Application,比如UserTask就是一个Application.

源码类:com.netflix.discovery.shared.Application。

Application实例属性中保存了实例对象集合——Set 。

配置参数

eureka官方并没有提供完整的配置文件列表,这里是他们对配置的描述:https://github.com/Netflix/eureka/wiki/Configuring-Eureka,所有有一些配置我们要结合源码去网上搜一下,这里列出源码中的key。

前缀namespace,默认为eureka

是否进行服务注册

registration.enabled

默认true

定时检查是否需要注册的时间/第一次注册的延时时间

appinfo.initial.replicate.time

默认40s

版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: