深入理解 JSON-RPC 2.0:轻量级远程调用协议详解

深入理解 JSON-RPC 2.0:轻量级远程调用协议详解

在构建客户端与服务端分离的系统时(比如 CLI 与核心进程通信、微服务之间的调用),我们经常需要一种简单、清晰的远程过程调用(RPC)协议。JSON-RPC 2.0 正是为此而生。它用 JSON 作为数据格式,设计极简,却足够强大,被广泛应用于语言服务器协议(LSP)、区块链节点通信、以及各种内部工具架构中。

本文将从协议背景、核心概念、消息格式、错误处理到实际应用,全面介绍 JSON-RPC 2.0。


1. 什么是 JSON-RPC 2.0?

JSON-RPC 是一种轻量级的远程过程调用协议。它允许客户端向服务端发送「调用某个方法并携带参数」的请求,服务端执行后返回结果或错误。

2.0 是当前主流版本,由 JSON-RPC 工作组在 2010 年左右正式定稿。相比 1.0,2.0 明确了版本字段、统一了错误结构、支持通知(Notification)和批量请求,并去掉了一些历史包袱。

它的核心特点可以概括为三点:

  • 轻量:消息本身就是普通 JSON,几乎没有额外开销。
  • 传输无关:不绑定 HTTP、WebSocket 或任何特定传输层。
  • 语言无关:只要能处理 JSON,任何语言都能实现客户端或服务端。

2. 设计哲学:简单即强大

JSON-RPC 的设计刻意保持克制。它不试图解决路由、认证、流式传输、服务发现等复杂问题,而是把这些留给上层或传输层去处理。

协议只关心一件事:如何用结构化的 JSON 消息表达一次远程函数调用。

这种「只做一件事并做好」的哲学,让它非常适合作为内部通信协议。很多现代系统(比如 VS Code 的 Language Server Protocol)都选择在 JSON-RPC 之上构建更复杂的功能。


3. 三种核心消息类型

JSON-RPC 2.0 定义了三种消息:

3.1 Request(请求)

客户端发起方法调用时使用。必须包含以下字段:

字段 类型 说明
jsonrpc string 必须为 "2.0"
method string 要调用的方法名
params object / array 参数(可选)
id string / number / null 请求标识,用于匹配响应

示例:

json 复制代码
{
  "jsonrpc": "2.0",
  "method": "execute_task",
  "params": {
    "task_id": "t-001",
    "prompt": "写一个快速排序"
  },
  "id": 1
}

params 既可以是命名参数(对象),也可以是位置参数(数组),服务端需要约定好使用哪种风格。

3.2 Response(响应)

服务端处理完请求后返回。成功和失败的结构不同:

成功响应:

json 复制代码
{
  "jsonrpc": "2.0",
  "result": {
    "output": "def quick_sort(arr): ...",
    "status": "success"
  },
  "id": 1
}

错误响应:

json 复制代码
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": "task_id is required"
  },
  "id": 1
}

注意:result 和 error 字段互斥 ,不能同时出现。id 必须与请求中的 id 保持一致,这样才能让客户端正确匹配异步返回的结果。

3.3 Notification(通知)

不需要服务端返回结果的请求。它和普通 Request 几乎一样,但没有 id 字段。

json 复制代码
{
  "jsonrpc": "2.0",
  "method": "log",
  "params": {
    "level": "info",
    "message": "任务已开始执行"
  }
}

服务端收到 Notification 后直接处理,不返回任何响应。这种机制非常适合事件推送、日志上报、状态同步等场景。


4. 错误处理机制

JSON-RPC 2.0 定义了一套标准错误码,方便客户端统一处理:

错误码 含义 说明
-32700 Parse error 服务端收到的不是合法 JSON
-32600 Invalid Request JSON 合法,但不是合法的 Request 对象
-32601 Method not found 方法不存在
-32602 Invalid params 参数无效
-32603 Internal error 服务端内部错误
-32000 到 -32099 Server error 预留给服务端自定义错误

错误对象结构固定:

json 复制代码
{
  "code": -32602,
  "message": "Invalid params",
  "data": "可选的额外信息,可以是任意 JSON 值"
}

data 字段是可选的,常用于传递更详细的调试信息或业务错误细节。


5. 批量请求(Batch)

JSON-RPC 2.0 支持一次发送多个请求。客户端只需把多个 Request 对象放进一个 JSON 数组即可:

json 复制代码
[
  {
    "jsonrpc": "2.0",
    "method": "add",
    "params": [1, 2],
    "id": 1
  },
  {
    "jsonrpc": "2.0",
    "method": "subtract",
    "params": [10, 3],
    "id": 2
  },
  {
    "jsonrpc": "2.0",
    "method": "log",
    "params": {"message": "批量调用完成"}
  }
]

服务端会返回对应的响应数组(Notification 不会出现在响应中)。批量请求能有效减少网络往返次数,适合需要同时执行多个独立操作的场景。


6. 传输层无关性

