news 2026/5/11 21:35:36

【JSON-RPC远程过程调用组件库】测试报告

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【JSON-RPC远程过程调用组件库】测试报告

RPC 框架测试报告


一、项目背景

本项目是一个基于 C++ 实现的轻量级 RPC(远程过程调用)框架,旨在解决分布式系统中服务间通信的复杂性。框架提供三大核心能力:基础 RPC 远程调用(同步/异步/回调三种模式)、基于注册中心的服务发现(支持服务注册、发现、上线/下线通知)、主题发布订阅(1:N 消息推送)。底层基于 Muduo 高性能网络库,自定义 TLV 应用层协议解决 TCP 粘包问题,使用 JSON 作为序列化格式。项目为学习型框架,核心价值在于从零理解 RPC 框架的协议编解码、请求路由分发、服务发现机制和发布订阅设计。


二、项目简介

本 RPC 框架包含以下核心功能模块:

  • 基础 RPC 模块:客户端通过 TCP 连接直连服务端,发送 JSON 请求调用注册的远程方法(如 Add),支持同步阻塞、异步 Future、回调三种调用模式。服务端通过 RpcRouter 进行方法路由、参数类型校验和回调执行。

  • 服务注册与发现模块:RegistryServer 作为注册中心,管理服务提供者的注册/注销,维护方法与主机列表的映射。客户端通过 Discoverer 进行服务发现,支持本地缓存和上线/下线通知推送。

  • 发布订阅模块:TopicServer 管理主题的创建/删除/订阅/取消/发布。发布者发布消息后,服务端通过 Topic::pushMessage 遍历订阅者集合并主动推送消息(1:N 推模式)。

  • 协议层:自定义 LVProtocol 二进制协议,格式为| 4B len | 4B mtype | 4B idLen | id 字符串 | JSON body |,所有整数字段使用网络字节序。


三、测试计划

3.1 测试策略

采用黑盒集成测试策略。测试客户端基于 Python 实现,完全独立于 C++ 框架代码,通过 TCP 套接字直接构造 LVProtocol 二进制数据包与服务端交互。测试覆盖三个核心模块的 Happy Path、异常边界、并发场景和性能压测。

3.2 测试环境

组件说明
服务端Ubuntu 云服务器,C++ (g++ 11 + Muduo + jsoncpp)
测试客户端Windows 10,Python 3.x
通信方式公网 TCP,自定义 LVProtocol 二进制协议
RpcServer端口 9090,注册 Add(num1:int, num2:int) → int
RpcServer(registry)端口 9090,启用服务注册,连接注册中心
RegistryServer端口 8080,服务注册与发现
TopicServer端口 7070,主题发布订阅

3.3 提测方式

分模块独立测试:基础 RPC → 发布订阅 → 服务发现 → 异常边界 → 性能压测。各模块用例独立,最后执行全量回归确保无兼容性问题。


四、测试工具

工具用途
Python + pytest自动化功能测试,实现 LVProtocol 协议封包/解包
Python + ThreadPoolExecutor性能压测,多线程并发
自定义 protocol.pyTLV 协议二进制封包/解包,对应 C++ 源码 LVProtocol 类
Git版本管理,代码修改与同步
日志文件测试结果持久化至 test/log/ 目录

五、测试类型与覆盖情况

测试类型覆盖范围发现问题数量备注
功能测试基础RPC、发布订阅、服务发现三大模块核心功能0验证功能逻辑、错误码返回、连接关闭等
异常测试非法参数、非法JSON、非法mtype、超大body0验证服务端容错能力,无崩溃
边界测试空body、len字段篡改、>64KB消息0验证maxDataSize保护和缓冲区处理
并发测试多线程并发调用、粘包场景、连接池复用0验证线程安全与粘包拆分
性能测试5档递增压力(10~200线程 / 1000~10000请求)0零错误,吞吐量天花板~320 req/s

六、功能测试

6.1 基础 RPC 模块

用例 ID用例名称测试步骤预期结果执行结果
TC-RPC-001正常RPC调用发送 Add(11,22) 请求rcode=0, result=33PASS
TC-RPC-002参数类型错误num1 传字符串 “hello”rcode=4 (INVALID_PARAM)PASS
TC-RPC-003参数缺失只传 num1,不传 num2rcode=4 (INVALID_PARAM)PASS
TC-RPC-004调用不存在方法调用 Multiplyrcode=5 (NOT_FOUND_SERVICE)PASS
TC-RPC-005非法JSON bodybody 为截断的JSON字符串连接被服务端关闭PASS
TC-RPC-006请求-响应ID匹配同一连接发送3个不同ID请求3个响应ID与请求一一对应PASS
TC-RPC-007连续多次调用同一连接连续5次Add5次全部返回正确结果PASS
TC-RPC-008并发多连接3个并发连接各发2次Add6次全部成功,无串扰PASS
TC-RPC-009粘包场景快速连发3条请求,TCP合并3条全部正常响应PASS

