如何实现RPC远程调用

1,718 阅读7分钟

前言
1. 建立连接

  • HTTP
  • Socket

2.请求处理

  • BIO
  • NIO
  • AIO

3.传输协议

  • HTTP协议
  • DUBBO协议
  • WebService协议

4.序列化
5.总结

前言

我们知道RPC是什么,它能做什么,但是它是怎么做的我们却一知半解,今天把一知半解的重新梳理一下!

RPC(Remote Procedure Call)远程方法调用,在不同的物理机上的不同进程内的的方法,可以实现像调用本地方法一样调用远程服务方法,实现服务与服务之间的交互。

那么这个过程又是如何实现的呢?

以人与人之间的打电话交流为例,有一个场景人物A和人物B,A要向B询问一个B一定知道的问题场景如下:

A首先给B打电话,电话接通后,A提出问题,B收到问题后思考得到答案后再通过电话告诉A,A得到了答案后挂断电话。

这个过程就可以类比RPC远程调用,A和B分别是一个服务,A调用B的一个方法

那么首先就是要建立连接,建立连接之后A、B才能通信,通信时双方需要说同样

的语言(不然一个说中文一个说英文,谁也听不懂),而电话就起到传输的作用负

责将A、B说的话传送给彼此。

这里实现一个RPC远程调用的过程就出来了:

  1. 首先建立连接(打电话)

  2. 第二请求处理(B大脑思考)

  3. 第三传输协议(A、B说的语言)

  4. 第四序列化(网络序列化A、B的话)

1. 建立连接

RPC实现的第一步就是连接的问题,只有双方建立连接才能进行下一步操作,双

方以客户端服务端为例进行展开。

我们知道客户端与服务端建立连接可以通过网络中的TCP协议来实现,而通过

TCP连接网络连接有两种最常用的方式:

  • 1、HTTP实现

  • 2、TCP/IP中的Socke

1.1. HTTP

HTTP通信是通过HTTP协议来完成的,一个HTTP请求会建立一个TCP连接,然后发生三次握手的过程,连接建立后进行请求处理,请求结束进行四次挥手断开连接。

1.2. Socket

Socket也叫套接字,是TCP/IP协议中的一个实现,Socket的构造如:

socket=IP地址+端口号

当建立一个连接的时候就会生成一对套接字

Socket:={socket1,socket2}={(IP1:port1),(IP2,port2)},

一个在客户端一个在服务端。Socket通信分为四个步骤:

1、服务端监听:

首先ServerSocket会通过bind()方法绑定一个端口,然后调用listen()方法监听这个端口,等待客户端的连接

2、客户端请求:

ClientSocket调用connect()方法向ServerSocket绑定的端口发送连接请求,请求建立连接。

3、连接确认:

当ServerSocket监听到ClientSocket的连接请求时,会调用accept()方法响应ClientSocket请求,与客户端建立连接。

4、数据传输:

当两个Socket建立连接之后,ClientSocket调用send()方法发送数据,ServerSocket调用receive()方法接收数据,然后ServerSocket处理请求,处理完成之后调用send()方法,ClientSocket调用receive方法接收响应数据。

2. 请求处理

服务端收到客户端的请求之后,该如何处理这个请求呢?比如一个请求过来服务端就分配一个线程去处理该请求或者多个请求使用一个线程去处理,这就是服务端的请求处理方式

在服务端有三种处理方式分别为:

2.1. BIO(同步阻塞)

同步非阻塞的方式即客户端每发送一个请求服务端就生成一个线程处理。但是如果客户端请求过多服务端线程达到瓶颈。另外如果客户端请求没有请求数据,那么服务端线程也会阻塞,造成资源的浪费。

2.2. NIO(同步非阻塞)

同步非阻塞解决的就是BIO中阻塞的问题,即为服务端的一个线程会绑定客户端的多个请求,一个线程通过轮询多个绑定的客户端请求来处理客户端请求,这种方式也就是所谓的I/O多路复用。这样就保证了在服务端单线程的情况下依然可以处理多个客户端请求。

2.3. AIO(异步非阻塞)

异步非阻塞则是更好的一种策略,这种方式很好的解决NIO中同步的问题,通过异步的方式来实现,可以理解为客户端发起一个I/O请求可以直接返回,I/O完成之后会直接通知到客户端,而不需要客户端完成各种I/O的实际操作。这样的方式则很好的解决了客户端等待以及阻塞的问题。

到这里客户端与服务端的连接已经建立并且也实现了彼此的I/O请求,那么接下来就需要对请求的数据做操作,对数据的操作有两个方面一个就是传输协议,另一个就是序列化。

这里可以查看Netty的相关文章。

3. 传输协议

首先说传输协议,传输协议就是客户端与服务端传输数据的一种协议,通过这种协议约束彼此之间的传输,保证彼此的数据都可识别。常见的传输协议有

3.1. HTTP协议

HTTP协议规定了客户端发送请求的方式有GET\POST\DELETE\PUT等,发送的数据包含在一个body中,服务器处理完成返回数据到一个响应体中,响应体包含数据以及状态码等数据。通过这样的一种协议保证了客户端与服务端传输的正确性。

3.2. DUBBO协议

dubbo协议是dubbo提供的一种服务与服务之间传输的一种协议,该协议规定了请求的数据的格式,通过这种格式服务可以进行数据的读取以及解析处理。

3.3. WebService协议

webservice是基于http的soap协议传输数据,webservice协议就是由http+xml组成的,其中xml中会用到wsdl,wsdl是描述语言xml中的一种格式。在使用时需要按照一定的格式匹配xml实现数据的包装。

通过以上协议的分析可以知道,客户端与服务端双方按照规定的协议进行通信以及数据的传输可以实现彼此无障碍的交流。

4. 序列化

说完了传输协议最后再看序列化的问题,那么什么是序列化呢?序列化可以理解为,客户端在发送数据前对该数据按照一定的规则进行编码,经过编码后的数据在网络中传输,最终传输给服务端,服务端接收到数据之后需要按照一定的规则进行解码得到客户端发送的正确数据,这就是序列化和反序列化。

整个过程可以理解为一把钥匙开一把锁的过程,只有匹配上正确的锁芯才能打开锁,序列化反序列化也是这个道理。

那么为什么要进行编码呢?

这就要考虑网络传输的问题,我们希望数据的传输能够最大化的传输,如果一个1G的文件经过编码之后减小到了400M,那么就很好的提高了数据的传输效率。常见的序列化方式分为两类:文本类的有XML以及JSON等,二进制类的有PB/Thrift等。

5、总结

经过以上的四个过程就可以实现一个完整的RPC远程调用,每个过程中具体的实现可以查看相应的书籍学习。

参考资料:

1、《拉钩教育微服务课程》