JSON-RPC 最大的优势之一是不绑定任何传输协议。常见的承载方式包括:

  • stdin / stdout:非常适合 CLI 与本地守护进程通信
  • HTTP:用 POST 发送 JSON 消息,简单直接
  • WebSocket:适合需要双向通信和服务器主动推送的场景
  • Unix Domain Socket / TCP:高性能本地或远程通信
  • 消息队列:作为消息体在 RabbitMQ、NATS 等系统中传递

正是因为这种解耦,同一个 JSON-RPC 服务可以同时支持多种接入方式,而业务逻辑完全不需要修改。


7. 与其他协议的对比

特性 JSON-RPC 2.0 REST gRPC XML-RPC
数据格式 JSON JSON / 其他 Protobuf XML
调用风格 方法调用 资源 + HTTP 动词 方法调用 方法调用
性能 中等 中等 高 较低
可读性 高 高 低(二进制) 中等
流式支持 需自行实现 有限 原生支持 无
学习成本 低 中 中高 低
典型场景 内部工具、LSP、节点通信 公开 API 高性能微服务 老旧系统

JSON-RPC 在「简单」和「表达力」之间取得了很好的平衡。它不像 REST 那样强调资源建模,也不像 gRPC 那样追求极致性能和强类型,而是专注于「远程函数调用」这件事本身。


8. 实际应用场景

  • 编辑器与语言服务器:VS Code、Neovim 等通过 Language Server Protocol(基于 JSON-RPC)与各种语言服务器通信。
  • 区块链节点:以太坊等很多节点使用 JSON-RPC 对外提供接口。
  • CLI 与核心进程:本地工具把核心逻辑做成常驻进程,CLI 通过 JSON-RPC 调用,实现状态共享和快速启动。
  • 插件系统:主程序与插件之间用 JSON-RPC 通信,降低耦合。
  • 微服务内部调用:在对性能要求不极端的场景下,用 JSON-RPC 替代更重的框架。

9. 实现时的注意事项

  1. 必须严格校验 jsonrpc 字段

    只接受 "2.0",拒绝其他值。

  2. id 的处理要小心

    • 请求有 id → 必须返回对应响应
    • 请求没有 id → 当作 Notification,禁止返回响应
    • 响应的 id 必须与请求一致
  3. 错误不能包含 result,成功不能包含 error

    两者互斥。

  4. 批量请求中的顺序

    响应数组的顺序应与请求数组保持一致(虽然规范没有强制,但实际实现中最好保持)。

  5. 大参数与流式数据

    JSON-RPC 本身不适合传输超大二进制数据或真正的流式场景,这时通常需要配合其他机制(如先返回一个资源 ID,再通过其他通道传输数据)。

  6. 安全

    协议本身不提供认证和加密,这些必须由传输层或上层协议解决。


10. 总结

JSON-RPC 2.0 是一个设计克制、实用主义的远程调用协议。它用最简单的 JSON 消息完成了「远程函数调用」这一核心需求,同时保持了极高的可读性和实现灵活性。

它的价值不在于功能有多么丰富,而在于边界清晰。当你需要一个轻量、易调试、不绑定特定传输方式的内部通信协议时,JSON-RPC 2.0 往往是非常合适的选择。

在实际项目中,它可以作为通信的「第一层」,在此之上再构建任务管理、事件通知、流式输出等更高级的能力。理解它的设计取舍,有助于我们在架构决策时做出更清醒的判断。

后记

2026年10月29日于上海,在grok辅助下完成。

相关推荐
腾讯数据架构师1 小时前
任务跑完怎么直接出图表?CubeStudio 任务可视化 ECharts 数据格式实操(CSV/JSON + metric.json,11 种图表一键渲染)
前端·json·echarts·数据可视化
救救孩子把2 小时前
结构化输出为何“格式正确、答案错误”?JSON Schema 的能力边界
android·java·json·agent·agent服务
霸道流氓气质3 小时前
智能表单生成器:结构化输出契约、JSON Schema 驱动渲染与 EAV/JSONB 混合存储的 Vue3 + Spring AI 生产级实战
人工智能·spring·json
SEO_juper4 小时前
Bash 交叉验证 robots.txt 和 sitemap:两个文件自相矛盾,页面永远收录不了
开发语言·python·node.js·json·bash
AI 编程助手GPT1 天前
用 jq 清洗订单 JSON:先隔离异常,再统计已支付金额
json·jq
qq_340040881 天前
idea2021版,vue项目的package.json不展示scripts的绿色箭头
javascript·vue.js·json
骑着蜗牛撵大象3271 天前
大模型 SDK 编译就崩?用 CMakeLists 把 httplib、JSON 与 OpenSSL 装配成可复用的 ChatServer
android·java·c++·http·json·cmake·大模型sdk
rich_Chan.2 天前
阿里云百炼联网搜索教程:web_search 工具开启方法、web_extractor 网页抓取与 json 检索轨迹
前端·阿里云·json