测试结果:9/9 全部通过,零失败。

测试结果摘录(点击展开)

TC-RPC-001: 正常RPC调用 Add(11,22) → 33

{"mtype":3,"mtype_name":"RSP_R","rcode":0,"body":{"rcode":0,"result":33}}

来源:test/log/TC-RPC-001-20260510.txt

TC-RPC-004: 未知方法 Multiply → rcode=5 (NOT_FOUND_SERVICE)

{"mtype":3,"mtype_name":"RSP_R","rcode":5,"body":{"rcode":5,"result":null}}

来源:test/log/TC-RPC-004-20260510.txt

6.2 发布订阅模块

用例 ID用例名称测试步骤预期结果执行结果
TC-PUB-001创建主题创建主题 “news”rcode=0PASS
TC-PUB-002重复创建同一连接创建两次 “news”两次均返回 rcode=0PASS
TC-PUB-003订阅主题创建 “news” 后订阅rcode=0PASS
TC-PUB-004发布→订阅者接收发布者发消息,检查订阅者订阅者收到 REQ_TOPIC 推送,内容一致PASS
TC-PUB-005多订阅者1:N3个订阅者,1个发布者3个订阅者全部收到相同推送PASS
TC-PUB-006取消订阅订阅后取消,再发布原订阅者不再收到推送PASS
TC-PUB-007删除主题删除后尝试订阅rcode=7 (NOT_FOUND_TOPIC)PASS
TC-PUB-008订阅不存在主题直接订阅 “ghost_topic”rcode=7 (NOT_FOUND_TOPIC)PASS
TC-PUB-009发布到无订阅者创建后不订阅直接发布rcode=0,服务端不崩溃PASS
TC-PUB-010订阅者断连订阅者断开,发布者再发布服务端不崩溃,正常返回 rcode=0PASS
TC-PUB-011非法操作类型optype=99rcode=6 (INVALID_OPTYPE)PASS

测试结果:11/11 全部通过,零失败。

测试结果摘录(点击展开)

TC-PUB-004: 发布消息 → 订阅者接收推送

发布者发布 “hello world” 到 “news” 主题 → 发布者收到 rcode=0,订阅者收到 REQ_TOPIC 推送:

{"publish_response":{"mtype":4,"mtype_name":"RSP_TOPIC","rcode":0},"push_message":{"mtype":1,"body":{"optye":4,"topic_key":"news","topic_msg":"hello world"}}}

来源:test/log/TC-PUB-004-20260510.txt

TC-PUB-011: 非法 optype=99 → rcode=6 (INVALID_OPTYPE)

{"mtype":4,"mtype_name":"RSP_TOPIC","rcode":6,"body":{"rcode":6}}

来源:test/log/TC-PUB-011-20260510.txt

6.3 服务发现模块

用例 ID用例名称测试步骤预期结果执行结果
TC-SD-001服务注册向注册中心注册 Subtract 方法rcode=0PASS
TC-SD-002服务发现发现 Add 方法host列表包含 9090 端口提供者PASS
TC-SD-003发现不存在服务发现 NoSuchMethodrcode=5 (NOT_FOUND_SERVICE)PASS
TC-SD-004服务上线通知发现者先登记,提供者后注册发现者收到 SERVICE_ONLINE 推送PASS
TC-SD-005服务下线通知提供者断开连接发现者收到 SERVICE_OFFLINE 推送PASS
TC-SD-006后注册通知已知发现者发现者先登记,提供者后注册发现者收到上线通知,提供者注册成功PASS
TC-SD-007多提供者同方法两个提供者注册 Echo发现返回两个 hostPASS
TC-SD-008提供者断连自动注销提供者注册后断开,新发现者查询rcode=5 (NOT_FOUND_SERVICE)PASS
TC-SD-009发现者断连不影响发现者断连,新发现者查询仍能正常发现 AddPASS
TC-SD-010端到端全流程发现Add→获取地址→直连RPCAdd(11,22)=33PASS
TC-SD-011非法操作类型optype=99rcode=6 (INVALID_OPTYPE)PASS

测试结果:11/11 全部通过,零失败。

测试结果摘录(点击展开)

TC-SD-010: 端到端全流程 — 服务发现 → 直连 RPC → Add(11,22)=33

{"discovery":{"mtype":5,"mtype_name":"RSP_SERVICE","rcode":0,"body":{"host":[{"host_ip":"127.0.0.1","host_port":9090}],"method":"Add","optye":1,"rcode":0}},"rpc_result":{"mtype":3,"mtype_name":"RSP_R","rcode":0,"body":{"rcode":0,"result":33}}}

