RPC基础用法

首先copy下RPC的基本定义:

远程过程调用(Remote Procedure Call,缩写为 RPC)是一个计算机通信协议。 该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。

golang官方库为net/rpc,提供encoding/gob方法实现编解码

RPC相关内容:

数据传输:JSON Protobuf thrift
负载:随机算法 轮询 一致性hash 加权
异常容错:健康检测 熔断 限流

golang编写rpc程序必须满足以下条件:

  • 结构体首字母得大写
  • 必须是公有的方法,即方法首字母大写
  • 只有两个参数,第一个为接收参数,第二个为返回给客户端的指针类型的参数,所以通信时需要将信息封装好才能满足要求
  • 一个返回值:error

大致框架流程:

  • 服务端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import "net/rpc"

// 服务端注册的结构体
type ServiceName struct{
//your field here
}

type Request struct{

}

// 返回给客户端的参数
type ResponseParam struct{

}

// 传参均通过第二个指针类型的参数
func (s *ServiceName)Method1(request Request, response *ResponseParam)error{

}

//主函数
func main(){
// 注册服务
rpc.Register(new(ServiceName))
// 服务绑定到http协议,即通过http来传输
rpc.HandleHttp()
// 监听服务
err := http.ListenAndServe(":8000", nil)
if err != nil{
log.Fatal("Listening error :", err)
}

}

  • 客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 端口号要一致
conn ,err := rpc.DialHTTP("tcp", ":8000")
if err != nil{
log.Fatal("Dailing error :", err)
}
//客户端定义请求
req := Request{}
var res ResponseParam
// 拨号RPC服务
// 第一个参数含义为 服务名.方法名
err = rpc.Call("ServiceName.MethodName", req, &res)
if err != nil{
log.Fatal("Listening error :", err)
}
// 对传回来的res的操作
...

下载 rpcx

服务端编写类似:
注意定义方法时多了第一个参数为context.Context,在并发编程时介绍过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import "context"

type Args struct {
A int
B int
}

type Reply struct {
C int
}

type Arith int

func (t *Arith) Mul(ctx context.Context, args *Args, reply *Reply) error {
reply.C = args.A * args.B
return nil
}

主函数中也是类似函数注册服务:

1
2
3
4
s := server.NewServer()
s.RegisterName("Arith", new(Arith), "")
// or s.Register(new(Arith), "")
s.Serve("tcp", ":8972")