news 2026/9/10 22:40:31

Nacos 集群内部 RPC 规范深度解析:ClusterRpcClientProxy、请求处理器与内网认证体系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Nacos 集群内部 RPC 规范深度解析:ClusterRpcClientProxy、请求处理器与内网认证体系

Nacos 集群内部 RPC 规范深度解析:ClusterRpcClientProxy、请求处理器与内网认证体系

【免费下载链接】nacosan easy-to-use dynamic service discovery, configuration and service management platform for building AI cloud native applications.项目地址: https://gitcode.com/GitHub_Trending/na/nacos

导读

本文基于 Nacos 官方设计文档 foundation-internal-rpc-spec.md,系统讲解 Nacos 集群节点之间 server-to-server RPC 的传输模型、调用者模型、处理器注册与来源限制、内网 API 认证与请求过滤器、Payload 注册规则、集群请求分类以及超时与重试语义。读者将掌握 Nacos 集群节点间通知、查询、校验与状态同步请求如何被构造、鉴权、分发与处理,并能结合仓库源码(ClusterRpcClientProxyRequestHandlerRegistryRemoteRequestAuthFilter等)理解其底层实现原理,为二次开发与生产排障提供依据。


1. 适用范围:什么是 Nacos 内部 RPC

Nacos 内部 RPC(Internal RPC)是 Nacos 服务端节点之间请求的传输与处理器模型。当 Core、Config、Naming 等领域需要通知、查询、校验或同步与其他成员之间的状态时,走的就是这套内部 RPC。它属于基础设施层(foundation-level)规范,是 Foundation Capabilities Spec 中内部 RPC 部分的展开,并依赖以下规范:

  • Cluster Membership Spec(成员关系)
  • Remote Connection Lifecycle Spec(远程连接生命周期)
  • Request Filtering And Runtime Context Spec(请求过滤与运行时上下文)
  • gRPC API Spec(gRPC 接口)

本规范不定义AP/CP 一致性算法本身。Distro 数据归属、Raft 组行为、Config dump 顺序、Naming 反熵规则由使用该内部 RPC 基础的领域或一致性规范定义;共享 Config dump 与本地缓存边界由 Persistence And Dump Spec 定义。

2. 设计模型:复用 SDK 的 Payload 信封

Nacos 内部 RPC 与 SDK 面向的 gRPC API共用同一个固定 gRPCPayload信封。业务含义由Payload.metadata.type选择,body 中存放 JSON 序列化后的RequestResponse对象。

集群 gRPC 服务端使用cluster来源标签,ClusterRpcClientProxy创建的 server-to-server 客户端同样携带该标签:

RemoteConstants.LABEL_SOURCE = RemoteConstants.LABEL_SOURCE_CLUSTER

在源码 RemoteConstants.java 中可以看到这三个常量的真实取值:LABEL_SOURCE = "source"LABEL_SOURCE_SDK = "sdk"LABEL_SOURCE_CLUSTER = "cluster"。集群服务端 GrpcClusterServer.java 的getSourceLabel()直接返回RemoteConstants.LABEL_SOURCE_CLUSTER

因此,大多数内部 RPC 并不是一套独立的协议族,而是在远程层之上施加"受限来源 + 鉴权 + 处理器纪律"的约束。唯一的例外是内置的 JRaft CP 传输:它使用 JRaft 原生的 gRPC 消息与处理器,而非 Nacos 的PayloadRequestHandler模型,但它仍属于内部 server-to-server API,并遵守本规范中的服务端身份规则。

整体链路模型为:

member view -> ClusterRpcClientProxy per-member gRPC client -> Payload(metadata.type = request simple class name) -> RequestHandlerRegistry -> Request filters -> domain RequestHandler -> Response payload

3. 调用者模型:ClusterRpcClientProxy 的职责

ClusterRpcClientProxy是内部 RPC 的调用入口,位于 ClusterRpcClientProxy.java。它是 Spring@Service,同时继承MemberChangeListener,与成员管理深度绑定。

3.1 客户端生命周期

