首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >golang源码分析:jsonrpc(1)

golang源码分析:jsonrpc(1)

作者头像
golangLeetcode
发布2026-03-18 18:17:57
发布2026-03-18 18:17:57
480
举报

随着LLM引用的大火,json-rpc 2.0协议应用越来越广泛,它使用JSON (JavaScript Object Notation) 来编码请求和响应。JSON-RPC 目前有两个主要版本:1.0 和 2.0。2.0 版本在1.0的基础上进行了改进,包括更严格的错误处理和更清晰的规范定义。具体协议内容如下:

JSON-RPC 请求是一个JSON对象,包含以下字段:

代码语言:javascript
复制
jsonrpc: 必须为字符串"2.0",表示协议版本。
method: 必须为字符串,表示要调用的远程过程名。
params: 可选字段,可以是数组或对象,包含方法调用的参数。
id: 可选字段,用于标识请求,如果存在,响应中也必须包含相同的id。

JSON-RPC 响应也是一个JSON对象,包含以下字段:

代码语言:javascript
复制
jsonrpc: 必须为字符串"2.0"。
result: 可选字段,包含方法调用的结果。
error: 可选字段,如果方法调用失败,包含错误信息。
id: 必须与请求中的id相同。

SON-RCP错误处理:JSON-RPC 错误响应包含一个error字段,该字段是一个对象,包含以下字段:

代码语言:javascript
复制
code: 必须为整数,表示错误代码。
message: 必须为字符串,表示错误信息。
data: 可选字段,包含错误的详细数据。

错误代码

JSON-RPC 定义了一些标准的错误代码:

代码语言:javascript
复制
-32700: 解析错误,JSON 解析失败。
-32600: 无效的请求,请求格式不正确。
-32601: 方法未找到,请求的方法不存在。
-32602: 无效的参数,参数格式或值不正确。
-32603: 内部错误,服务器内部错误。
-32000 到 -32099: 服务器错误,服务器定义的错误。

JSON-RPC通常通过HTTP协议进行通信,但也可以使用其他传输协议,如WebSockets。

其实我们按照json-rpc协议的规范来进行传参数和返回值,并使用json格式进行序列化传输,就可以实现json-rpc协议,作为gopher我们不需要自己实现,net/rpc/jsonrpc已经包含了完整的实现。

下面我们通过一个例子分析客户端的源码实现

代码语言:javascript
复制
代码语言:javascript
复制
package main
import (
    "log"
    "net"
    "net/rpc/jsonrpc"
    "time"
    "learn/vscode/jsonrpc/exp1/model"
)
func main() {
    conn, err := net.DialTimeout("tcp", "127.0.0.1:8080", 30*time.Second) // 30秒超时时间
    if err != nil {
        log.Fatalf("客户端发起连接失败:%v", err)
    }
    defer conn.Close()
    client := jsonrpc.NewClient(conn)
    var item model.Item
    client.Call("ServiceHandler.GetName", 1, &item)
    log.Printf("ServiceHandler.GetName 返回结果:%v\n", item)
    var resp model.Response
    item = model.Item{2, "学院君2"}
    client.Call("ServiceHandler.SaveName", item, &resp)
    log.Printf("ServiceHandler.SaveName 返回结果:%v\n", resp)
}

运行结果如下

代码语言:javascript
复制
2025/06/21 22:38:12 ServiceHandler.GetName 返回结果:{1 学院君}
2025/06/21 22:38:12 ServiceHandler.SaveName 返回结果:{true 2 存储成功}

可以看到除了 jsonrpc.NewClient和Call方法外基本和普通的httpclient差不多,下面看下NewClient的具体实现,源码位于net/rpc/jsonrpc/client.go

代码语言:javascript
复制
func NewClient(conn io.ReadWriteCloser) *rpc.Client {
    return rpc.NewClientWithCodec(NewClientCodec(conn))
}

没错,它调用了上一篇介绍的net/rpc包的NewClientWithCodec 方法。只不过参数里的Client的编码解码方式换成了json

代码语言:javascript
复制
func NewClientCodec(conn io.ReadWriteCloser) rpc.ClientCodec {
    return &clientCodec{
        dec:     json.NewDecoder(conn),
        enc:     json.NewEncoder(conn),
        c:       conn,
        pending: make(map[uint64]string),
    }
}

然后是Call方法,没错直接使用了net/rpc的Call方法

代码语言:javascript
复制
func (client *Client) Call(serviceMethod string, args any, reply any) error {
    call := <-client.Go(serviceMethod, args, reply, make(chan *Call, 1)).Done
    return call.Error
}

可以看到,除了编码解码方式完,其他流程和gob编码方式的rpc几乎一样。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档