吐血整理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并在你的下一个项目中高效使用它。

相关新闻

MCSPI控制器模式详解:从信号定义到实战配置的嵌入式SPI开发指南

MCSPI控制器模式详解:从信号定义到实战配置的嵌入式SPI开发指南

1. MCSPI控制器模式:从信号定义到实战配置的深度解析在嵌入式系统开发中,SPI(Serial Peripheral Interface)几乎是工程师的“必修课”。它简单、高效,是连接传感器、存储器、显示屏等外设的“血管”。但当你从标准SPI转…

2026/10/13 11:12:31 阅读更多 →
TI C2000 MibSPI寄存器深度解析:从引脚控制到数据传输实战

TI C2000 MibSPI寄存器深度解析:从引脚控制到数据传输实战

1. 项目概述与核心价值在嵌入式开发,尤其是基于德州仪器(TI)C2000、Hercules等系列MCU的项目中,SPI(串行外设接口)是连接Flash、传感器、ADC/DAC等外设的“血管”。但很多开发者,尤其是刚接触TI…

2026/10/10 21:10:56 阅读更多 →
ZeroOmega:终极浏览器代理管理解决方案,轻松掌控网络访问

ZeroOmega:终极浏览器代理管理解决方案,轻松掌控网络访问

ZeroOmega:终极浏览器代理管理解决方案,轻松掌控网络访问 【免费下载链接】ZeroOmega Manage and switch between multiple proxies quickly & easily. 项目地址: https://gitcode.com/gh_mirrors/ze/ZeroOmega ZeroOmega是一款强大的开源浏览…

2026/10/11 22:54:52 阅读更多 →

最新新闻

从零搭建可视化图表设计工具:数据建模、渲染选型与交互实现

从零搭建可视化图表设计工具:数据建模、渲染选型与交互实现

1. 从零搭建 diagram-design:一个可视化图表设计工具的核心骨架第一次看到 diagram-design 这个标题,很多人会以为它只是一个画流程图的页面。但真正动手做过图表工具的人都知道,这里面藏着一整套关于数据建模、布局计算、交互反馈和渲染性能…

2026/10/14 13:13:15 阅读更多 →
语义地图构建实战:从几何SLAM到语言可交互的机器人空间认知

语义地图构建实战:从几何SLAM到语言可交互的机器人空间认知

1. lingbot-map到底是做什么的:一个能"听懂"指令的机器人地图系统先说结论:这不是那种传统意义上的二维栅格地图或纯几何SLAM项目,而是一个把"语言理解"嵌进"建图与空间认知"全流程的机器人地图系统。名字里的…

2026/10/14 13:13:15 阅读更多 →
公众号流量变现:从阅读量到收益的深度解析

公众号流量变现:从阅读量到收益的深度解析

1. 公众号流量与收益的落差解析最近有位同行在社群里晒出一组数据:单篇公众号文章获得90万阅读量,最终收益却只有80多元。这个案例瞬间引发热议——为什么看似漂亮的流量数据,实际收益却如此惨淡?作为经历过类似情况的从业者&…

2026/10/14 13:13:15 阅读更多 →
知识工作流插件集全攻略:从采集到输出的高效知识管理方案

知识工作流插件集全攻略:从采集到输出的高效知识管理方案

当年我刚开始认真搭建自己的知识工作流时,其实走了不少弯路。每天刷大量资讯、做很多笔记,最后全都散落在各个软件里,真正要用的时候什么都找不到。直到我决定把所有东西统一沉淀到一套插件体系里,情况才有了质变。这套被我整理成…

2026/10/14 13:13:15 阅读更多 →
基于时间序列的磁盘容量预测:从负载指标采集到扩容排期

基于时间序列的磁盘容量预测:从负载指标采集到扩容排期

简介:资源聚焦应用系统负载分析与磁盘容量预测场景,基于Python实现数据挖掘流程,适合正在学习数据挖掘、系统监控或运维预测的开发者参考。通过解析历史负载与磁盘使用数据,帮助掌握从数据预处理、模式发现到趋势预测的完整思路。…

2026/10/14 13:13:15 阅读更多 →
2026最新降AI率实测:DeepSeek+Kimi指令合集,AI感显著降低!

2026最新降AI率实测:DeepSeek+Kimi指令合集,AI感显著降低!

熬夜码出的几万字大作,查阅资料费尽心血,但整体语调却显得机械生硬,急需寻找降低ai的方法。 为了让文字回归真实的表达质感,我拿废弃文档当小白鼠,深度测评了市面上热门的免费降ai率工具。 今天就把这段填坑经验全盘…

2026/10/14 13:12:14 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →