周一面试啊,被问到nacos是怎么完成服务注册和发现的时分,满脑子里居然只蹦出了心跳这两个字,惭愧汗然之余开端把nacos的客户端和服务端源码看了一下。当然也学习了其他人的见解。其实就是开端看不懂,查了一下。哈哈哈哈哈
nacos是阿里开源的当然我们都知道啦,主要是三大功用。
- 服务的注册与发现中心
- 服务的装备中心
- 动态dns
服务的注册与发现
服务的发现
服务的发现是什么呢,这儿仍是稍微说一下。微服务架构中会根据不同业务功用区分不同的服务,比如说订单服务,商品服务等等。那么本来在单体架构中下订单扣件库存就很自然的是在一个业务中操作数据库就好,可是在微服务架构中就只能经过http恳求或许rpc,可是不管运用哪种都需要知道对方服务的ip地址和端口号。假如直接写死ip和端口号会有一些坏处,比如不利于服务的横向扩展,不利于服务的负载均衡,还有服务升级或许以外宕机的时分无法自动切换到可用的服务。所以呢就有了注册中心,这儿讲的就是nacos。服务启动时会将自己注册到nacos的注册中心(后面详细讲),当消费服务调用出产服务的时分会在注册中心中拿到这个服务的信息经过客户端的负载均衡的算法拿到其间一个服务的ip地址和端口号,然后进行调用。
nacos可以根据rpc、Dubbo、springcloud等等,这儿主要对springcloud环境的介绍。
源码剖析
从客户端下手
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
引入了这个依赖后找到spring.factories会发现里边自动装配的类
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获取的实例列表。
服务的注册(客户端)
NacosServiceRegistryAutoConfiguration是进口,然后找到NacosAutoServiceRegistration。
看字面意思是自动注册,ok点进去看他。由于上一个类中是new了这个类所以这儿去看他的结构函数,你会发现初始化了他的父类
持续看他的父类
ok他是完成了applicationlistener, 那么往下看bind和start办法
start办法中调用了register
register办法中调用nameingservice的注册实例的办法
接着看registerInstance办法。这儿看到最终serverProxy注册了实例,在此之前构建并执行了发给服务端的心跳,删除服务心跳事30s,标记不健康心跳是15s,发送频率是5s.
服务的注册(服务端)
检查serverProxy.registerService办法,这儿构建了一下参数然后调用reqApi办法向nacos注册中心发送http恳求注册。 检查reqApi会检查到/v1/ns/instance也就是说客户端是恳求的服务端中的这个接口进行注册的。
上面获取了namespaceId,和serviceName后执行注册办法
假如服务为空就创建一个新的,从模型中获取这个服务并添加到注册表中。