spring cloud:eureka源码之我见(四)服务注册源码剖析

一、Eureka client端的服务注册

Eureka client的服务注册流程代码位于eureka client包下的InstanceInfoReplicator类中。还记得之前的Eureka server初始化流程和Eureka client初始化流程中都实例化了一个DiscoveryClient类吗?在他的构造方法中,有一行代码

initScheduledTasks();

这行代码内部就隐藏着eureka client的注册。

 (1)在InstanceInfoReplicator的start()方法中,将自己作为一个线程放入调度线程池中,默认延迟40s去执行这个线程,还将isInstanceInfoDirty设置为true。

(2)延迟40s后,定时调度启动,执行run()方法开始注册。也就是eureka client在启动40s后才开始注册,而且这里的定时调度40s执行一次,不过只有istanceInfo发送改变,才会去重新注册。首先调用DsicoveryClient.refreshInstanceInfo()方法,这里面其实是调用了ApplicationInfoManager的一些方法来刷新一下服务实例的配置,用健康检查器查看了一下服务实例的状态,然后将状态更新到ApplicationInfoManager中。

(3)由于之前将isInstanceInfoDirty设置为true,所以这里执行服务注册。

(4)服务注册的时候,是基于EurekaClient的register()方法去注册的,而底层其实是通过调用EurekaTransport的registrationClient(EurekaHttpClient的实例)的register()方法,调用eureka server对外暴露的一个restful接口,将InstanceInfo给发送了过去。

 而EurekaTransport的registrationClient是在DiscoveryClient的构造方法中完成了初始化。

(5)eureka大量的基于jersey框架,在eureka server上提供restful接口,在eureka client如果要发送请求到eureka server的话,一定是基于jersey框架,去发送的http restful接口调用的请求

(6)真正执行注册请求的就是eureka-client-jersey2工程里的AbstractJersey2EurekaHttpClient,请求http://localhost:8080/v2/apps/ServiceA,将服务实例的信息发送过去。

二、Eureka server是如何完成服务注册的

从eureka client的注册流程中,我们看到eureka client通过http请求,将服务实例的信息发送给了eureka server的接口,而eureka server接收到请求是如何完成服务注册的呢?

1.首先,我们去寻找一下eureka server的接口。eureka使用的是jersey框架,在eureka-core的resources包下,有一堆的resource,这些resources就相当于springmvc中的controller,用来接收http请求。而在之前的源码结构中,我们知道,eureka-core包就是eureka-server的功能实现,这些resource就是eureka-server的controller。

所有的http请求都会发送给eureka server的web应用,最后走jersey的servlet,jersey的servlet会根据请求的路径,将请求转发给对应的resource(相当于转发给某个controller)。

我们来看一下之前eureka client注册所发送的http请求路径:

http://localhost:8080/v2/apps/ServiceA

根据这个路径,我们找到一个resource:ApplicationsResource

然后在ApplicationResource中找到post请求对应的方法===>addInstance

这就是eureka server用来接收注册请求的。

这个方法接收的是InstanceInfo,代表了一个服务实例(服务可能部署在多台服务器上,每台服务器上的一个服务就是一个服务实例)。

所谓的InstanceInfo里面包含的数据包括两部分:

(1)主机名、ip地址、端口号、url地址等

(2)lease(租约)的信息:保持心跳的间隔时间、服务注册的时间、服务启动的时间、上一次心跳的时间等

这个方法一开始就进行了大量的参数校验,保证了代码的健壮性,值得参考,只不过检验逻辑可以放入私有方法中实现,便于阅读。

2.主要的注册代码就是:

 而这个registry是用的哪个实现类呢?

我们可以回到eureka server启动的地方,在EurekaBootStrap.initEurekaServerContext()方法中,eureka server初始化了一个PeerAwareInstanceRegistry,然后将这个registry放入到了EurekaServerContext中,而ApplicationsInstance就是从EurekaServerContext中获取的registry。

在PeerAwareInstanceRegistry的registry方法中最终还是调用了父类的registry方法完成了注册。

3.注册表的核心结构

ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>

这就是注册表PeerAwareInstanceRegistry的核心数据结构

外层Map的key是InstanceInfo.getAppName,服务实例名

内层Map的key是InstanceInfo.getId,服务实例id

如下所示:

{

“ServiceA”: {

“001”: Lease<InstanceInfo>,

“002”: Lease<InstanceInfo>,

“003”: Lease<InstanceInfo>

},

“ServiceB”: {

“001”: Lease<InstanceInfo>

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值