【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 10Python 3.x通信方式公网 TCP自定义 LVProtocol 二进制协议RpcServer端口 9090注册 Add(num1:int, num2:int) → intRpcServer(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) 请求rcode0, result33PASSTC-RPC-002参数类型错误num1 传字符串 “hello”rcode4 (INVALID_PARAM)PASSTC-RPC-003参数缺失只传 num1不传 num2rcode4 (INVALID_PARAM)PASSTC-RPC-004调用不存在方法调用 Multiplyrcode5 (NOT_FOUND_SERVICE)PASSTC-RPC-005非法JSON bodybody 为截断的JSON字符串连接被服务端关闭PASSTC-RPC-006请求-响应ID匹配同一连接发送3个不同ID请求3个响应ID与请求一一对应PASSTC-RPC-007连续多次调用同一连接连续5次Add5次全部返回正确结果PASSTC-RPC-008并发多连接3个并发连接各发2次Add6次全部成功无串扰PASSTC-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.txtTC-RPC-004: 未知方法 Multiply → rcode5 (NOT_FOUND_SERVICE){mtype:3,mtype_name:RSP_R,rcode:5,body:{rcode:5,result:null}}来源:test/log/TC-RPC-004-20260510.txt6.2 发布订阅模块用例 ID用例名称测试步骤预期结果执行结果TC-PUB-001创建主题创建主题 “news”rcode0PASSTC-PUB-002重复创建同一连接创建两次 “news”两次均返回 rcode0PASSTC-PUB-003订阅主题创建 “news” 后订阅rcode0PASSTC-PUB-004发布→订阅者接收发布者发消息检查订阅者订阅者收到 REQ_TOPIC 推送内容一致PASSTC-PUB-005多订阅者1:N3个订阅者1个发布者3个订阅者全部收到相同推送PASSTC-PUB-006取消订阅订阅后取消再发布原订阅者不再收到推送PASSTC-PUB-007删除主题删除后尝试订阅rcode7 (NOT_FOUND_TOPIC)PASSTC-PUB-008订阅不存在主题直接订阅 “ghost_topic”rcode7 (NOT_FOUND_TOPIC)PASSTC-PUB-009发布到无订阅者创建后不订阅直接发布rcode0服务端不崩溃PASSTC-PUB-010订阅者断连订阅者断开发布者再发布服务端不崩溃正常返回 rcode0PASSTC-PUB-011非法操作类型optype99rcode6 (INVALID_OPTYPE)PASS测试结果11/11 全部通过零失败。测试结果摘录点击展开TC-PUB-004: 发布消息 → 订阅者接收推送发布者发布 “hello world” 到 “news” 主题 → 发布者收到 rcode0订阅者收到 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.txtTC-PUB-011: 非法 optype99 → rcode6 (INVALID_OPTYPE){mtype:4,mtype_name:RSP_TOPIC,rcode:6,body:{rcode:6}}来源:test/log/TC-PUB-011-20260510.txt6.3 服务发现模块用例 ID用例名称测试步骤预期结果执行结果TC-SD-001服务注册向注册中心注册 Subtract 方法rcode0PASSTC-SD-002服务发现发现 Add 方法host列表包含 9090 端口提供者PASSTC-SD-003发现不存在服务发现 NoSuchMethodrcode5 (NOT_FOUND_SERVICE)PASSTC-SD-004服务上线通知发现者先登记提供者后注册发现者收到 SERVICE_ONLINE 推送PASSTC-SD-005服务下线通知提供者断开连接发现者收到 SERVICE_OFFLINE 推送PASSTC-SD-006后注册通知已知发现者发现者先登记提供者后注册发现者收到上线通知提供者注册成功PASSTC-SD-007多提供者同方法两个提供者注册 Echo发现返回两个 hostPASSTC-SD-008提供者断连自动注销提供者注册后断开新发现者查询rcode5 (NOT_FOUND_SERVICE)PASSTC-SD-009发现者断连不影响发现者断连新发现者查询仍能正常发现 AddPASSTC-SD-010端到端全流程发现Add→获取地址→直连RPCAdd(11,22)33PASSTC-SD-011非法操作类型optype99rcode6 (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.txt6.4 异常边界测试用例 ID用例名称测试步骤预期结果执行结果TC-EDGE-001空bodybody为空字符串连接关闭或返回解析错误PASSTC-EDGE-002超大body 64KB发送约70KB的消息触发maxDataSize保护连接关闭PASSTC-EDGE-003len字段不匹配len20但实际body200B仅解析len指定的字节不崩溃PASSTC-EDGE-004非法mtypemtype99MessageFactory返回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~009test/test_topic_pubsub.py发布订阅11TC-PUB-001~011test/test_service_discovery.py服务发现11TC-SD-001~011test/test_edge_cases.py异常边界4TC-EDGE-001~004test/test_performance.py性能压测3场景RPC/Topic/Discovery 并发压测7.2 核心测试代码LVProtocol 协议封包test/protocol.pyimportstructdefpack(mtype:int,msg_id:str,body:str)-bytes:按 LVProtocol 格式打包: | len(4B) | mtype(4B) | idLen(4B) | id | body |id_bytesmsg_id.encode(utf-8)body_bytesbody.encode(utf-8)length44len(id_bytes)len(body_bytes)headerstruct.pack(!iii,length,mtype,len(id_bytes))returnheaderid_bytesbody_bytesdefunpack_first(data:bytes)-tuple:解出第一条完整消息返回 (mtype, msg_id, body_str, total_msg_len)iflen(data)12:returnNonelength,mtype,id_lenstruct.unpack(!iii,data[:12])total_msg_len4lengthiflen(data)total_msg_len:returnNonemsg_iddata[12:12id_len].decode(utf-8)body_lenlength-4-4-id_len bodydata[12id_len:12id_lenbody_len].decode(utf-8)return(mtype,msg_id,body,total_msg_len)RPC 调用封装defrpc_request(method:str,params:dict,msg_id:strNone)-bytes:ifmsg_idisNone:msg_idstr(uuid.uuid4())bodyjson.dumps({method:method,parameters:params})returnpack(0,msg_id,body)# MType.REQ_R 0连接池长连接压测test/test_performance.py核心片段defworker_rpc(task_id:int):connsocket.socket(socket.AF_INET,socket.SOCK_STREAM)conn.connect((HOST,RPC_PORT))recv_bufbwhileTrue:idxget_next_index()starttime.perf_counter()conn.sendall(p.rpc_request(Add,{num1:task_id*100idx,num2:idx}))whileTrue:rp.unpack_first(recv_buf)ifrisnotNone:recv_bufrecv_buf[r[3]:]record_latency(idx,time.perf_counter()-start)breakrecv_bufconn.recv(4096)conn.close()八、性能测试8.1 测试方案采用递增压力模型分 5 档从 10 线程逐步提升至 200 线程总请求数从 1000 递增至 10000。前 2 档使用短连接每次请求新建 TCP后 3 档使用连接池长连接复用。覆盖三个场景场景操作端口基础 RPCAdd(num1, num2) 同步调用9090发布订阅创建主题 发布消息7070服务发现查询 Add 方法主机列表80808.2 性能测试结果汇总基础 RPC — Add 方法递增压力档位并发总请求连接模式吞吐量P50P95P99错误基线101,000短连接57.1 req/s160.6ms276.9ms334.6ms0A档503,000短连接211.9 req/s171.7ms554.2ms1159.7ms0B档1005,000短连接209.5 req/s232.0ms1171.7ms1277.6ms0B档(池)1005,000连接池327.9 req/s87.6ms1262.5ms1347.9ms0C档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/目录测试用例设计 测试报告测试总结与优化建议后续可补充 WSL/Linux 本地压测消除公网延迟对性能数据的干扰获取更准确的服务端吞吐量上限可增加 JMeter 集成利用其图形化报告和分布式压测能力异常测试可进一步覆盖断网重连、服务端 OOM、TCP 半开连接等场景建议对性能测试中 P95/P99 延迟偏高的问题做 profiling定位是客户端 Python GIL 还是服务端 EventLoop 排队本报告部分内容由 AI 辅助生成。测试数据均来源于实际执行结果日志文件存放于Auto_test/test/log/目录。