Nacos源码分析,Nacos如何注册一个服务实例?

作为SpringCloudAlibaba微服务架构实战派上下册和RocketMQ消息中间件实战派上下册的作者,我来给大家带来Nacos源码系列的技术文章。

HTTP方式注册服务实例

Naocs使用InstanceController类的HTTP方法register()提供注册服务实例的功能。


/*** 注册服务实例到注册中心。* * @param request HttpServletRequest对象,包含注册服务的请求参数。* @return 返回字符串"ok"表示注册成功。* @throws Exception 抛出异常处理注册过程中的错误。*/
public String register(HttpServletRequest request) throws Exception {// 从请求中获取命名空间ID,未指定则使用默认值final String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID,Constants.DEFAULT_NAMESPACE_ID);// 从请求中获取服务名称,这是必选参数final String serviceName = WebUtils.required(request, CommonParams.SERVICE_NAME);// 校验服务名称格式NamingUtils.checkServiceNameFormat(serviceName);// 根据请求构建服务实例对象final Instance instance = HttpRequestInstanceBuilder.newBuilder().setDefaultInstanceEphemeral(switchDomain.isDefaultInstanceEphemeral()).setRequest(request).build();// 向注册中心注册实例getInstanceOperator().registerInstance(namespaceId, serviceName, instance);// 发布注册事件,用于跟踪和日志记录NotifyCenter.publishEvent(new RegisterInstanceTraceEvent(System.currentTimeMillis(), "", false, namespaceId,NamingUtils.getGroupName(serviceName), NamingUtils.getServiceName(serviceName), instance.getIp(),instance.getPort()));return "ok";
}

这里需要注意的是如下代码实现,其中InstanceOperator接口的实现类为InstanceOperatorClientImpl。

 /*** 获取实例操作器的实例。* * @return 返回 InstanceOperator 类型的实例,用于操作服务实例。*/private InstanceOperator getInstanceOperator() {return instanceServiceV2;}

在InstanceOperatorClientImpl类中,Nacos封装了Nacos支持的多种注册方式,

persistent服务注册(非临时)

PersistentClientOperationServiceImpl

PersistentClientOperationServiceImpl 是 Nacos 注册中心的一个关键组件,特别是在处理非临时(persistent)服务注册时。Nacos 是一个用于服务发现和配置管理的开源平台,广泛用于微服务架构中。

在 Nacos 的服务注册流程中,当服务实例尝试注册为非临时服务时,会涉及到 PersistentClientOperationServiceImpl。这个类负责将服务信息持久化到 Nacos 服务器的存储系统中,通常是通过使用 JRaft 协议(一种基于 Raft 一致性算法的分布式协议)来确保数据的一致性和可靠性。

具体来说,PersistentClientOperationServiceImpl 可能会执行以下任务:

  1. 接收并处理来自客户端的注册请求。
  2. 将注册请求中的数据(如服务的 IP 地址、端口、元数据等)按照 Nacos 的数据模型进行格式化。
  3. 使用 JRaft 协议将数据写入到集群中的多数节点,以确保数据的持久化和一致性。
  4. 在注册成功后,向客户端返回确认信息。

需要注意的是,由于 Nacos 的内部实现和版本更新可能会发生变化,因此上述描述可能不完全适用于所有版本的 Nacos。

此外,如果在启动 Nacos 服务器时遇到与 PersistentClientOperationServiceImpl 相关的错误,可能需要检查集群状态、网络配置、日志记录等信息来诊断问题。这些错误信息通常会在服务器的日志文件中有所体现,因此查看和分析这些日志是解决问题的关键步骤。

总的来说,PersistentClientOperationServiceImpl 在 Nacos 中扮演着处理非临时服务注册的核心角色,是确保服务数据持久化和一致性的重要组成部分。