来源:test/log/TC-SD-010-20260510.txt

6.4 异常边界测试

用例 ID用例名称测试步骤预期结果执行结果
TC-EDGE-001空bodybody为空字符串连接关闭或返回解析错误PASS
TC-EDGE-002超大body >64KB发送约70KB的消息触发maxDataSize保护,连接关闭PASS
TC-EDGE-003len字段不匹配len=20但实际body>200B仅解析len指定的字节,不崩溃PASS
TC-EDGE-004非法mtypemtype=99MessageFactory返回nullptr,连接关闭PASS

测试结果:4/4 全部通过,零失败。

测试结果摘录(点击展开)

TC-EDGE-002: 超大 body >64KB → 触发 maxDataSize 保护

连接被服务端关闭 (maxDataSize 保护触发),符合预期

来源:test/log/TC-EDGE-002-20260510.txt


七、自动化测试

7.1 测试脚本清单

脚本文件模块用例数说明
test/protocol.py协议层LVProtocol 封包/解包,MType/RCode 枚举
test/test_rpc_basic.py基础RPC9TC-RPC-001~009
test/test_topic_pubsub.py发布订阅11TC-PUB-001~011
test/test_service_discovery.py服务发现11TC-SD-001~011
test/test_edge_cases.py异常边界4TC-EDGE-001~004
test/test_performance.py性能压测3场景RPC/Topic/Discovery 并发压测

7.2 核心测试代码

LVProtocol 协议封包test/protocol.py):

importstructdefpack(mtype:int,msg_id:str,body:str)->bytes:"""按 LVProtocol 格式打包: | len(4B) | mtype(4B) | idLen(4B) | id | body |"""id_bytes=msg_id.encode("utf-8")body_bytes=body.encode("utf-8")length=4+4+len(id_bytes)+len(body_bytes)header=struct.pack("!iii",length,mtype,len(id_bytes))returnheader+id_bytes+body_bytesdefunpack_first(data:bytes)->tuple:"""解出第一条完整消息,返回 (mtype, msg_id, body_str, total_msg_len)"""iflen(data)<12:returnNonelength,mtype,id_len=struct.unpack("!iii",data[:12])total_msg_len=4+lengthiflen(data)<total_msg_len:returnNonemsg_id=data[12:12+id_len].decode("utf-8")body_len=length-4-4-id_len body=data[12+id_len:12+id_len+body_len].decode("utf-8")return(mtype,msg_id,body,total_msg_len)

RPC 调用封装

defrpc_request(method:str,params:dict,msg_id:str=None)->bytes:ifmsg_idisNone:msg_id=str(uuid.uuid4())body=json.dumps({"method":method,"parameters":params})returnpack(0,msg_id,body)# MType.REQ_R = 0

连接池长连接压测test/test_performance.py核心片段):

defworker_rpc(task_id:int):conn=socket.socket(socket.AF_INET,socket.SOCK_STREAM)conn.connect((HOST,RPC_PORT))recv_buf=b""whileTrue:idx=get_next_index()start=time.perf_counter()conn.sendall(p.rpc_request("Add",{"num1":task_id*100+idx,"num2":idx}))whileTrue:r=p.unpack_first(recv_buf)ifrisnotNone:recv_buf=recv_buf[r[3]:]record_latency(idx,time.perf_counter()-start)breakrecv_buf+=conn.recv(4096)conn.close()

八、性能测试

8.1 测试方案

采用递增压力模型,分 5 档从 10 线程逐步提升至 200 线程,总请求数从 1000 递增至 10000。前 2 档使用短连接(每次请求新建 TCP),后 3 档使用连接池长连接复用。覆盖三个场景:

场景操作端口
基础 RPCAdd(num1, num2) 同步调用9090
发布订阅创建主题 + 发布消息7070
服务发现查询 Add 方法主机列表8080

8.2 性能测试结果汇总

基础 RPC — Add 方法递增压力

档位并发总请求连接模式吞吐量P50P95P99错误
基线101,000短连接57.1 req/s160.6ms276.9ms334.6ms0
A档503,000短连接211.9 req/s171.7ms554.2ms1159.7ms0
B档1005,000短连接209.5 req/s232.0ms1171.7ms1277.6ms0
B档(池)1005,000连接池327.9 req/s87.6ms1262.5ms1347.9ms0
C档20010,000连接池317.0 req/s389.7ms1665.1ms1989.4ms0

关键发现

  • 引入连接池后,同等 100 线程下 P50 从 232ms 降至 87.6ms(降幅 62%),吞吐量从 209.5 升至 327.9 req/s(升幅 57%)
  • 吞吐量天花板约 320 req/s,受限于公网延迟(~40ms RTT)+ Python GIL 客户端调度开销
  • 5 档递增压力、累计 24,000 次请求,零错误
  • 服务端 CPU 使用率始终低于 10%,框架自身无性能瓶颈