从源码看,其核心规则可以逐条对应实现:

  • 按成员建客户端:每个远端成员对应一个集群 RPC 客户端,客户端 key 固定为Cluster-{member.address}(见memberClientKey(Member)方法);
  • 单地址路由:每个集群客户端通过ServerListFactory只路由到恰好一个成员地址(源码中匿名ServerListFactorygenNextServer()getCurrentServer()getServerList()均只返回该成员地址);
  • 成员变更刷新init()@PostConstruct时通过NotifyCenter.registerSubscriber(this)订阅成员变更,onEvent(MembersChangeEvent event)回调中重新获取allMembersWithoutSelf()并调用refresh(members)refresh会为新成员创建客户端,并销毁已离开成员的Cluster-前缀客户端(RpcClientFactory.getClient(...).shutdown());
  • 发送前注入身份头sendRequest/asyncRequest在真正发出请求前都会调用injectorServerIdentity(request),通过AuthHeaderUtil.addIdentityToHeader注入配置的服务端身份;
  • 三种调用方式:同步请求sendRequest(Member, Request[, timeoutMills])(默认超时DEFAULT_REQUEST_TIME_OUT = 3000L毫秒)、带回调的异步请求asyncRequest(Member, Request, RequestCallBack)、以及向allMembersWithoutSelf()广播的sendRequestToAllMembers(Request)

3.2 调用者规则

规范要求调用方必须容忍:成员变化、客户端缺失、客户端已停止、超时以及过期成员状态。例如sendRequest在目标客户端不存在时会抛出NacosException(CLIENT_INVALID_PARAM, "No rpc client related to member: ...")isRunning(Member)方法用于在领域行为需要时检查目标客户端是否连接运行。

领域调用方应在领域行为需要时检查目标成员是否存在、成员状态、能力以及客户端运行状态。一次成功的 RPC 只意味着远端处理器按自身契约接受并处理了请求,并不代表集群级收敛——除非领域协议明确如此声明。

4. 处理器注册与来源限制

服务端处理器继承RequestHandler<T extends Request, S extends Response>RequestHandlerRegistry(位于 RequestHandlerRegistry.java)实现ApplicationListener<ContextRefreshedEvent>,在 Spring 上下文刷新后扫描所有RequestHandler类型的 Bean,按请求类 simple name 注册registryHandlers.putIfAbsent(tClass.getSimpleName(), requestHandler)),并维护sourceRegistry记录来源限制。

4.1 @InvokeSource 来源限制

@InvokeSource注解定义在 InvokeSource.java,只有一个String[] source()属性。RequestHandlerRegistry.onApplicationEvent中,若处理器类标注了@InvokeSource,则把允许的来源集合写入sourceRegistry(key 为请求类 simple name);checkSourceInvokeAllowed(type, source)方法在后续请求分发时校验:

public boolean checkSourceInvokeAllowed(String type, String source) { if (sourceRegistry.containsKey(type) && !sourceRegistry.get(type).contains(source)) { return false; } return true; }

处理器规则总结:

  • 一个 Payload 类型在一个服务端运行时中应只有一个语义处理器;
  • 集群专用处理器必须用@InvokeSource声明cluster来源;声明后,来自其他来源标签的调用会在请求解析到达处理器之前被拒绝;
  • 若处理器未声明@InvokeSource,注册表不强制来源限制,因此新增内部处理器应显式声明
  • 处理器来源限制是传输层保护,绝不能替代鉴权或权限检查。

作为对照,RequestHandlerRegistryTest.java 与 ClusterRpcClientProxyTest.java 覆盖了注册、来源校验与客户端刷新行为,可作为理解该机制的测试佐证。

4.2 处理器拥有语义,远程层拥有分发

规范强调:处理器拥有请求语义;远程基础层拥有分发、来源检查、请求上下文、过滤器与响应转换。这意味着领域开发者只关心handle(Request, RequestMeta)的业务逻辑,传输层面的纪律由基础设施统一保证。

5. 安全与请求过滤器

内部 RPC 必须使用与其他受保护 gRPC 请求相同的安全模型。核心规则:

  • 内部集群 API 应在handle(...)上标注@Secured(apiType = ApiType.INNER_API)
  • 领域专属内部 API 应在鉴权插件需要类型化资源时设置signType或资源信息;
  • ClusterRpcClientProxy必须注入配置的服务端身份头;
  • RemoteRequestAuthFilter在内网 API 鉴权启用时校验内部 API 的服务端身份;
  • 公共 API 关闭鉴权不得被当作跳过必需内部服务端身份校验的理由;
  • 命名空间校验、参数提取、TPS 控制等请求过滤器应在领域需要时声明在处理器上。

5.1 RemoteRequestAuthFilter 的实现

