一、RpcRouter是干嘛的?
想象你开了一家“万能代办公司”(服务端)
客户发来一张工单(RPC请求),上面写着:“帮我算一下11+22”(调用Add函数)
- Dispatcher(前台)拿到工单,一看是 算数据业务 ,就把工单丢给了RpcRounter(算数部门主管)
- RpcRounter(主管)拿到工单后,不会立刻去算,他要先做两件事:
- 查明册:我们公司有“算加法”这个业务吗?(查找method映射表)
- 验参数:客户填的参数对吗?他说算11+22,但如果他填了“abc” + 22,那肯定不行(参数校验)
3.执行:校验通过了,主管才把具体的数据交给底层的“打工人”(具体业务回调函数)去执行 ,最后把结果返回
总结:RpcRounter的核心任务就是“找方法”和“验参数”
二、RpcRounter的数据流转文字架构图
======================= 【客户端发来 RPC 请求】 ======================= { "method": "Add", "parameters": { "num1": 11, "num2": 22 } } ↓ ┌─────────────────────────────────────────────────────────────┐ │ 阶段一:Dispatcher 分发 (来自上一层的接线员) │ │ 动作:识别出 MType 是 "RPC请求",将 Body(JSON数据) 交给 RpcRouter│ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 阶段二:RpcRouter 路由与校验 (本模块核心) │ │ │ │ 动作1:提取 method 字段 (如 "Add") │ │ ↓ │ │ 动作2:查表 hash_map<method, describe> │ │ ├── 查到了!找到 "Add" 对应的 ServiceDescribe (服务描述) │ │ └── 没查到?返回错误:方法不存在 │ │ ↓ │ │ 动作3:调用 ServiceDescribe 进行参数校验 │ │ ├── 检查 num1 是不是整型?(是 11,通过) │ │ ├── 检查 num2 是不是整型?(是 22,通过) │ │ └── 校验不通过?返回错误:参数格式错误 │ └─────────────────────────────────────────────────────────────┘ ↓ (校验通过,提取 parameters 数据) ┌─────────────────────────────────────────────────────────────┐ │ 阶段三:业务回调执行 (真正干活的业务函数) │ │ 动作:调用注册好的业务函数 (如 Add(num1, num2)) │ │ 结果:计算出 33,封装成 JSON 响应 │ └─────────────────────────────────────────────────────────────┘ ↓ ======================= 【返回给客户端】 ======================= { "rcode": "OK", "result": 33 }三、结合图片,拆解RpcRouter的内部设计
1. 核心数据结构:hash_map<method, describe>
在 RpcRouter 的底部,有一个非常重要的数据结构,它是一个哈希表(字典)。
Key(键):方法名称(比如
"Add","Translate")。Value(值):
ServiceDescribe(服务描述对象)。
为什么需要这个 map?
当客户端发来"method": "Add"时,RpcRouter 需要以最快的速度(O(1)时间复杂度)找到对应的方法信息,而不是用if-else一个个去比对。
2. 核心对象:ServiceDescribe(服务描述)
图中的上半部分展示了ServiceDescribe包含的四个核心要素。这是参数校验的基石。
在服务注册时,每个方法都必须提供这个描述:
方法名称:比如
Add。参数字段及格式描述:规定参数名必须叫
num1和num2,且必须是整数。参数校验接口:提供一个函数,专门用来比对客户端传来的 JSON 数据是否符合上面的格式。
业务回调函数:如果校验通过了,该去调用哪个具体的函数来执行真正的加法运算。
3. 对外接口:onRpcRequest
图中右侧的onRpcRequest模块,说明 RpcRouter 必须向外暴露一个统一的入口函数,供 Dispatcher 调用。
当网络上有 RPC 请求过来时,Dispatcher 就会触发onRpcRequest,然后把 JSON 数据传进来,内部开始走我们上面画的“查表 -> 校验 -> 执行”流程。
四、 总结
RpcRouter 模块的设计哲学是“先验后行,安全第一”。
在网络通信中,我们绝不能盲目信任客户端传来的数据。如果客户端恶意传入错误的参数(比如本该传 int 却传了 char),直接执行底层业务函数可能会导致服务端崩溃。
因此,RpcRouter 强制要求每个注册的服务都必须提供
ServiceDescribe(服务描述)。在收到请求时,它利用哈希表快速定位方法,并严格执行参数校验。只有符合规范的请求,才会被真正放行去执行业务逻辑。这种设计不仅保证了服务端的稳定性,也为后续的自动化服务发现和注册提供了数据支撑