三场景对比(10线程基线)

场景吞吐量平均延迟P95延迟P99延迟
基础RPC57.1 req/s174.6ms276.9ms334.6ms
发布订阅37.9 req/s262.7ms370.6ms467.2ms
服务发现60.2 req/s165.3ms218.5ms267.0ms

服务发现最快(纯内存查表),发布订阅最慢(每次需 CREATE + PUBLISH 两次往返)。


九、项目测试 Bug 简述

9.1 Bug 优先级统计

本次测试共发现0 个 Bug

  • P0(崩溃级):0 个
  • P1(严重级):0 个
  • P2/P3(一般/轻微级):0 个

9.2 Bug 详情列表

无。


十、遗留问题

本次测试未发现功能或性能层面的 Bug。以下为项目已知的架构层面待改进项(非本次测试发现的缺陷,而是框架设计阶段的已知局限):

编号问题优先级说明
1JSON序列化性能P2相比Protobuf有性能差距,大消息场景可成为瓶颈
2无RPC超时机制P1future.get()无限阻塞,缺少超时保护
3无心跳/健康检查P1注册中心仅被动感知TCP断开,无法检测静默故障
4负载均衡仅轮询P2缺少加权、最少连接等策略
5锁粒度可优化P2Dispatcher回调在锁内执行
6无连接池P2客户端每次发现新地址建新连接
7无流控/背压P2发布订阅场景无发送速率控制

十一、测试结论

整体测试结果:本次项目测试通过。三大核心模块(基础RPC、发布订阅、服务发现)共 35 个功能 + 异常 + 边界用例全部通过,零失败。性能压测 5 档累计 24,000 次请求零错误,框架稳定可靠。

耗时统计:项目测试耗时约 2 小时(含功能测试 31 用例、异常边界 4 用例、性能压测 3 场景 5 档)。

项目补充信息

项目信息
项目框架C++ (g++ 11),Muduo 网络库,jsoncpp,自定义 LVProtocol 协议
代码仓库https://gitee.com/BearOnToilet/json_rpc.git
测试代码Auto_test/test/目录,Python 实现
测试文档Auto_test/doc/目录(测试用例设计 + 测试报告)

测试总结与优化建议

  1. 后续可补充 WSL/Linux 本地压测,消除公网延迟对性能数据的干扰,获取更准确的服务端吞吐量上限
  2. 可增加 JMeter 集成,利用其图形化报告和分布式压测能力
  3. 异常测试可进一步覆盖断网重连、服务端 OOM、TCP 半开连接等场景
  4. 建议对性能测试中 P95/P99 延迟偏高的问题做 profiling,定位是客户端 Python GIL 还是服务端 EventLoop 排队

本报告部分内容由 AI 辅助生成。测试数据均来源于实际执行结果,日志文件存放于Auto_test/test/log/目录。

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

太流批了,发票合并神器

今天给大家推荐两款软件&#xff0c;一款是图片转PDF&#xff0c;一款是发票合并工具。有需要的小伙伴可以下载收藏。 第一款&#xff1a;png2pdf png2pdf是一款png图片转PDF的小工具&#xff0c;这类的工具之前也有推荐过&#xff0c;但是今天这款比较特殊。 只要把图片拖入软…

作者头像 李华
网站建设 2026/5/11 21:28:43

GNSS数据处理避坑指南:手把手教你用Python实现周跳探测(附代码)

GNSS数据处理避坑指南&#xff1a;手把手教你用Python实现周跳探测&#xff08;附代码&#xff09; 在GNSS数据处理的实际工作中&#xff0c;周跳问题就像隐藏在数据中的"地雷"&#xff0c;稍不注意就会导致定位结果出现严重偏差。对于测绘工程专业的学生和刚入行的工…

作者头像 李华
网站建设 2026/5/11 21:27:10

PyTorch模型可视化:从TorchSummary到高效模型调试

1. 为什么我们需要模型可视化工具 第一次训练神经网络时&#xff0c;我盯着黑漆漆的命令行窗口&#xff0c;看着一串串数字飞快滚动&#xff0c;完全不知道模型内部发生了什么。这种"黑箱"体验相信很多初学者都经历过。直到发现了TorchSummary这个神器&#xff0c;才…

作者头像 李华
网站建设 2026/5/11 21:22:29

从零到一:基于Simulink的Buck电路建模与PID控制器自动调参实战

1. Buck电路基础与Simulink建模入门 Buck电路作为开关电源的经典拓扑结构&#xff0c;本质上是一个降压型DC-DC转换器。我第一次接触Buck电路时&#xff0c;最直观的理解就是把它想象成一个"智能水龙头"&#xff1a;输入高压就像全开的水龙头&#xff0c;而我们需要通…

作者头像 李华