RemoteRequestAuthFilter.java 继承AbstractRequestFilter,其filter(...)逻辑与规范逐条对应:

  1. 通过反射获取处理器handle方法,检查是否标注@Secured
  2. secured.apiType()写入RequestContextAuthContext
  3. 滚动升级兼容:若ApiType.INNER_APIinnerApiAuthEnabled.isEnabled()为 false,则直接放行(旧版本 Nacos 可能对部分内部 API 不带服务端身份,遵循旧逻辑);
  4. 非 INNER_API 且公共鉴权关闭时放行;
  5. 调用protocolAuthService.checkServerIdentity(request, secured)校验服务端身份,FAIL直接返回NO_RIGHT错误响应,MATCHED放行;
  6. 之后进入常规身份与权限校验(parseResource/parseIdentity/validateIdentity/validateAuthority),失败抛出AccessException并转为错误响应。

5.2 InnerApiAuthEnabled 仅是兼容门

InnerApiAuthEnabled只是 2.x 到 3.x 滚动升级的兼容开关,已标记为在 Nacos 3.4.0 移除;持久的内部 API 服务端身份校验绝不能依赖这个临时组件。

5.3 已知请求过滤器关注点

过滤器关注点典型注解或路径规则
服务端身份与鉴权@SecuredRemoteRequestAuthFilter保护内部 API 并解析鉴权上下文。
参数校验@ExtractorManager.Extractor复用共享参数提取与校验。
命名空间校验@NamespaceValidation资源标识含命名空间时校验其存在性。
TPS 控制@TpsControl为集群流量注册并执行稳定的控制点。

RequestHandlerRegistry在注册时还会检测handle方法上的@TpsControl注解,并在TpsControlConfig.isTpsControlEnabled()开启时通过ControlManagerCenter注册 TPS 控制点——这印证了 TPS 控制是注册期与运行期双层生效的。

5.4 JRaft 原生 gRPC 的凭据校验

JRaft 原生 gRPC 鉴权遵循传输特有的规则:

  • 每个新建 JRaft 客户端通过 gRPCCallCredentials附加配置的 Nacos 服务端身份;
  • gRPCServerInterceptor在任何 Raft、CLI、snapshot、read、write 处理器执行前校验凭据;
  • 该路径不引入Nacos 的RequestHandler或 payload 包装;
  • 凭据复用nacos.core.auth.server.identity.keynacos.core.auth.server.identity.value,且独立于公共 API 鉴权开关强制要求;
  • 固定的小写元数据名nacos-server-identity-keynacos-server-identity-value承载配置的 key 与 value,这样运维自定义的身份 key 不会被误解释为 gRPC 元数据名;
  • 日志绝不能打印身份 value。

这些元数据常量可在 JRaftAuthMetadata.java 中直接看到:

static final Metadata.Key<String> IDENTITY_KEY = Metadata.Key.of( "nacos-server-identity-key", Metadata.ASCII_STRING_MARSHALLER); static final Metadata.Key<String> IDENTITY_VALUE = Metadata.Key.of( "nacos-server-identity-value", Metadata.ASCII_STRING_MARSHALLER);

对应的NacosJRaftCallCredentialsNacosJRaftServerInterceptor位于 raft/auth 目录,并有 NacosJRaftCallCredentialsTest.java 与 NacosJRaftServerInterceptorTest.java 佐证。

重要边界:凭据是请求鉴权,不是传输机密性。明文 JRaft 通道对路径上的攻击者仍可被观测和重放;需要此类保护的部署必须加固传输边界。滚动升级兼容与强制转换规则由 CP Consistency Spec 负责。

6. Payload 注册:处理器不是完整的 gRPC 契约

仅有请求处理器 Bean不足以构成有效的 gRPC payload 契约。请求与响应 payload 类必须注册,远程层才能解析Payload.metadata.type

6.1 注册规则

  • 请求与响应类必须继承 Nacos 远程RequestResponse模型;
  • payload 类必须保持 JSON 兼容;
  • payload 类必须注册到合适的 payload 注册表中,或在META-INF/services/com.alibaba.nacos.api.remote.Payload文件中登记,之后才能被视为有效的 gRPC 契约;
  • 新请求类必须通过Request#getModule()返回稳定的模块名;
  • 注册 payload 并不意味着成为公共 API,除非接口规范明确暴露。

仓库中真实的注册文件位于 api/src/main/resources/META-INF/services/com.alibaba.nacos.api.remote.Payload,其中可以看到ConfigChangeClusterSyncRequestServerReloadRequestServerLoaderInfoRequest、各 Naming 请求、AI 领域请求等均已登记。如果代码中存在处理器但 payload 类型未注册,该处理器必须被当作未激活或不完整的 gRPC 契约。

6.2 一个真实的处理器样例

以 Config 领域为例,ConfigChangeClusterSyncRequestHandler.java 完整展示了本规范所有要素的落点:

