Go 每日一库:jsonrpc 库,JSON-RPC 通信实现

Go 每日一库:jsonrpc 库,JSON-RPC 通信实现

【免费下载链接】go-daily-lib Go 每日一库 【免费下载链接】go-daily-lib 项目地址: 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 通信能力,适用于微服务间通信、分布式系统协调等场景。更多高级用法可参考:

通过本文学习,你已掌握 JSON-RPC 的基础使用和分布式扩展方案。实际项目中,可根据需求选择合适的服务发现机制(如 etcd、Consul),并结合 TLS 加密提升通信安全性。

【免费下载链接】go-daily-lib Go 每日一库 【免费下载链接】go-daily-lib 项目地址: https://gitcode.com/GitHub_Trending/go/go-daily-lib

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值