Hi all, I'd like to share a feature introduced by the following PR: - master: https://github.com/apache/iotdb/pull/19125 IoTDB nodes often need to perform operations that look exactly like client-session operations (tree/table sessions, session pools, subscription providers/consumers) between each other. Before this change, internal callers could not reuse the client session stack directly: such calls either went through the client-facing RPC endpoint with a normal user login, or had to use separate internal interfaces. This PR exposes the client session protocol (IClientRPCService) on the existing DataNode internal RPC endpoint through Thrift service multiplexing, so trusted node-to-node traffic can reuse Session/TableSession and subscription capabilities while staying on the internal port. No new port is opened: the special client RPC shares the original internal RPC host and port, and the legacy unprefixed IDataNodeRPCService route with its mixed-version behavior is unchanged. dn_internal_port └── TMultiplexedProcessor ├── default / no prefix │ └── IDataNodeRPCService.Processor │ └── DataNodeInternalRPCServiceImpl └── "IClientRPCService:<method>" └── IClientRPCService.Processor └── InternalClientRPCServiceImpl The implementation multiplexes the internal endpoint: - The DataNode internal endpoint now runs a TMultiplexedProcessor: unprefixed requests keep going to IDataNodeRPCService as the default route, while IClientRPCService:<method> is routed to the new InternalClientRPCServiceImpl. - The client wraps its protocol with TMultiplexedProtocol only when an internal RPC service name is configured, and preserves that service name across reconnects. - Redirect endpoints are selected per session: internal RPC sessions are redirected to the DataNode internal endpoint, while ordinary client sessions keep using the client RPC endpoint. - New node-commons builders create internal tree/table sessions, pools, subscription sessions, and table pull consumers, without adding any new public session-client API. The internal session login path is deliberately limited to trusted traffic: - It trusts the username supplied by the internal caller and does not require a password or TOTP. - It still requires the user to exist so operation-level authorization can be evaluated, and it does not apply account login policies because this is not a user login. - Operation-level authorization, quota, and query-ownership checks still apply, and no login audit record is emitted for internal session creation. - External clients continue to use the normal password/TOTP flow on the client RPC endpoint. Main changes include: - DataNode: add InternalClientRPCServiceProcessor and InternalClientRPCServiceImpl, register the multiplexed processor, and run the paired session cleanup in InternalServiceThriftHandler.deleteContext. - Client: add RPC-service-name, node-supplier, thread-pool, and available-node hooks in Session/SessionPool/SessionConnection, plus INodeSupplier.isCallerManaged() for externally managed suppliers. - node-commons: add internal session/pool/subscription builders, and split SessionInfo into orthogonal internalRpcSession and internalDatabaseSession flags so the endpoint family does not imply database-internal privileges. - Redirect path: Analysis/IAnalysis and insert plan nodes now carry TDataNodeLocation and resolve the internal vs client endpoint at redirect time. - ConfigNode/protocol: add TDataNodeInfo.internalRpcEndPoint; internal subscription discovery uses it, and THREAT_MODEL.md documents the new dn_internal_port surface. - Tests: InternalSessionIT, InternalTableSessionIT, InternalSessionRedirectIT, InternalTableSessionRedirectIT, InternalSubscriptionTableIT (with internal SSL), InternalSessionProtocolTest, and InternalServiceThriftHandlerTest. Feedback and suggestions are welcome.
大家好, 我想分享以下 PR 中新增的一个功能: - master:https://github.com/apache/iotdb/pull/19125 IoTDB 的节点之间经常需要执行一些与客户端会话完全同构的操作(树模型/表模型 Session、Session 池、订阅 provider/consumer)。在此之前,内部调用方无法直接复用客户端会话这套能力,只能走面向客户端的 RPC 端口并执行正常用户登录,或者改用另外的内部接口。本 PR 通过 Thrift 服务多路复用,在 DataNode 原有的 internal RPC 端口上额外支持了一套特殊的 client RPC,把客户端会话协议(IClientRPCService)暴露出来,使可信的节点间通信可以复用 Session/TableSession 和订阅能力,同时仍然停留在内部端口。这里并没有新开端口:这套特殊的 client RPC 复用原 internal RPC 的 host 和 port,原有的无前缀 IDataNodeRPCService 路由及其混合版本行为保持不变。 dn_internal_port └── TMultiplexedProcessor ├── default / no prefix │ └── IDataNodeRPCService.Processor │ └── DataNodeInternalRPCServiceImpl └── "IClientRPCService:<method>" └── IClientRPCService.Processor └── InternalClientRPCServiceImpl 实现上对内部端口做了服务多路复用: - DataNode 内部端口现在使用 TMultiplexedProcessor:无前缀请求仍按默认路由交给 IDataNodeRPCService,IClientRPCService:<method> 则路由到新增的 InternalClientRPCServiceImpl。 - 客户端只有在配置了内部 RPC 服务名时才用 TMultiplexedProtocol 包装协议,并在重连时保留该服务名。 - 重定向按会话选择端点:internal RPC 会话重定向到 DataNode 内部端点,普通客户端会话仍使用客户端 RPC 端点。 - node-commons 新增了内部树模型/表模型 Session、Session 池、订阅会话和表模型拉取消费者的 builder,且不会新增对外的公共 session 客户端 API。 内部会话的登录路径只面向可信流量: - 信任内部调用方传入的用户名,不要求密码或 TOTP。 - 仍要求用户存在,以便进行权限判定;因为这不是用户登录,所以不应用账号登录策略。 - 仍会执行操作级鉴权、配额和查询归属校验,内部会话创建不会记录登录审计日志。 - 外部客户端继续在客户端 RPC 端口使用正常的密码/TOTP 流程。 主要修改包括: - DataNode:新增 InternalClientRPCServiceProcessor 与 InternalClientRPCServiceImpl,注册多路复用 processor,并在 InternalServiceThriftHandler.deleteContext 中成对清理会话。 - 客户端:在 Session/SessionPool/SessionConnection 中新增 RPC 服务名、节点 supplier、线程池与可用节点初始化钩子,并新增 INodeSupplier.isCallerManaged() 支持外部托管的 supplier。 - node-commons:新增内部 Session/池/订阅 builder,并把 SessionInfo 拆成相互独立的 internalRpcSession 和 internalDatabaseSession 两个标记,避免把端点类型误当作数据库内部权限。 - 重定向链路:Analysis/IAnalysis 和各写入计划节点改为携带 TDataNodeLocation,在重定向时再决定使用内部端点还是客户端端点。 - ConfigNode/协议:新增 TDataNodeInfo.internalRpcEndPoint;内部订阅发现改用该端点,并在 THREAT_MODEL.md 中记录新的 dn_internal_port 面。 - 测试:InternalSessionIT、InternalTableSessionIT、InternalSessionRedirectIT、InternalTableSessionRedirectIT、InternalSubscriptionTableIT(启用内部 SSL)、InternalSessionProtocolTest、InternalServiceThriftHandlerTest。 欢迎大家提出反馈和建议。 Best regards, Wenwei Shu
