吐血整理JSON-RPC2.0的原理与应用

发布时间:2026/7/25 16:53:15
吐血整理JSON-RPC2.0的原理与应用 吐血整理JSON-RPC2.0的原理与应用作为一名全栈工程师我在日常开发中经常需要处理不同服务之间的远程调用问题。从RESTful API到gRPC再到WebSocket每种协议都有自己的适用场景。但有一个协议它轻量、跨语言、且天然支持异步调用那就是JSON-RPC。今天我就从原理到实战彻底讲清楚JSON-RPC 2.0。## 什么是JSON-RPC 2.0JSON-RPC是一种无状态的、轻量级的远程过程调用RPC协议。它使用JSON作为数据格式基于HTTP或TCP等传输层协议工作。JSON-RPC 2.0是目前最广泛使用的版本规范简单清晰非常适合微服务间通信、浏览器扩展、区块链应用如以太坊等场景。核心特性-无状态每次调用都是独立的不依赖上下文-轻量级JSON编码易于解析和生成-支持批量调用一次请求可以发送多个调用-通知机制无需响应的单向消息## 协议规范详解JSON-RPC 2.0的请求对象包含以下字段-jsonrpc必须为2.0-method要调用的方法名字符串-params参数可选可以是数组或对象-id请求标识符可用于匹配响应通知时可为null响应对象包含-jsonrpc必须为2.0-result成功时的返回值成功时必需-error失败时的错误对象失败时必需-id与请求相同的id错误对象包含-code错误码整数-message错误描述字符串-data附加数据可选标准错误码--32700解析错误--32600无效请求--32601方法不存在--32602无效参数--32603内部错误--32000~-32099服务器错误## 实战Python实现一个简单的JSON-RPC服务器下面我用Python从零搭建一个JSON-RPC服务器支持基本调用和错误处理。### 示例1基础JSON-RPC服务器python# json_rpc_server.pyimport jsonfrom http.server import HTTPServer, BaseHTTPRequestHandlerclass JSONRPCHandler(BaseHTTPRequestHandler): # 定义可用方法 methods { add: lambda a, b: a b, subtract: lambda a, b: a - b, echo: lambda msg: msg, divide: lambda a, b: a / b # 注意可能除零错误 } def do_POST(self): # 读取请求体 content_length int(self.headers[Content-Length]) body self.rfile.read(content_length).decode(utf-8) try: request json.loads(body) except json.JSONDecodeError as e: # 处理JSON解析错误 self.send_response(200) self.send_header(Content-Type, application/json) self.end_headers() error_response { jsonrpc: 2.0, error: { code: -32700, message: Parse error, data: str(e) }, id: None } self.wfile.write(json.dumps(error_response).encode()) return # 验证jsonrpc版本 if request.get(jsonrpc) ! 2.0: self.send_response(200) self.send_header(Content-Type, application/json) self.end_headers() error_response { jsonrpc: 2.0, error: {code: -32600, message: Invalid Request}, id: request.get(id, None) } self.wfile.write(json.dumps(error_response).encode()) return method_name request.get(method) params request.get(params, []) request_id request.get(id) # 检查方法是否存在 if method_name not in self.methods: response { jsonrpc: 2.0, error: {code: -32601, message: fMethod {method_name} not found}, id: request_id } else: try: # 调用方法 if isinstance(params, list): result self.methods[method_name](*params) elif isinstance(params, dict): result self.methods[method_name](**params) else: result self.methods[method_name]() response { jsonrpc: 2.0, result: result, id: request_id } except Exception as e: # 捕获运行时错误 response { jsonrpc: 2.0, error: {code: -32603, message: Internal error, data: str(e)}, id: request_id } self.send_response(200) self.send_header(Content-Type, application/json) self.end_headers() self.wfile.write(json.dumps(response).encode())if __name__ __main__: server HTTPServer((localhost, 8080), JSONRPCHandler) print(JSON-RPC server running on http://localhost:8080) server.serve_forever()测试命令使用curlbash# 正常调用curl -X POST http://localhost:8080 -H Content-Type: application/json -d {jsonrpc:2.0,method:add,params:[3,5],id:1}# 错误调用方法不存在curl -X POST http://localhost:8080 -H Content-Type: application/json -d {jsonrpc:2.0,method:unknown,params:[],id:2}### 示例2支持批量调用的客户端python# json_rpc_client.pyimport jsonimport requestsclass JSONRPCClient: def __init__(self, endpoint): self.endpoint endpoint def call(self, method, paramsNone, request_id1): 单个RPC调用 :param method: 方法名 :param params: 参数列表或字典 :param request_id: 请求ID :return: 响应结果 payload { jsonrpc: 2.0, method: method, id: request_id } if params is not None: payload[params] params response requests.post(self.endpoint, jsonpayload) response_data response.json() if error in response_data: raise Exception(fRPC Error: {response_data[error]}) return response_data.get(result) def batch_call(self, calls): 批量RPC调用 :param calls: 列表每个元素是(method, params, request_id)元组 :return: 响应列表 batch_payload [] for method, params, request_id in calls: payload { jsonrpc: 2.0, method: method, id: request_id } if params is not None: payload[params] params batch_payload.append(payload) response requests.post(self.endpoint, jsonbatch_payload) response_data response.json() # 返回结果映射按id排序 results {} for item in response_data: if result in item: results[item[id]] item[result] elif error in item: results[item[id]] {error: item[error]} return results def notify(self, method, paramsNone): 发送通知无需响应 :param method: 方法名 :param params: 参数 payload { jsonrpc: 2.0, method: method, params: params } # 通知没有id字段 requests.post(self.endpoint, jsonpayload)# 使用示例if __name__ __main__: client JSONRPCClient(http://localhost:8080) # 单个调用 result client.call(add, [10, 20], 1) print(fadd(10,20) {result}) # 输出: 30 # 使用命名参数 result client.call(subtract, {a: 10, b: 3}, 2) print(fsubtract(10,3) {result}) # 输出: 7 # 批量调用 batch_calls [ (add, [1, 2], 10), (echo, [hello world], 11), (divide, [10, 2], 12), (divide, [10, 0], 13) # 这个会出错 ] results client.batch_call(batch_calls) print(fBatch results: {results}) # 输出: {10: 3, 11: hello world, 12: 5.0, 13: {error: {...}}} # 发送通知 client.notify(echo, [this is a notification])## 高级应用与WebSocket集成在需要实时通信的场景如聊天应用、实时数据推送JSON-RPC与WebSocket结合非常强大。下面是一个基于WebSocket的JSON-RPC实现片段python# websocket_rpc_server.py使用websockets库import asyncioimport jsonimport websocketsclass WebSocketRPCServer: def __init__(self): self.methods { ping: lambda: pong, get_time: lambda: asyncio.get_event_loop().time() } async def handle_message(self, websocket, message): try: request json.loads(message) except json.JSONDecodeError: await websocket.send(json.dumps({ jsonrpc: 2.0, error: {code: -32700, message: Parse error}, id: None })) return method request.get(method) params request.get(params, []) request_id request.get(id) if method in self.methods: try: result self.methods[method](*params) if isinstance(params, list) else self.methods[method](**params) response { jsonrpc: 2.0, result: result, id: request_id } except Exception as e: response { jsonrpc: 2.0, error: {code: -32603, message: str(e)}, id: request_id } else: response { jsonrpc: 2.0, error: {code: -32601, message: Method not found}, id: request_id } await websocket.send(json.dumps(response)) async def handler(self, websocket, path): async for message in websocket: await self.handle_message(websocket, message)# 启动服务器# start_server websockets.serve(WebSocketRPCServer().handler, localhost, 8765)# asyncio.get_event_loop().run_until_complete(start_server)# asyncio.get_event_loop().run_forever()## 应用场景总结JSON-RPC 2.0在实际项目中应用广泛1.微服务通信在Kubernetes集群中服务间调用可以使用JSON-RPC比REST更直接2.区块链以太坊的JSON-RPC接口是开发者与智能合约交互的标准方式3.浏览器扩展Chrome扩展的消息传递机制类似JSON-RPC4.IoT设备轻量级协议适合资源受限设备## 总结JSON-RPC 2.0是一个被低估的协议它的简洁性使其成为很多场景的理想选择。通过本文的代码示例你可以看到- 实现一个JSON-RPC服务器只需要不到100行Python代码- 批量调用可以大幅提升性能减少HTTP连接数- 通知机制适用于日志、监控等单向消息场景- 与WebSocket结合可以实现双向实时通信在实际项目中我建议- 对于内部服务调用优先考虑JSON-RPC而非REST减少HTTP开销- 使用标准的错误码便于客户端统一处理- 注意安全性总是验证请求的jsonrpc字段和参数类型- 考虑使用成熟库如Python的jsonrpcserver、jsonrpcclient减少重复造轮子希望这篇文章能帮你彻底掌握JSON-RPC 2.0并在你的下一个项目中高效使用它。