JSON-RPC协议

JSON-RPC 是一种轻量级的远程过程调用(RPC)协议,用 JSON 作为数据编码格式。它的核心思想很简单:让客户端可以像调用本地函数一样调用远程服务器上的方法,而消息载荷是一段结构化的 JSON。

一、本质

RPC = Remote Procedure Call。客户端发一段消息说"请帮我执行 subtract(42, 23)",服务端执行后把结果回传。JSON-RPC 就是用 JSON 来描述这段"调用请求"和"结果响应"的协议规范。它与传输层无关------可以跑在 HTTP、WebSocket、TCP、stdio(进程管道)甚至 Unix socket 上,协议本身只规定消息格式。

目前主流是 JSON-RPC 2.0(2010 年发布),相比 1.0 增加了批量调用、命名参数、明确的错误码等。

二、消息格式

  1. 请求(Request)

    {
    "jsonrpc": "2.0",
    "method": "subtract",
    "params": [42, 23],
    "id": 1
    }

四个字段:

jsonrpc:固定 "2.0",标识协议版本

method:要调用的方法名(字符串)

params:参数,可以是数组(按位置)或对象(按名字,如 {"minuend": 42, "subtrahend": 23})

id:请求标识符,服务端必须在响应中原样返回,用于客户端把响应对应到请求

  1. 成功响应

    { "jsonrpc": "2.0", "result": 19, "id": 1 }

  2. 错误响应

    {
    "jsonrpc": "2.0",
    "error": { "code": -32601, "message": "Method not found" },
    "id": 1
    }

result 与 error 必须二选一。错误码有一组保留范围:-32700 解析错误、-32600 无效请求、-32601 方法不存在、-32602 参数无效、-32603 内部错误、-32000~-32099 服务端自定义。

  1. 通知(Notification)

    { "jsonrpc": "2.0", "method": "log", "params": ["hello"] }

不带 id 的请求叫通知,服务端不需要响应。常用于"只发不收"的事件推送。

  1. 批量调用(Batch)

把多个请求装进一个数组一次发出,服务端返回对应数组:

复制代码
[
  { "jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": 1 },
  { "jsonrpc": "2.0", "method": "subtract", "params": [42,23], "id": 2 }
]

三、与其他 RPC/接口形式对比

相比 REST:JSON-RPC 是"调用方法"思维(动词 + 参数),REST 是"操作资源"思维(URL + HTTP 动词)。JSON-RPC 通常一个端点跑所有方法,请求体决定行为。

相比 gRPC:gRPC 用 Protobuf 二进制编码 + HTTP/2,体积小性能高但需要 IDL 和代码生成;JSON-RPC 纯文本、人类可读、零依赖,适合调试和动态语言。

相比 GraphQL:GraphQL 强调按需取数据;JSON-RPC 强调调用动作。

四、典型应用场景

  • 以太坊 / 区块链节点接口:以太坊节点的 eth_blockNumber、eth_call 等就是标准的 JSON-RPC over HTTP/WebSocket
  • 编辑器协议:LSP(Language Server Protocol)、DAP(Debug Adapter Protocol)都是 JSON-RPC over stdio
  • MCP(Model Context Protocol):Anthropic 推的模型上下文协议也基于 JSON-RPC
  • 桌面应用 IPC:VSCode 扩展主进程↔渲染进程、各种 Electron 应用
  • 轻量内部服务:当不想上 gRPC 又嫌 REST 表达动作笨拙时

五、如何发出

HTTP

绝大多数公开的 JSON-RPC 服务(比如以太坊节点)都跑在 HTTP 上。客户端把请求体作为 POST body 发出去,服务端在响应体里返回结果。

curl 示例(调用以太坊主网的 eth_blockNumber):

复制代码
curl -X POST https://eth.llamarpc.com \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'

返回:

复制代码
{"jsonrpc":"2.0","id":1,"result":"0x14a2b3c"}

Node.js / 浏览器 fetch:

复制代码
const res = await fetch("https://eth.llamarpc.com", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    method: "eth_blockNumber",
    params: [],
    id: 1,
  }),
})
const { result, error } = await res.json()

WebSocket

需要服务端主动推送(订阅事件、流式更新)时用 WebSocket。同一个连接上可以发任意多条消息,每条都是独立的 JSON 文本帧。

复制代码
const ws = new WebSocket("wss://eth.llamarpc.com")

ws.onopen = () => {
  ws.send(JSON.stringify({
    jsonrpc: "2.0",
    method: "eth_subscribe",
    params: ["newHeads"],
    id: 1,
  }))
}

ws.onmessage = (e) => {
  const msg = JSON.parse(e.data)
  // 可能是响应(含 id),也可能是服务端推送的通知(含 method)
  console.log(msg)
}

要点:WebSocket 上的 JSON-RPC 是双向的------服务端也能给你发 method 通知;你需要自己用 id 维护一张 pending 表来匹配响应和请求。

进程间:stdio(LSP、MCP 都用这种)

LSP、MCP、各种 CLI 协议跑在 stdin/stdout 上。这种场景必须用 Content-Length 帧头(LSP 风格)或换行分隔(NDJSON 风格)来切分消息,否则 JSON 流没法切开。

LSP / MCP 风格(带 Content-Length):

每条消息前面加一个 HTTP-like 头,空行后跟 JSON 体:

复制代码
Content-Length: 76\r\n \r\n {"jsonrpc":"2.0","method":"initialize","params":{},"id":1}

Node.js 里写一条到子进程:

复制代码
import { spawn } from "node:child_process"
const child = spawn("my-language-server", [])

function send(msg) {
  const body = JSON.stringify(msg)
  const header = `Content-Length: ${Buffer.byteLength(body, "utf8")}\r\n\r\n`
  child.stdin.write(header + body)
}

send({ jsonrpc: "2.0", method: "initialize", params: {}, id: 1 })

读取的时候要先解析 header 拿到长度,再按字节数读 body。

NDJSON 风格(一行一条 JSON):

复制代码
{"jsonrpc":"2.0","method":"ping","id":1}\n

简单但要求 JSON 内不能有真实换行,序列化时确保 JSON.stringify 输出单行即可。

相关推荐
PixelBai2 小时前
JSON过滤使用教程:从入门到精通
javascript·chrome·json
IP老炮不瞎唠2 小时前
采集运行不稳定?分清住宅IP与数据中心代理的差异
网络·网络协议·tcp/ip
森G2 小时前
65、UDP协议(拓展选学)---------网络编程
网络·c++·qt·网络协议·tcp/ip·udp
cyforkk3 小时前
破除网络协议迷雾:TCP、TLS 与 HTTP 的“连环套”逻辑
网络协议·tcp/ip·http
冰^3 小时前
AI CC Switch 解决了什么?
人工智能·gpt·网络协议·chatgpt·github·aigc
master3363 小时前
SSL 证书链问题导致微信小程序无法正常工作
网络协议·微信小程序·ssl
@insist1233 小时前
系统架构设计师-TCP/IP 协议族核心协议详解
网络协议·tcp/ip·系统架构·软考·系统架构设计师·软件水平考试
PixelBai3 小时前
JSON过滤实际应用场景案例
json
一生了无挂14 小时前
Java处理JSON技巧教学(从基础到高阶实战全覆盖)
java·开发语言·json