Go 每日一库:jsonrpc 库,JSON-RPC 通信实现
【免费下载链接】go-daily-lib Go 每日一库 项目地址: https://gitcode.com/GitHub_Trending/go/go-daily-lib
JSON-RPC(JSON Remote Procedure Call)是一种轻量级的远程过程调用协议,它使用 JSON 格式进行数据交换,易于阅读和实现。在 Go 语言中,标准库 net/rpc/jsonrpc 提供了对 JSON-RPC 1.0 版本的支持,而 go-daily-lib 项目中的 jsonrpc 模块则通过丰富的示例展示了如何在实际项目中应用这一协议。本文将从基础使用到服务发现,带你全面掌握 JSON-RPC 在 Go 中的实践。
快速入门:构建基础 JSON-RPC 服务
服务端实现
首先需要创建一个 RPC 服务端,定义对外提供的方法并注册到 RPC 框架中。以下是一个简单的乘法计算服务实现:
// [jsonrpc/get-started/server/main.go](https://link.gitcode.com/i/625c821476734f8b92b39a758289c840)
package main
import (
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
)
type Args struct {
A, B int
}
type Arith int
func (t *Arith) Multiply(args *Args, reply *int) error {
*reply = args.A * args.B
return nil
}
func main() {
l, err := net.Listen("tcp", ":1234")
if err != nil {
log.Fatal("listen error:", err)
}
arith := new(Arith)
rpc.Register(arith)
for {
conn, err := l.Accept()
if err != nil {
log.Fatal("accept error:", err)
}
go rpc.ServeCodec(jsonrpc.NewServerCodec(conn))
}
}
客户端实现
客户端通过 TCP 连接服务端,并使用 jsonrpc 编解码器发起 RPC 调用:
// [jsonrpc/get-started/client.go](https://link.gitcode.com/i/56cd034ad6a78a6f125b0fc7fc9b0526)
package main
import (
"fmt"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
)
type Args struct {
A, B int
}
func main() {
conn, err := net.Dial("tcp", ":1234")
if err != nil {
log.Fatal("dial error:", err)
}
client := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn))
args := &Args{7, 8}
var reply int
err = client.Call("Arith.Multiply", args, &reply)
if err != nil {
log.Fatal("Multiply error:", err)
}
fmt.Printf("Multiply: %d*%d=%d\n", args.A, args.B, reply)
}
进阶应用:动态服务发现与负载均衡
基于 ZooKeeper 的服务注册与发现
在分布式系统中,服务地址可能动态变化。jsonrpc 模块提供了基于 ZooKeeper 的服务注册与发现示例,通过 ZooKeeper 实现服务节点的自动感知和负载均衡:
// [jsonrpc/zookeeper/client/main.go](https://link.gitcode.com/i/32471f677ec08beecdea3a4b91aa95bc)
package main
import (
"flag"
"fmt"
"math/rand"
"time"
)
var (
zookeeperAddr *string
)
func init() {
zookeeperAddr = flag.String("addr", ":2181", "zookeeper address")
}
type Args struct {
A, B int
}
func main() {
flag.Parse()
fmt.Println(*zookeeperAddr)
p := NewProxy(*zookeeperAddr)
p.Connect()
go p.Run()
for i := 0; i < 10; i++ {
var reply int
args := &Args{rand.Intn(1000), rand.Intn(1000)}
p.Call("Arith.Multiply", args, &reply)
fmt.Printf("%d*%d=%d\n", args.A, args.B, reply)
}
time.Sleep(1 * time.Minute)
for i := 0; i < 100; i++ {
var reply int
args := &Args{rand.Intn(1000), rand.Intn(1000)}
p.Call("Arith.Multiply", args, &reply)
fmt.Printf("%d*%d=%d\n", args.A, args.B, reply)
}
}
多节点部署架构
ZooKeeper 示例中,服务端启动时会将自身地址注册到 ZooKeeper,客户端通过 ZooKeeper 获取服务列表并动态选择节点发起请求。架构如下:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ ZooKeeper │<────>│ 服务节点 1 │<────>│ 客户端 │
└─────────────┘ └─────────────┘ └─────────────┘
↑ ↑
│ │
↓ ↓
┌─────────────┐ ┌─────────────┐
│ 服务节点 2 │<────>│ 服务节点 3 │
└─────────────┘ └─────────────┘
核心功能与最佳实践
1. 协议格式解析
JSON-RPC 请求/响应格式遵循标准规范,以下是一个乘法调用的请求示例:
{
"method": "Arith.Multiply",
"params": [{"A": 7, "B": 8}],
"id": 1
}
响应示例:
{
"id": 1,
"result": 56,
"error": null
}
2. 错误处理机制
当调用出错时,服务端会返回非空的 error 字段,客户端需通过 client.Call 的返回值捕获错误:
err = client.Call("Arith.Multiply", args, &reply)
if err != nil {
log.Fatalf("RPC error: %v", err)
}
3. 性能优化建议
- 连接池复用:避免频繁创建 TCP 连接,可使用连接池管理长连接
- 批量请求:对于高频小请求,可合并为批量请求减少网络往返
- 超时控制:通过
context.WithTimeout实现调用超时保护
总结与扩展阅读
jsonrpc 库为 Go 开发者提供了简洁高效的 RPC 通信能力,适用于微服务间通信、分布式系统协调等场景。更多高级用法可参考:
- 官方文档
- jsonrpc/zookeeper/server/main.go:ZooKeeper 服务注册实现
- jsonrpc/dial/main.go:简化版拨号客户端
通过本文学习,你已掌握 JSON-RPC 的基础使用和分布式扩展方案。实际项目中,可根据需求选择合适的服务发现机制(如 etcd、Consul),并结合 TLS 加密提升通信安全性。
【免费下载链接】go-daily-lib Go 每日一库 项目地址: https://gitcode.com/GitHub_Trending/go/go-daily-lib
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



