安装rpcx
go get -u -v -tags "reuseport quic kcp zookeeper etcd consul ping" github.com/smallnest/rpcx/...
tags 对应:
- quic: 支持 quic 协议
- kcp: 支持 kcp 协议
- zookeeper: 支持 zookeeper 注册中心
- etcd: 支持 etcd 注册中心
- consul: 支持 consul 注册中心
- ping: 支持 网络质量负载均衡
- reuseport: 支持 reuseport
关于更详细的说明,官方文档已经说的很详细了,地址:https://cn.doc.rpcx.io/part1/quickstart.html
这里上测试代码,更详细代码在后面的项目中会深入使用。
服务端实现
package main
import (
"context"
"errors"
"github.com/smallnest/rpcx/log"
"github.com/smallnest/rpcx/protocol"
"github.com/smallnest/rpcx/server"
)
//结构体和参数名均要求大写。
type Args struct {
A int
B int
}
type Reply struct {
C int
}
//定义了一个叫做 Arith 的 service, 并且为它实现了 Mul 方法。
type Arith int
func (t *Arith) Mul(ctx context.Context, args *Args, reply *Reply) error {
reply.C = args.A * args.B
return nil
}
//加认证函数
func auth(ctx context.Context, req *protocol.Message, token string) error {
if token != "ienxhallgsud87dfalg" {
return errors.New("invalid token")
}
return nil
}
func main() {
s := server.NewServer()
err := s.Register(new(Arith), "") //注册服务
if err != nil {
log.Fatal(err)
}
s.AuthFunc = auth
s.Serve("tcp", ":8972")
}
客户端实现
package main
import (
"context"
"flag"
"log"
"time"
"github.com/smallnest/rpcx/client"
)
var (
addr = flag.String("addr", "localhost:8972", "server address")
)
//测试发现,服务端和客户端的参数,struct内都需要大写
type Args struct {
A int
B int
}
type Reply struct {
C int
}
func main() {
flag.Parse()
d := client.NewPeer2PeerDiscovery("tcp@"+*addr, "")
option := client.DefaultOption
option.ReadTimeout = 10 * time.Second
xclient := client.NewXClient("Arith", client.Failtry, client.RandomSelect, d, option)
//一个XCLinet只对一个服务负责,它可以通过serviceMethod参数来调用这个服务的所有方法。如果你想调用多个服务,你必须为每个服务创建一个XClient。
//一个应用中,一个服务只需要一个共享的XClient。它可以被通过goroutine共享,并且是协程安全的。
//Go 代表异步调用, Call 代表同步调用。
//XClient对于一个服务节点使用单一的连接,并且它会缓存这个连接直到失效或异常。
defer xclient.Close()
xclient.Auth("ienxhallgsud87dfalg")
args := new(Args)
args.A = 10
args.B = 10
reply := new(Reply)
//同步模式
//err := xclient.Call(context.Background(), "Mul", args, reply)
//指定了serviceMethod--Mul
//if err != nil {
// log.Fatalf("failed to call: %v", err)
//}
//log.Printf("%d * %d = %d", args.A, args.B, reply.C)
//异步模式
acall, err := xclient.Go(context.Background(), "Mul", args, reply, nil)
if err != nil {
log.Fatalf("failed to call: %v", err)
}
replyCall := <-acall.Done
if replyCall.Error != nil {
log.Fatalf("failed to call: %v", replyCall.Error)
} else {
log.Printf("%d * %d = %d", args.A, args.B, reply.C)
}
}
网友评论