1、注册中心的原理
服务注册的主要功能主要体现在以下三点:
①注册的实例可在服务启动的时候注册到服务中心,关闭服务的时候会从注册中心上撤销
②消费者可以在注册中心获取可用的实例
③注册中心会调用健康检查的API来定期验证当前注册中心上的服务是否正常,以此判断是否能够处理请求
2、解读Nacos源码:
关于源码分析呢,我们没必要全部看,我们只要看关键的三部分:服务注册、服务地址的获取、服务地址变化的感知即可
2.1 服务注册
1、在Cloud中存在一个类名为ServiceRegistry的接口类,他是springcloud提供服务注册的一个标准,只要是集成到springcloud中实现服务注册的组件,都要实现该接口
package org.springframework.cloud.client.serviceregistry; public interface ServiceRegistry<R extends Registration> { void register(R registration); void deregister(R registration); void close(); void setStatus(R registration, String status); <T> T getStatus(R registration); }
2、接下来,我们看一下实现1中接口类的方法NacosServiceRegistry,看看他是什么时候实现注册的
public void register(Registration registration) { if (StringUtils.isEmpty(registration.getServiceId())) { log.warn("No service to register for nacos client..."); } else { String serviceId = registration.getServiceId(); String group = this.nacosDiscoveryProperties.getGroup(); Instance instance = this.getNacosInstanceFromRegistration(registration); try { //实现注册 this.namingService.registerInstance(serviceId, group, instance); log.info("nacos registry, {} {} {}:{} register finished", new Object[]{group, serviceId, instance.getIp(), instance.getPort()}); } catch (Exception var6) { log.error("nacos registry, {} register failed...{},", new Object[]{serviceId, registration.toString(), var6}); } } }
看一下怎么实现注册的
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException { if (instance.isEphemeral()) { BeatInfo beatInfo = new BeatInfo(); beatInfo.setServiceName(NamingUtils.getGroupedName(serviceName, groupName)); beatInfo.setIp(instance.getIp()); beatInfo.setPort(instance.getPort()); beatInfo.setCluster(instance.getClusterName()); beatInfo.setWeight(instance.getWeight()); beatInfo.setMetadata(instance.getMetadata()); beatInfo.setScheduled(false); long instanceInterval = instance.getInstanceHeartBeatInterval(); beatInfo.setPeriod(instanceInterval == 0L ? DEFAULT_HEART_BEAT_INTERVAL : instanceInterval); //创建心跳信息实现健康监测 this.beatReactor.addBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), beatInfo); } //实现服务注册 this.serverProxy.registerService(NamingUtils.getGroupedName(serviceName, groupName), groupName, instance); }
心跳相关的就不讲了,其实很简单,心跳他其实就是客户端通过定时任务向服务端发送一个请求注册信息的一个数据包,然后启动一个专门检测服务的定时,然后就有了默认15秒一检测,30秒剔除服务的机制,多余的不多说了,然后我们继续在看一下上述代码中的registerService方法做了什么事情
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException { LogUtils.NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}", new Object[]{this.namespaceId, serviceName, instance}); Map<String, String> params = new HashMap(9); params.put("namespaceId", this.namespaceId); params.put("serviceName", serviceName); params.put("groupName", groupName); params.put("clusterName", instance.getClusterName()); params.put("ip", instance.getIp()); params.put("port", String.valueOf(instance.getPort())); params.put("weight", String.valueOf(instance.getWeight())); params.put("enable", String.valueOf(instance.isEnabled())); params.put("healthy", String.valueOf(instance.isHealthy())); params.put("ephemeral", String.valueOf(instance.isEphemeral())); params.put("metadata", JSON.toJSONString(instance.getMetadata())); this.reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, (String)"POST"); }
其实很简单,就是用Map封装了注册地址等信息,最后在使用reqAPI,一个nacos提供注册的API接口来实现服务的注册,有兴趣的童鞋可以去查看一下nacos提供服务注册的API源码,主要看一下InstanceController控制类,这个是主要实现的接口类,可以简单概述一下这个接口主要做了那几件事情:
①Nacos客户端通过API的形式发送服务注册请求,请求这个类,这个类负责接收注册请求
②接收到请求之后,构建一个service对象保存到Map集合中
③使用定时任务对当前的所有的实例都进行创建心跳检测的机制
④基于数据的一致性协议将服务的数据进行同步
解析完上面的注册原理和源码之后,其实大家也就能知道了前面的一系列操作输入参数的封装,关键还是调用nacos提供的API实现了注册,那大家想想其他的API是怎么实现的?比如查询服务的地址信息等等API,大家有兴趣的话,可以研究一下,你会发现,代码实现起来很简单同时很有意思