@Since("2.0.0") @Component @InvokeSource(source = {RemoteConstants.LABEL_SOURCE_CLUSTER}) public class ConfigChangeClusterSyncRequestHandler extends RequestHandler<ConfigChangeClusterSyncRequest, ConfigChangeClusterSyncResponse> { private final DumpService dumpService; @Override @NamespaceValidation @TpsControl(pointName = "ClusterConfigChangeNotify") @ExtractorManager.Extractor(rpcExtractor = ConfigRequestParamExtractor.class) @Secured(signType = SignType.CONFIG, apiType = ApiType.INNER_API) public ConfigChangeClusterSyncResponse handle( ConfigChangeClusterSyncRequest configChangeSyncRequest, RequestMeta meta) throws NacosException { ParamUtils.checkParam(configChangeSyncRequest.getTag()); DumpRequest dumpRequest = DumpRequest.create(configChangeSyncRequest.getDataId(), configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant(), configChangeSyncRequest.getLastModified(), meta.getClientIp()); dumpRequest.setGrayName(configChangeSyncRequest.getGrayName()); dumpService.dump(dumpRequest); return new ConfigChangeClusterSyncResponse(); } }

这段代码把@InvokeSource(cluster)(来源限制)、@Secured(INNER_API, signType = CONFIG)(内网鉴权与类型化资源)、@NamespaceValidation@TpsControl@ExtractorManager.Extractor(参数提取校验)全部叠加在同一个handle上,正是本规范第 4、5、6 节的直接实现样例。

7. 当前集群请求分类

规范汇总了当前仓库中已存在的集群请求类别:

类别请求类型归属契约说明
成员上报MemberReportRequestMemberReportResponseCore cluster向对端上报成员元数据,将对端视图标记为UP,重置失败状态,并返回接收方自身的 self member。详细成员规则见 Cluster Membership Spec。
服务端远程上下文ServerReloadRequestServerReloadResponseServerLoaderInfoRequestServerLoaderInfoResponseCore remote重载远程协议上下文,或查询另一节点的连接与负载指标。
配置变更同步ConfigChangeClusterSyncRequestConfigChangeClusterSyncResponseConfig通知对端配置变更,使其刷新 dump 与监听可见状态。Config Notify 语义见 AP Consistency Spec,Config 资源语义由 Config 规范定义。
Naming Distro 传输DistroDataRequestDistroDataResponseNaming 与 Distro在节点间承载 Distro verify、snapshot、sync、delete、query 操作。Distro 归属与收敛规则见 AP Consistency Spec 与 Naming 规范。
插件可用性PluginAvailabilityRequestPluginAvailabilityResponseCore plugin查询节点上的插件可用性。当前代码有处理器,但未注册的 payload 不得被视为有效的 gRPC 契约。

其中 Config 变更同步的处理器即上文 6.2 节展示的 ConfigChangeClusterSyncRequestHandler.java,其对应测试见 ConfigChangeClusterSyncRequestHandlerTest.java;Distro 传输处理器见 DistroDataRequestHandler.java 及测试 DistroDataRequestHandlerTest.java。

领域规范可以新增更多类别,但必须保留本文档中的调用者、处理器、鉴权、来源与 payload 规则。

8. 请求结果与重试语义

集群 RPC 调用方必须自行定义重试或补偿行为。规范给出的规则:

  • 定向调用应显式标识目标成员,并处理目标客户端缺失或已停止的情况;
  • 扇出(fan-out)调用应使用当前成员视图,并容忍部分成功;
  • 异步调用必须定义回调行为、超时处理与重试调度;
  • 超时或传输失败并不能证明远端领域操作没有发生(这是分布式系统的经典"不确定结果"问题);
  • 响应成功只代表单一目标节点的处理器级成功,而非全局收敛;
  • 后台重试任务必须幂等,或用时间戳、版本、操作类型或领域状态做防护,遵循 Task Execution Spec。

例如:Config 变更同步可以通过其异步 notify 任务路径重试;Naming Distro verify 失败可能发出领域事件并调度修复。本地事件行为由 Event Dispatch And NotifyCenter Spec 定义,具体重试规则归属于 Config 与 Naming 的一致性规范。

9. 边界规则

  • 除非接口规范明确声明,内部 RPC不是公共 HTTP、SDK 或开放的 gRPC API;
  • 来源标签、连接存在性或成员资格本身都不是授权。内部请求必须使用服务端身份与鉴权过滤器;
  • JRaft 成员能力元数据是升级信号,不是身份或授权证明;JRaft 请求准入依赖服务端拦截器校验的凭据;
  • ClusterRpcClientProxy必须保持传输导向,不得拥有Config、Naming、AI 或插件 payload 的语义;
  • 领域 payload 不得依赖无界请求体大小、阻塞回调或关键远程线程上的慢速处理器侧远程 IO;
  • 影响滚动升级行为的内部 payload 兼容性字段应在领域层面记录;
  • 新增集群专用处理器应加入 gRPC API 清单,并链接到拥有其语义契约的领域规范。

