nacos注册中心之服务注册
基于nacos 1.1.4 的源码分析
Nacos提供了SDK和Open API的形式实现服务注册,两种方式本质都是一样的,SDK方式提供了一种访问的封装,底层是基于HTTP 协议完成请求的,所有我们直接基于Open API请求方式分析一下服务端的服务注册原理。
/nacos/v1/ns/instance
服务注册对外提供的服务接口请求地址为nacos/v1/ns/instance,实现代码为nacos-naming下的InstanceController类:
@RestController
@RequestMapping(UtilsAndCommons.NACOS_NAMING_CONTEXT + "/instance")
public class InstanceController {
@CanDistro
@PostMapping
public String register(HttpServletRequest request) throws Exception {
String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);
String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID, Constants.DEFAULT_NAMESPACE_ID);
serviceManager.registerInstance(namespaceId, serviceName, parseInstance(request));
return "ok";
}
}
调用registerInstance方法:
public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
createEmptyService(namespaceId, serviceName, instance.isEphemeral());
Service service = getService(namespaceId, serviceName);
if (service == null) {
throw new NacosException(NacosException.INVALID_PARAM,
"service not found, namespace: " + namespaceId + ", service: " + serviceName);
}
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
}
- 创建一个空服务,实际是初始化serviceMap
- getService:从serviceMap中根据namespaceId和serviceName得到服务对象
- 调用addInstance添加服务实例。
createEmptyService
createEmptyService用来创建空服务,调用createServiceIfAbsent
public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster) throws NacosException {
Service service = getService(namespaceId, serviceName);
if (service == null) {
Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName);
service = new Service();
service.setName(serviceName);
service.setNamespaceId(namespaceId);
service.setGroupName(NamingUtils.getGroupName(serviceName));
// now validate the service. if failed, exception will be thrown
service.setLastModifiedMillis(System.currentTimeMillis());
service.recalculateChecksum();
if (cluster != null) {
cluster.setService(service);
service.getClusterMap().put(cluster.getName(), cluster);
}
service.validate();
putServiceAndInit(service);
if (!local) {
addOrReplaceService(service);
}
}
}
- 根据namespaceId和serviceName从缓存中获取Service实例
- 如果没有,创建并调用putServiceAndInit()保存到缓存中。
putServiceAndInit方法:
private void putServiceAndInit(Service service) throws NacosException {
putService(service);
service.init();
consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service);
consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service);
Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJSON());
}
- 通过putService方法将服务缓存到内存
- service.init();建立心跳检测机制,通过定时任务不断检测当前服务下所有实例最后发送心跳包的时间。如果超时,则设置healthy为false表示服务不健康,并发送服务变更事件。
- consistencyService.listen实现数据一致性的监听
总结:
Nacos提供了SDK和Open API的形式实现服务注册,两种方式本质都是一样的
服务注册对外提供的服务接口请求地址为nacos/v1/ns/instance
服务注册过程:
- nacos客户端通过Open API的形式发送服务注册请求
服务端收到请求:
- 构建一个Service对象保存到Map集合中
- 使用定时任务对当前服务下的所有实例建立心跳检测机制。
- 基于数据一致性协议将服务数据进行同步。
nacos的服务注册对我们很重要,我们要理解其中的原理和注册流程,然后分析看源码,从而更好的理解nacos是怎么实现服务的注册的,这样我们才能理解透彻nacos的运作机制,以后在我们工作中遇到什么问题,我们能够及时排查,快速定位,这样我们才能在工作和学习中更好的提高效率完成任务。
你觉得这篇文章不错的话,请留言点赞评论~~