涨知识了,服务注册居然是这样实现的?【eureka源码系列NO.1】

前言

我计划写一个SpringCloud源码系列的文章,毕竟最有效的学习方式,就是尝试把知识教授给其他人,在这个过程中如果遇到问题,就需要反思、再学习、再反思、再学习,渐渐就进步了。

虽然eureka已经停止维护了,但是它的设计理念、系统架构设计都是值得学习的,是有学习的价值的,所以springCloud源码系列的探秘之旅,我们从此处开始。

服务端和客户端的概念

eureka由服务端和客户端两部分组成,服务端作为单独的一个服务运行,而客户端则是需要和我们自己的业务系统进行集成。

服务端负责维护各个服务的地址信息,客户端则需要和服务端进行通信,获取其他服务的地址。

客户端,调用服务端

源码概览

本系列文章通过源码+图解说明方式,力求用简单的、轻松的方式辅助大家理解eureka的核心机制。

springCloud-eureka是对netflix-eureka的封装,所以我们直接通过学习Netflix的eureka源码就ok了,当然最后还是会研究一下springCloud是怎么对netflix进行封装的。

本文使用的是eureka 1.7.2版本,下载地址为:https://github.com/Netflix/eureka

下载下来的源码如图:

image-20210811211421769

eureka-server和eureka-client是怎样通信的

eureka服务端作为一个单独的系统,可独立部署。就像平时我们自己开发的web服务一样,打成war包后,直接放入web容器中,再启动web容器(比如tomcat),eureka服务端就可以被客户端访问了。

eureka服务端提供了大量的接口,能够让客户端通过http请求进行调用,客户端一旦调用相应的接口(比如服务注册接口、服务下线接口等),服务端就可以做出相应的响应。

接下来通过一个服务注册的例子,来讲解eureka服务端在启动的过程中做了什么,eureka客户端的启动又做了些什么,服务注册又是怎么实现的。

eureka-server在项目启动期间做了些什么

首先,是eureka-server的启动过程,我们在eureka-core的源码中,查看一下eureka服务端启动时做了什么。

类名:EurekaBootStrap.java

主要涉及的方法:contextInitialized()initEurekaEnvironment()initEurekaServerContext()

服务端初始化1

说明:源代码太长,不适合放在文章里,所以用图片的方式做了一些简化。具体代码细节,建议大家可以从github下载源码,对照文章进行阅读。文章里只能梳理主要流程,展现主要的代码逻辑。

简单总结一下,eureka-server的启动,大概做了以下的事情:

1.做了一些初始化操作:读取配置文件、创建ApplicationInfoManagereurekaClientPeerAwareInstanceRegistryPeerEurekaNodes等对象。具体查看上图。

**2.启动了一堆定时任务。**具体有哪些定时任务,我们后续查看到对应的机制时再讲,避免蒙圈。

图中的简化代码,大家有一个简单的理解即可,这里我们主要讲服务注册,所以只关注 PeerAwareInstanceRegistry对象的创建即可。

来看看最关键的东西,注册表

客户端想要从服务端获取其他服务的信息,那么在服务端必定也必须要有一个地方保存所有的服务信息,对不对?

所以eureka的设计里,服务端的内部就维护了一张注册表,每当有新的服务注册时,服务端就会去更新这张注册表,注册表的初始化方法就是 new PeerAwareInstanceRegistry()

追进源码我们发现,实际创建的是AbstractInstanceRegistry.java类的对象,还是用一张图来简化该类。

注册表

AbstractInstanceRegistry.java中包含一些成员变量,暂时我们主要关注registry对象,其余的部分还是等到学习对应的机制时再讲解。

registry是一个ConcurrentHashMap对象,它就是真正的注册表至此我们已经知道在eureka-server里,是通过一个Map来维护服务注册信息。

服务注册是怎样实现的

接下来,来看看eureka-client调用服务注册接口时,eureka-server做了什么。

eureka-server端接收请求的类是eureka-core工程的resources包下的ApplicationResource.java,由于eureka的开发没有使用我们熟悉的springmvc,为了便于理解,我们可以把resources包下的类当做我们平常开发对应的Controller。

image-20210818213520273

首先,我们先来看看InstanceInfo对象,也就是eureka-client调用服务注册接口时传递了什么参数。

在这里为了更直观的演示,我们借助于eureka-server项目中自带的单元测试来断点调试一下。

单元测试项目截图:

image-20210821105529299

服务注册的单元测试代码,贴一小段,大概看一下eureka-server的测试代码长什么样:

public class EurekaClientServerRestIntegrationTest {	
	@Test
    public void testRegistration() throws Exception {
        InstanceInfo instanceInfo = instanceInfoIt.next();
        EurekaHttpResponse<Void> httpResponse = jerseyEurekaClient.register(instanceInfo);
        assertThat(httpResponse.getStatusCode(), is(equalTo(204)));
    }
}

断点看看InstanceInfo中都是些什么数据:

image-20210821110851041

InstanceInfo中的数据很多,我标注了一些常用的大家一眼就能看明白的参数。

前面提到过引进注册中心就是为了解决服务之间自动获取通信地址的难题,解决的方法就是所有的服务都把ip和端口号放在一个统一的地方(eureka-server),需要其他服务的地址时再从同一个地方去取即可。

现在大家就能知道,每个服务是怎么把自己的ip和端口号交给eureka-server的了。

看明白了服务注册时的请求参数,下面通过一张流程图来理解eureka-server在服务注册中具体做了哪些事情。

eureka-server服务注册流程如下

注册接口流程图

图中列出了服务注册过程中eureka-server端主要执行的逻辑,暂时我们只需要知道,eureka-server接收到服务注册的请求后,会将eureka-client传递过来的客户端的数据,保存进registry中即可。其他逻辑暂时可忽略。

通过断点调试,看看registry内部的数据长什么样的。

image-20210821114939476

画一张图,方便理解registry的数据结构。

注册表的数据结构

至此,服务注册的相关流程就结束了,下一篇,我们来看看eureka-client是怎么获取注册表的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值