从零实现RPC框架
# 介绍
远程过程调用(Remote Procedure Call,缩写RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。
远程过程调用是一个分布式计算的客户端-服务器(Client/Server)的例子,它简单而又广受欢迎。远程过程调用总是由客户端对服务器发出一个执行“若干过程”请求,并用客户端提供的参数,执行结果将返回客户端。由于存在各式各样的变体和细节差异,对应的派生了各式远程过程调用协议,而且它们并不互相兼容。 为了允许不同的客户端均能访问服务器,许多标准化的RPC系统应运而生了。其中大部分采用接口描述语言(Interface Description Language,IDL),方便跨平台的远程过程调用。
有些实现扩展了远程调用的模型,实现了双向的服务调用,但是不管怎样,调用过程还是由一个客户端发器,服务器提供响应。
# RPC vs RESTful
RPC的消息传输可以通过TCP、UDP或者HTTP等,所以有时候我们称之为RPC over TCP、RPC over HTTP。RPC 通过HTTP 传输消息的时候和RESTful的架构是类似的,但是也有不同。
# 首先我们比较RPC over HTTP 和 RESTful
首先RPC的客户端和服务器端是紧耦合的,客户端需要知道调用的“过程”的名字,“过程”的参数以及它们的类型、顺序等。一旦服务器修改了“过程”的实现,客户端的实现很容易出问题。RPC操作的是方法和过程,它要操作的是方法对象。RESTful操作的是资源(resource),而不是方法。
# 我们再来比较下,RPC over TCP 和 RESTful。
RPC over TCP可以通过长链接减少连接的建立所产生的花费,在调用次数非常巨大的时候(这是目前互联网公司经常遇到的情况,大并发的情况下),这个花费影响是非常巨大的。
# 实现
我们将实现一个服务端,核心是使用了net/rpc package。
- 1.使用net.Listen 来监听RPC请求。
import "net/rpc"
func main() {
l, err := net.Listen("tcp", ":8081")
go func() {
for {
rpc.Accept(l)
}
}()
}
2
3
4
5
6
7
8
9
10
- 2.简单实现一个RPC handler方法。
import "net/rpc"
type User struct {
Name string
Age int32
}
type Handler struct {
}
func New() *Handler {
h := &Handler{}
err := rpc.Register(h)
if err != nil {
panic(err)
}
return h
}
func (rh *Handler) GetUsers(payload int, reply *string) error {
// add logic to return users
return nil
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24