来自于开科唯识的面试官对于nacos的提问

1,578 阅读4分钟

周一面试啊,被问到nacos是如何实现服务注册和发现的时候,满脑子里竟然只蹦出了心跳这两个字,惭愧汗然之余开始把nacos的客户端和服务端源码看了一下。当然也借鉴了其他人的见解。其实就是开始看不懂,查了一下。哈哈哈哈哈

nacos是阿里开源的当然大家都知道啦,主要是三大功能。

  1. 服务的注册与发现中心
  2. 服务的配置中心
  3. 动态dns

服务的注册与发现

服务的发现

服务的发现是什么呢,这里还是稍微说一下。微服务架构中会根据不同业务功能划分不同的服务,比如说订单服务,商品服务等等。那么原来在单体架构中下订单扣件库存就很自然的是在一个事务中操作数据库就好,但是在微服务架构中就只能通过http请求或者rpc,但是无论使用哪种都需要知道对方服务的ip地址和端口号。如果直接写死ip和端口号会有一些弊端,比如不利于服务的横向扩展,不利于服务的负载均衡,还有服务升级或者以外宕机的时候无法自动切换到可用的服务。所以呢就有了注册中心,这里讲的就是nacos。服务启动时会将自己注册到nacos的注册中心(后面详细讲),当消费服务调用生产服务的时候会在注册中心中拿到这个服务的信息通过客户端的负载均衡的算法拿到其中一个服务的ip地址和端口号,然后进行调用。

image.png

nacos可以基于rpc、Dubbo、springcloud等等,这里主要对springcloud环境的介绍。

image.png

源码分析

从客户端入手

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

引入了这个依赖后找到spring.factories会发现里面自动装配的类

image.png

NacosDiscoveryAutoConfiguration用于服务发现加载配置信息和服务发现。
该类中ConditionalOnDiscoveryEnabled和ConditionalOnNacosDiscoveryEnabled为true时才会注册,默认为true,该类中注册了NacosDiscoveryProperties和NacosServiceDiscovery两个bean。
NacosDiscoveryProperties:配置加载自 application.yml,前缀为spring.cloud.nacos.discovery的配置信息,如service、server-addr、namespace等信息。 NacosServiceDiscovery:服务发现委托给NacosServiceDiscovery去做,而 NacosServiceDiscovery会让NamingService去获取服务实例。

这里会集成feign来包装http请求。fegin会在nacos的注册中心中拿到所有实例的列表,经过负载均衡的算法拿到其中一个实例进行远程调用。负载均衡这里fegin集成了ribbon,跟nginx对比的话他的不同之处在于它是在客户端通过算法实现负载均衡的。

在上面的自动装配的图片中会发现 NacosDiscoveryClientConfigServiceBootstrapConfiguration 在最下面。进去看会发现这个类引入了NacosDiscoveryClientConfiguration在进入看会看到注入了NacosDiscoveryClient这个类实现了DiscoveryClient接口。DiscoveryClient是springcloud中负责获取实例列表的。Feign通过DiscoveryClient获取的实例列表。

服务的注册(客户端)

image.png

NacosServiceRegistryAutoConfiguration是入口,然后找到NacosAutoServiceRegistration。 image.png

看字面意思是自动注册,ok点进去看他。因为上一个类中是new了这个类所以这里去看他的构造函数,你会发现初始化了他的父类 image.png

继续看他的父类 image.png

ok他是实现了applicationlistener, 那么往下看bind和start方法 image.png

start方法中调用了register image.png

register方法中调用nameingservice的注册实例的方法 image.png

接着看registerInstance方法。这里看到最后serverProxy注册了实例,在此之前构建并执行了发给服务端的心跳,删除服务心跳事30s,标记不健康心跳是15s,发送频率是5s. image.png

服务的注册(服务端)

查看serverProxy.registerService方法,这里构建了一下参数然后调用reqApi方法向nacos注册中心发送http请求注册。 image.png 查看reqApi会查看到/v1/ns/instance也就是说客户端是请求的服务端中的这个接口进行注册的。

上面获取了namespaceId,和serviceName后执行注册方法 image.png

如果服务为空就创建一个新的,从模型中获取这个服务并添加到注册表中。 image.png