简介
在之前的两篇文章rpc
和json-rpc
中,我们介绍了 Go 标准库提供的rpc
实现。在实际开发中,rpc
库的功能还是有所欠缺。今天我们介绍一个非常优秀的 Go RPC 库——rpcx
。rpcx
是一位国人大牛开发的,详细开发历程可以在rpcx
官方博客了解。rpcx
拥有媲美,甚至某种程度上超越gRPC
的性能,有完善的中文文档,提供服务发现和治理的插件。
快速使用
本文示例使用go modules
。
首先是安装:
$ go get -v -tags "reuseport quic kcp zookeeper etcd consul ping" github.com/smallnest/rpcx/...
可以看出rpcx
的安装有点特殊。使用go get -v github.com/smallnest/rpcx/...
命令只会安装rpcx
的基础功能。扩展功能都是通过build tags
指定。为了使用方便,一般安装所有的tags
,如上面命令所示。这也是官方推荐的安装方式。
我们先编写服务端程序,实际上这个程序与用rpc
标准库编写的程序几乎一模一样:
package main
import (
"context"
"errors"
"github.com/smallnest/rpcx/server"
)
type Args struct {
A, B int
}
type Quotient struct {
Quo, Rem int
}
type Arith int
func (t *Arith) Mul(cxt context.Context, args *Args, reply *int) error {
*reply = args.A * args.B
return nil
}
func (t *Arith) Div(cxt context.Context, args *Args, quo *Quotient) error {
if args.B == 0 {
return errors.New("divide by 0")
}
quo.Quo = args.A / args.B
quo.Rem = args.A % args.B
return nil
}
func main() {
s := server.NewServer()
s.RegisterName("Arith", new(Arith), "")
s.Serve("tcp", ":8972")
}
首先创建一个Server
对象,调用它的RegisterName()
方法在服务路径Arith
下注册Mul
和Div
方法。与标准库相比,rpcx
要求注册方法的第一个参数必须为context.Context
类型。最后调用s.Serve("tcp", ":8972")
监听 TCP 端口 8972。是不是很简单?启动服务器:
$ go run main.go
然后是客户端程序:
package main
import (
"context"
"flag"
"log"
"github.com/smallnest/rpcx/client"
)
var (
addr = flag.String("addr", ":8972", "service address")
)
func main() {
flag.Parse()
d := client.NewPeer2PeerDiscovery("tcp@"+*addr, "")
xclient := client.NewXClient("Arith", client.Failtry, client.RandomSelect, d, client.DefaultOption)
defer xclient.Close()
args := &Args{A:10, B:20}
var reply int
err :=xclient.Call(context.Background(), "Mul", args, &reply)
if err != nil {
log.Fatalf("failed to call: %v", err)
}
fmt.Printf("%d * %d = %d\n", args.A, args.B, reply)
args = &Args{50, 20}
var quo Quotient
err = xclient.Call(context.Background(), "Div", args, &quo)
if err != nil {
log.Fatalf("failed to call: %v", err)
}
fmt.Printf("%d * %d = %d...%d\n", arg