/*** 注册一个服务实例。* * @param service 服务信息* @param instance 实例信息* @param clientId 客户端ID* @throws NacosRuntimeException 如果服务是临时服务(非持久化服务),则抛出异常。*/@Overridepublic void registerInstance(Service service, Instance instance, String clientId) {// 获取服务的单例,并检查其是否为临时服务Service singleton = ServiceManager.getInstance().getSingleton(service);if (singleton.isEphemeral()) {throw new NacosRuntimeException(NacosException.INVALID_PARAM,String.format("Current service %s is ephemeral service, can't register persistent instance.",singleton.getGroupedServiceName()));}// 准备实例存储请求,并序列化为二进制数据final InstanceStoreRequest request = new InstanceStoreRequest();request.setService(service);request.setInstance(instance);request.setClientId(clientId);final WriteRequest writeRequest = WriteRequest.newBuilder().setGroup(group()).setData(ByteString.copyFrom(serializer.serialize(request))).setOperation(DataOperation.ADD.name()).build();try {// 向协议层发送写请求,注册实例protocol.write(writeRequest);// 记录注册信息日志Loggers.RAFT.info("Client registered. service={}, clientId={}, instance={}", service, clientId, instance);} catch (Exception e) {// 处理注册过程中可能出现的异常throw new NacosRuntimeException(NacosException.SERVER_ERROR, e);}}

临时服务注册

EphemeralClientOperationServiceImpl是Nacos注册中心中处理临时(ephemeral)服务注册和注销等操作的组件。与PersistentClientOperationServiceImpl不同,它处理的服务实例不需要持久化存储,通常这些服务实例的生命周期较短,且依赖于注册它们的客户端进程。

在Nacos中,服务实例可以是临时的或非临时的(持久的)。临时实例通常在客户端与服务端的心跳保持期间存在,如果客户端断开连接或心跳丢失,这些实例将被自动删除。而非临时实例则会被持久化存储,即使客户端断开连接也会保留在注册中心。

EphemeralClientOperationServiceImpl的主要功能包括:

  1. 处理临时服务实例的注册请求:当客户端向Nacos注册一个临时服务时,这个类会负责接收并处理这些请求。

  2. 维护心跳检测:对于临时服务,客户端需要定期发送心跳以表明服务仍然活跃。EphemeralClientOperationServiceImpl会检测并处理这些心跳信息,确保服务状态是最新的。

  3. 处理服务注销:当客户端关闭或不再需要某个服务时,它会发送注销请求,EphemeralClientOperationServiceImpl会处理这些请求并从注册中心移除相应的服务实例。

  4. 通知其他服务消费者:当有新的临时服务注册或现有服务注销时,这个类可能会负责通知其他相关的服务消费者,以确保它们能够获取到最新的服务列表。

由于临时服务不需要持久化存储,因此EphemeralClientOperationServiceImpl在处理这些服务时更加轻量级和高效。这种特性使得它非常适合于处理动态变化且生命周期较短的服务实例。

/*** 注册一个服务实例到指定的服务中。* * @param service 指定的服务对象。* @param instance 需要注册的实例对象。* @param clientId 客户端ID,用于标识哪个客户端进行了实例注册。* @throws NacosException 当注册过程出现异常时抛出。*/@Overridepublic void registerInstance(Service service, Instance instance, String clientId) throws NacosException {// 检查实例合法性NamingUtils.checkInstanceIsLegal(instance);// 获取服务的单例对象Service singleton = ServiceManager.getInstance().getSingleton(service);// 如果服务是持久化的,则不能注册临时实例if (!singleton.isEphemeral()) {throw new NacosRuntimeException(NacosException.INVALID_PARAM,String.format("Current service %s is persistent service, can't register ephemeral instance.",singleton.getGroupedServiceName()));}// 获取客户端对象Client client = clientManager.getClient(clientId);// 检查客户端及其ID的合法性checkClientIsLegal(client, clientId);// 准备实例发布信息InstancePublishInfo instanceInfo = getPublishInfo(instance);// 向客户端添加服务实例client.addServiceInstance(singleton, instanceInfo);// 更新客户端的最后修改时间client.setLastUpdatedTime();// 重算客户端的版本号client.recalculateRevision();// 发布客户端注册服务事件NotifyCenter.publishEvent(new ClientOperationEvent.ClientRegisterServiceEvent(singleton, clientId));// 发布实例元数据事件NotifyCenter.publishEvent(new MetadataEvent.InstanceMetadataEvent(singleton, instanceInfo.getMetadataId(), false));}

gRPC方式注册服务实例

在高清楚如何用gRPC方式注册服务实例之前,开发者一定要清楚Nacos的gRPC通信渠道是如何启动。

启动Nacos服务端通信渠道

 在Nacos中,GrpcClusterServerGrpcSdkServer是用于不同通信场景的GRPC服务器。具体来说:

  1. GrpcClusterServer:这个服务器主要用于Nacos集群节点之间的交互。当Nacos以集群模式运行时,各个节点之间需要通过GRPC进行通信以保持数据的一致性和同步。GrpcClusterServer就是为此而设计的,它处理集群内部节点之间的通信请求,确保集群的健壮性和数据的可靠性。

  2. GrpcSdkServer:这个服务器则用于客户端与Nacos服务器之间的交互。当外部客户端(如微服务应用)需要与Nacos服务器进行通信时,例如注册服务、发现服务或获取配置等,就会通过GrpcSdkServer来完成。它提供了对外服务的GRPC接口,使得客户端能够方便地调用Nacos的功能。

总结来说,当Nacos集群内部节点之间需要通信时,会使用GrpcClusterServer;而当外部客户端需要与Nacos服务器通信时,则会使用GrpcSdkServer。这样的设计使得Nacos能够灵活地处理不同类型的通信需求,提高了系统的可扩展性和可维护性。

具体是如何启动的呢?利用抽象类BaseRpcServer中的方法start()。


/*** 在服务器构建之后立即调用此方法,用于启动RPC服务器。* 该方法不接受参数且没有返回值。* 启动过程中,首先记录启动日志,然后启动服务器本身,接着如果存在SSL上下文刷新器,则刷新SSL上下文。* 最后,注册一个关闭钩子,以便在应用程序关闭时能够优雅地停止RPC服务器。* * @throws Exception 如果启动过程中遇到任何错误,则抛出异常。*/
@PostConstruct
public void start() throws Exception {String serverName = getClass().getSimpleName();// 记录启动日志Loggers.REMOTE.info("Nacos {} Rpc server starting at port {}", serverName, getServicePort());startServer();// 如果存在SSL上下文刷新器,则刷新SSL上下文if (RpcServerSslContextRefresherHolder.getInstance() != null) {RpcServerSslContextRefresherHolder.getInstance().refresh(this);}// 记录启动成功日志Loggers.REMOTE.info("Nacos {} Rpc server started at port {}", serverName, getServicePort());// 注册关闭钩子,以优雅地停止服务器Runtime.getRuntime().addShutdownHook(new Thread(() -> {// 记录停止日志Loggers.REMOTE.info("Nacos {} Rpc server stopping", serverName);try {// 停止服务器BaseRpcServer.this.stopServer();// 记录停止成功日志Loggers.REMOTE.info("Nacos {} Rpc server stopped successfully...", serverName);} catch (Exception e) {// 记录停止失败日志Loggers.REMOTE.error("Nacos {} Rpc server stopped fail...", serverName, e);}}));}

最终会启动两个gRPC服务端通信渠道,一个用于Nacos集群节点之间的交互,一个用于客户端与Nacos服务器之间的交互。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/821009.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

低代码开发平台权威推荐:创新开发、领跑市场!

Gartner是低代码领域的一家权威机构,该机构常常通过"魔力象限"的研究方法,评选全球范围内IT细分领域的产品,来帮助决策者提供重要的咨询建议。本文盘点了Gartner机构推荐的6款低代码平台:Zoho Creator、Mendix、Oracle、…

Java 中建造者模式,请用代码具体举例

建造者模式是一种创建型设计模式,它允许你创建一个复杂对象的不同部分并将它们组装在一起,以产生最终的对象。以下是一个简单的 Java 示例,演示了建造者模式的用法: // 产品类 class Computer {private String cpu;private String…

JVM结构化体系

目录 目录 1.JVM 简介 1.1. 如何理解 JVM 呢? 1.2. 市场主流 JVM 分析? 1.3. 为什么要学习 JVM? 1.4. 字节码底层是如何执行呢? 如何理解 JIT 呢? 为什么 JVM 中解释执行与编译执行的并存(混合模式&…

【C++】类和对象③(类的默认成员函数:拷贝构造函数 | 赋值运算符重载)

🔥个人主页:Forcible Bug Maker 🔥专栏:C 目录 前言 拷贝构造函数 概念 拷贝构造函数的特性及用法 赋值运算符重载 运算符重载 赋值运算符重载 结语 前言 本篇主要内容:类的6个默认成员函数中的拷贝构造函数…

el-drawer二次封装进行可拖拽

1.想要的效果 鼠标放到上面出现箭头显示可拖拽得图标 2.代码实现 2.1封装成自定义指令 // drawerDragDirective.js // 定义指令 const drawerDragDirective {// 指令绑定时的处理函数bind(el, ) {const minWidth 300;const dragDom el.querySelector(.el-drawer);// 创…

掀起区块链开发狂潮!Scaffold-eth带你一键打造震撼DApp

文章目录 前言一、Scaffold-eth是什么?二、安装和配置1.准备工作2.安装3.配置开发环境 三、进阶使用1.放入自己的合约2.部署运行 总结 前言 前面的文章传送🚪:hardhat入门 与 hardhat进阶 在之前的文章中,我们已经探讨了使用Har…

【Linux】提升Linux命令行效率:光标移动和文本操作的键盘快捷键

Just 那么年少 还那么骄傲 两眼带刀 不肯求饶 即使越来越少 即使全部都输掉 也要没心没肺地笑 Just 那么年少 我向你招手 让你看到 我混账到老 天涯海角 天荒地老 只等你摔杯为号 🎵 朴树《Forever Young》 Linux命令行界面(CLI&am…

设计模式系列:简单工厂模式

作者持续关注 WPS二次开发专题系列,持续为大家带来更多有价值的WPS二次开发技术细节,如果能够帮助到您,请帮忙来个一键三连,更多问题请联系我(QQ:250325397) 目录 定义 特点 使用场景 优缺点 (1) 优点…

故障转移-redis

4.4.故障转移 集群初识状态是这样的: 其中7001、7002、7003都是master,我们计划让7002宕机。 4.4.1.自动故障转移 当集群中有一个master宕机会发生什么呢? 直接停止一个redis实例,例如7002: redis-cli -p 7002 sh…

保持微软Microsoft Teams始终在线的方案

保持微软Microsoft Teams始终在线的方案 背景方案 背景 目前使用微软Teams办公的小伙伴很多,但是长时间不操作电脑就被自动设置成离线状态。对于在电脑前学习书本或者在思考问题的小伙伴就显得不太友好,因为即使我们不操作电脑我们也时刻在电脑前&#…

定时器产生延时停止

1,需求: 当按下按钮SB1,输出信号为0N,指示灯点亮;按下按钮SB2,经过10s的延时后,指示灯熄灭 2,关闭使用定时的常闭触电

Python 如何的调试模式使用 Python 的内置调试器 pdb 或者集成开发环境(IDE)如 PyCharm、Visual Studio Code

Python 的调试模式通常是通过使用 Python 的内置调试器 pdb 或者集成开发环境(IDE)如 PyCharm、Visual Studio Code 等中的调试工具来实现的。 使用 pdb pdb 是 Python 的标准库中的一个模块,它提供了一个交互式的源代码调试器。你可以使用…

Graphql mock 方案

GraphQL API 的强类型本质非常适合模拟。模拟是 GraphQL Code-First 开发过程的重要组成部分,它使前端开发人员能够构建 UI 组件和功能,而无需等待后端实现。 我们期望基于 TS 强类型定义的特点以及中后台常见列表、详情的数据类型共性,实现…

HG泄露(ctfhub)

工具准备:dirsearch、dvcs-ripper 网络安全之渗透测试全套工具篇(内含安装以及使用方法)_dvcs-ripper-CSDN博客 dvcs-ripper:一款perl的版本控制软件信息泄露利用工具,支持bzr、cvs、git、hg、svn... tree //树状…

APP开发_Android 与 js 互相调用

1 js 调用 Android 方法 当使用 JavaScript 调用 Android 原生方法时,主要涉及到 Android 的 WebView 组件,它允许你在 Android 应用中嵌入网页内容,并提供了 JavaScript 与 Android 代码交互的能力。 (1)创建JavaSc…

项目升级到jdk21后 SpringBoot相关组件的适配

了解到jdk21是一个LTS版本,可以稳定支持协程的功能。经过调研,将目前线上的jdk8升级到21,使用协程提升并发性能。 目前系统使用springBoot 2.0.3.RELEASE,并且引入了mybatis-spring-boot-starter、spring-boot-starter-data-redi…

MySql数据库从0-1学习-第四天多表查询

多表查询,指从多张表查询数据 连接查询 内连接: 相当于查询A和B交集部分数据外连接 左外连接: 查询左表所有的数据(包括两张表交集部分的数据)有外连接: 查询右表所有的数据(包括两张表交集部分的数据) 子查询 内连接查询 隐式内连接查询 select 字段列表 from 表1,表2 whe…

聪明利用ChatGPT,让你的论文更加出色

ChatGPT无限次数:点击直达 聪明利用ChatGPT,让你的论文更加出色 引言 近年来,人工智能技术的快速发展给我们的学术研究带来了前所未有的便利。其中,自然语言处理技术中的ChatGPT模型,作为一种生成式预训练模型,为我们…

【电控笔记2.3】速度回路+系统延迟

2.3.1速度回路pi控制器设计 pi伯德图近似设计(不考虑延时理想情况下) Tl:负载转矩 PI控制器的转折频率:Ki/Kp

VScode插件发布

背景 上期在初涉 VS Code 插件开发-CSDN博客中,通过Yeoman工具创建了第一个插件项目,在helloworld的基础上修改,实现预期的功能后,需要将VScode插件发布到插件市场中使用。 官方文档:Publishing Extensions | Visual…