一、RpcRouter是干嘛的?
想象你开了一家"万能代办公司"(服务端)
客户发来一张工单(RPC请求),上面写着:"帮我算一下11+22"(调用Add函数)
- **Dispatcher(前台)**拿到工单,一看是 算数据业务 ,就把工单丢给了RpcRounter(算数部门主管)
- **RpcRounter(主管)**拿到工单后,不会立刻去算,他要先做两件事:
- 查明册:我们公司有"算加法"这个业务吗?(查找method映射表)
- 验参数:客户填的参数对吗?他说算11+22,但如果他填了"abc" + 22,那肯定不行(参数校验)
3.执行:校验通过了,主管才把具体的数据交给底层的"打工人"(具体业务回调函数)去执行 ,最后把结果返回
总结:RpcRounter的核心任务就是"找方法 "和"验参数"
二、RpcRounter的数据流转文字架构图
bash
======================= 【客户端发来 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(服务描述)。在收到请求时,它利用哈希表快速定位方法,并严格执行参数校验。只有符合规范的请求,才会被真正放行去执行业务逻辑。这种设计不仅保证了服务端的稳定性,也为后续的自动化服务发现和注册提供了数据支撑
