RPC需要解决的问题
- 分布式系统中服务之间的调用问题
- 远程过程调用要能够像本地调用一样,让调用者感知不到远程调用的逻辑。
RPC(Remote Procedure Call)远程过程调用是一个计算机协议,该协议允许运行于一台计算机的程序调用另一台计算机的子程序,程序员无需额外地为交互作用编程。
RPC允许跨机器、跨语言调用计算机程序方法。Golang中实现RPC会使用已经封装好的官方库和第三方库。Go RPC可以利用TCP或HTTP来传递数据,对咬传递的数据使用多种类型的编码解码方案。
RPC协议构建在TCP、UDP、HTTP之上,允许开发者直接调用另一台计算机上的程序,开发者无需额外地为这个调用过程编写网络通信相关代码,使得开发包括网络分布式程序在内的应用程序更加容易。
RPC本质上是一种协议,允许一台计算机程序通过网络从远程计算机程序上请求服务,无需使用者了解底层网络技术。在OSI七层网络通信模型中,RPC跨域了传输层和应用层,使网络分布式程序开发更为容易。
RPC采用C/S(客户端/服务器)的工作模式,请求程序为客户端(client),服务提供程序为服务端(server)。当执行一个远程过程调用时,客户端程序首先会发送一个带有参数的调用信息服务端,然后等待服务端响应。
在服务端,服务进程保持休眠状态直到客户端调用信息到达为止,当一个调用信息到达时,服务端获得进程参数,计算出结果,并向客户端发送应答信息,然后等待下一个调用。最后,客户端接收来自服务端的应答信息,获得进程结果,然后调用执行并继续。
- client调用句柄发送参数,调用本地系统内核,发送网络消息到server等待应答。
- server句柄接收到调用信息,获得进程参数,执行远程过程,计算结果,返回server句柄。
- server句柄返回response,调用远程系统内核,将消息传回本地。
- client句柄从本地主机内核中接收数据后,client接收句柄返回的数据。
RPC在架构上由四部分组成:客户端、客户端存根(Stub)、服务端、服务端存根(Stub)
- 客户端(client)
服务调用发起方,又称为服务消费者。 - 客户端存根(client stub)
客户端存根程序运行在客户端所在的计算机上,主要用来存储要调用的服务端的地址。
客户端存根程序负责将客户端请求远端服务端程序的数据打包成为数据包,通过网络发送给服务端存根程序。
客户端存根接收服务端存根程序发送的调用结果数据包,并解析返回给客户端。 - 服务端(server)
远端的计算机机器上运行的程序,拥有客户端需要调用的方法。 - 服务端存根(server stub)
服务端存根接受客户端存根程序通过网络发送的请求消息数据包,并调用服务端中真正的程序功能方法,完成功能调用。
服务端存根将服务端执行调用的结果进行数据处理打包后发送给客户端存根程序。
如何实现客户端到服务端的调用,想要在网络中任意两台计算机上实现远程过程调用,需要解决很多问题。
- 两台物理机在网络中需要建立稳定且可靠的通信连接
- 两天服务器的通信协议定义问题,两台服务器程序如何识别对方的请求和返回结果。两台计算机必须都能够识别对方发送过来的信息,并且能够识别出其中的请求含义和返回含义,才能进行处理。
RPC是如何实现远程过程调用的的呢?
1.当客户端想要发起一个远程过程调用时,首先通过调用本地客户端存根程序(stub)的方式调用想要使用的功能方法名。
2.客户端存根程序(stub)接收到客户端的功能调用请求后,将客户端请求调用的方法名、携带的参数等信息进行序列化,然后打包成数据包。
3.客户端存根(stub)查找到远程服务端程序的IP地址后,调用Socket通信协议,通过网络发送给服务端。
4.服务端存根程序(stub)接收到客户端发送的数据包信息,通过约定好的协议将数据反序列化,得到请求的方法名和请求参数等参数。
5.服务端存根程序(stub)准备相关数据后,调用本地服务端对应的功能方法,传入对应参数。
6.服务端程序根据已有业务逻辑执行调用过程,等到业务执行结束后,将执行结果返回给服务端存根程序。
7.服务端存根程序将程序调用结果按照约定的协议进行序列化后,通过网络发送给客户端存根程序。
8.客户端存根成匈奴接收到服务端存根程序发送的返回数据后,对数据进行反序列化操作,并将调用返回的数据传递给客户端请求发起者。
9.客户端请求发起者得到调用结果,整个RPC调用过程结束。
RPC相关技术
1.动态代理技术
服务端存根程序和客户端存根程序,在具体编码实现中会使用动态代理技术自动生成一段程序。
2.序列化和反序列化
RPC调用过程中,数据需从一台机器上传递给另外一台机器上。互联网上所有数据都是以字节的形式进行传输,在编码过程中往往使用的都是数据对象,要在互联网上传递数据对象和变量,需要对数据对象做序列化和反序列化处理。
- 序列化:将对象转换为字节序列的过程成为对象的序列化,即编码的过程。
- 反序列化:将字节序列恢复为对象的过程称为对象的反序列化,即解码的过程。
Golang RPC
- net/rpc
Golang官方提供的net/rpc
库使用encoding/gob
进行编码和解码,支持TCP和HTTP数据传输方式,由于其他语言不支持Golang特有的gob
编码方式,因此使用net/rpc
库实现的RPC无法跨语言调用。
- net/rpc/jsonrpc
Golang官方还提供了net/rpc/jsonrpc
库实现RPC方式,JSON RPC采用JSON进行数据编码和解码,因而支持跨语言调用,但目前jsonrpc
库是基于TCP协议实现的,不支持HTTP。
- protobuf
除了Golang官方提供的RPC库,第三方库大部分会采用protobuf
进行数据编码和解码,根据protobuf
声明文件可自动生成RPC方法与服务注册代码,在Golang中可以很方便地进行RPC服务调用。
有疑问加站长微信联系(非本文作者)