Go语言教程第十集 如何玩转Restful和RPC网络编程( 五 )


RPC的核心有两个:通信协议和序列化 。在 HTTP 2 之前,一般采用自定义 TCP 协议的方式进行通信,HTTP 2 出来后,也有采用该协议的,比如流行的gRPC 。
序列化和反序列化是一种把传输内容编码和解码的方式,常见的编解码方式有 JSON、 等 。
在大多数 RPC的架构设计中,都有、 Stub、、 Stub这四个组件,和之间通过进行通信 。RPC 架构如下图所示:
(图片来自于搜索)
下面我为你总结下 RPC 调用的流程:
RPC 调用常用于大型项目,也就是我们现在常说的微服务,而且还会包含服务注册、治理、监控等功能,是一套完整的体系 。
Go 语言 RPC 简单入门
RPC这么流行,Go 语言当然不会错过,在 Go SDK 中,已经内置了 net/rpc 包来帮助开发者实现 RPC 。简单来说,net/rpc 包提供了通过网络访问服务端对象方法的能力 。
现在我通过一个加法运算来演示 RPC的使用,它的服务端代码如下所示:
ch22//.go
package servertype MathService struct {}type Args struct {A, B int}func (m *MathService) Add(args Args, reply *int) error {*reply = args.A + args.Breturn nil}
在以上代码中:
有了这个定义好的服务对象,就可以把它注册到暴露的服务列表中,以供其他客户端使用了 。在Go 语言中,要注册一个一个RPC 服务对象还是比较简单的,通过方法即可,示例代码如下所示:
ch22/.go
package mainimport ("gotour/ch22/server""log""net""net/rpc")func main(){rpc.RegisterName("MathService",new(server.MathService))l, e := net.Listen("tcp", ":1234")if e != nil {log.Fatal("listen error:", e)}rpc.Accept(l)}
以上示例代码中,通过函数注册了一个服务对象,该函数接收两个参数:
然后通过 net. 函数建立一个TCP 链接,在 1234 端口进行监听,最后通过 rpc. 函数在该 TCP 链接上提供这个 RPC 服务 。现在客户端就可以看到这个服务以及它的Add 方法了 。
任何一个框架都有自己的规则,net/rpc 这个 Go 语言提供的RPC 框架也不例外 。要想把一个对象注册为 RPC 服务,可以让客户端远程访问,那么该对象(类型)的方法必须满足如下条件:
总结下来,该方法的格式如下所示:
func (t *T) MethodName(argType T1, replyType *T2) error
这里面的 T1、T2都是可以被 /gob 序列化的 。
有了提供好的RPC 服务,现在再来看下客户端如何调用,它的代码如下所示:
ch22/.go
package mainimport ("fmt""gotour/ch22/server""log""net/rpc")func main(){client, err := rpc.Dial("tcp","localhost:1234")if err != nil {log.Fatal("dialing:", err)}args := server.Args{A:7,B:8}var reply interr = client.Call("MathService.Add", args, &reply)if err != nil {log.Fatal("MathService.Add error:", err)}fmt.Printf("MathService.Add: %d+%d=%d", args.A, args.B, reply)}
在以上实例代码中,首先通过 rpc.Dial 函数建立 TCP 链接,需要注意的是这里的 IP、端口要和RPC 服务提供的一致,确保可以建立 RCP 链接 。
TCP 链接建立成功后,就需要准备远程方法需要的参数,也就是示例中的args 和 reply 。参数准备好之后,就可以通过 Call 方法调用远程的RPC 服务了 。Call 方法有 3 个参数,它们的作用分别如下所示:
调用的远程方法的名字,这里是.Add,点前面的部分是注册的服务的名称,点后面的部分是该服务的方法;
客户端为了调用远程方法提供的参数,示例中是args;
为了接收远程方法返回的结果,必须是一个指针,也就是示例中的& ,这样客户端就可以获得服务端返回的结果了 。
服务端和客户端的代码都写好了,现在就可以运行它们,测试 RPC调用的效果了 。