10. 相关规范索引

  • Foundation Capabilities Spec
  • Cluster Membership Spec
  • Remote Connection Lifecycle Spec
  • Request Filtering And Runtime Context Spec
  • AP Consistency Spec
  • CP Consistency Spec
  • Persistence And Dump Spec
  • Task Execution Spec
  • Event Dispatch And NotifyCenter Spec
  • gRPC API Spec
  • Auth And Permission Spec
  • Config Spec
  • Naming Consistency And Client State Spec
  • Control Plugin Spec

关键源码文件速查

  • 集群调用入口:core/src/main/java/com/alibaba/nacos/core/cluster/remote/ClusterRpcClientProxy.java
  • 处理器注册表:core/src/main/java/com/alibaba/nacos/core/remote/RequestHandlerRegistry.java
  • 来源限制注解:core/src/main/java/com/alibaba/nacos/core/remote/grpc/InvokeSource.java
  • 内网鉴权过滤器:core/src/main/java/com/alibaba/nacos/core/auth/RemoteRequestAuthFilter.java
  • JRaft 身份元数据:core/src/main/java/com/alibaba/nacos/core/distributed/raft/auth/JRaftAuthMetadata.java
  • 来源常量定义:api/src/main/java/com/alibaba/nacos/api/remote/RemoteConstants.java
  • Payload 注册文件:api/src/main/resources/META-INF/services/com.alibaba.nacos.api.remote.Payload
  • 配置变更同步处理器样例:config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandler.java
  • Distro 传输处理器样例:naming/src/main/java/com/alibaba/nacos/naming/remote/rpc/handler/DistroDataRequestHandler.java

【免费下载链接】nacosan easy-to-use dynamic service discovery, configuration and service management platform for building AI cloud native applications.项目地址: https://gitcode.com/GitHub_Trending/na/nacos

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 22:40:17

Axure智慧化后台管理系统设计实战指南

1. 智慧化后台管理系统设计趋势解析当企业数字化转型进入深水区&#xff0c;后台管理系统的设计范式正在发生根本性变革。传统以功能堆砌为主的界面设计已经难以满足现代企业的运营需求&#xff0c;我们正在经历从"功能实现"到"智慧决策"的设计理念跃迁。最…

作者头像 李华
网站建设 2026/9/10 22:39:25

30秒装好 TVBoxOSC:把电视变成大屏文档阅读器

30秒装好 TVBoxOSC&#xff1a;把电视变成大屏文档阅读器 【免费下载链接】TVBoxOSC TVBoxOSC - 一个基于第三方项目的代码库&#xff0c;用于电视盒子的控制和管理。 项目地址: https://gitcode.com/GitHub_Trending/tv/TVBoxOSC TVBoxOSC 是一款电视盒子控制与管理工具…

作者头像 李华
网站建设 2026/9/10 22:39:15

AI写作工具如何助力毕业论文高效完成

1. 毕业季的痛点与AI写作工具的崛起 又到了一年一度的毕业季&#xff0c;对于即将毕业的大学生来说&#xff0c;论文写作无疑是最大的挑战之一。根据我多年指导毕业设计的经验&#xff0c;90%的学生都会遇到以下几个典型问题&#xff1a; 面对空白文档不知如何下笔&#xff0c…

作者头像 李华
网站建设 2026/9/10 22:37:05

CVAT 接入第三方模型:4 步在标注画布上跑出检测框

CVAT 接入第三方模型&#xff1a;4 步在标注画布上跑出检测框 【免费下载链接】cvat Computer Vision Annotation Tool (CVAT) is a leading platform for building high-quality visual datasets for vision AI. It offers open-source, cloud, and enterprise products, as w…

作者头像 李华
网站建设 2026/9/10 22:36:22

(全新整理)投资者保护指数面板数据-北京工商大学2010-2024年

文章目录资料下载地址介绍01、数据介绍02、数据指标03、数据截图项目备注资料下载地址资料下载地址 点击这里下载资料 介绍 01、数据介绍 北京工商大学的投资者保护指数面板数据‌是由该校商学院投资者保护研究院研发的一套衡量中国上市公司投资者保护水平的量化指标体系&a…

作者头像 李华