简介
RPC(Remote Procedure Call),即远程过程调用或者远程方法调用。它允许像调用本地方法一样调用远程方法。
RPC是CS(Client/Server)模式,client发送RPC请求,server进行响应。
为啥要用RPC,HTTP不香吗?使用RPC的目的是啥?
- 使调用远程方法像调用本地方法一样简单
- 性能高
我的理解
RPC核心就三点:
- 网络通信。因为是远程调用,肯定需要网络通信,那就需要有client和server,client发送RPC请求,server进行响应。涉及的问题就有:拆包、解包、序列化和反序列化
- 约定协议。
- server端需要告诉client端它提供了哪些远程方法,client才知道它能调用哪些方法,以及做某件事时要调用哪个方法。(类似http接口文档)
- server端还需要告诉client端每个方法的参数列表,client才知道调用方法时如何传参。
- server端还需要告诉client端每个方法的返回结果是啥,client才知道如何解析返回结果。
- client和server端要约定消息格式(RPC请求和响应的消息格式)、序列化和反序列化方式等,只有这样:client端发送RPC请求时才知道怎样构造请求体、如何序列化;server端收到RPC请求时才知道如何反序列化、如何处理请求体;server端返回响应时才知道如何构造响应体、如何序列化;client端收到RPC响应时才知道如何反序列、如何处理响应体......
- server端收到RPC请求,根据协议解析请求体(解析出方法标识、方法参数等),然后路由到本地方法进行本地方法调用。
- 本地方法调用。包括client端的本地调用和server端的本地调用。client端进行本地方法调用后,然后发送RPC请求;server端收到RPC请求,需要路由到本地方法进行本地调用。涉及的问题就有:server如何解析RPC请求、如何路由到本地方法进行本地调用,如何解析还得看client如何传参,所以双方肯定要有个约定、有个协议。
其实,方法签名(方法名+入参列表+返回结果)本身就可以作为一个协议了,根据方法签名client就能知道该方法的标识符是啥、如何传参、如何解析返回结果,根据方法签名server就能知道如何解析参数进行本地方法调用。
RPC如何做到像调用本地方法一样调用远程方法?
其实就是client和server依赖相同的接口,server端实现接口提供真正的服务,client端本地调用接口从而调用远程方法(即调用远程方法就像调用本地方法一样),接口就作为双方约定的协议(这个接口就能告诉client端:server端提供了哪些远程方法、每个方法如何传参、每个方法返回值如何解析)。
至于底层的网络通信、client本地调用后如何发送RPC请求、server收到RPC请求如何进行本地方法调用就是个通用的问题了,可以实现一个框架解决这个通用问题。
RPC调用的大致过程就是:
- client进行本地方法调用
- client发送RPC请求
- server进行本地方法调用
- server返回响应
- client处理返回值
总结一下问题(帮助更好理解RPC)
client侧的问题:
- client怎么知道它干某件事时需要调用哪个远程方法?以及如何传递方法参数?如何处理这个方法的返回结果?
这就需要server端把它提供的所有远程方法的方法元信息告诉client。方法元信息即方法标识符、参数列表、返回结果,方法标识符告诉client该方法是干啥的,参数列表告诉client如何传参,返回结果告诉client如何处理返回值。那如何告诉呢?常见的解决方案是:client和server依赖相同的接口。
- client怎么知道发送RPC请求时需要传哪些请求参数、如何构造请求体、采用何种序列化协议?
- client怎么知道收到RPC响应时采用何种反序列化协议、如何解析响应结果?
server端问题:
- server端收到RPC请求时采用何种反序列化协议、如何解析请求体?
- server端如何将RPC请求路由到对应的本地方法上进行本地调用?
- server端怎么知道返回RPC响应时需要返回哪些信息、如何构造响应体、采用何种序列化协议?
这些问题都需要双方约定好协议!!!
RPC框架就解决了这些通用问题。可以研究下各个RPC框架如何解决这些问题的。
RPC大致原理
RPC框架就负责创建client-stub和server-stub,封装RPC调用过程,开发者只需关注本地方法调用即可,无需关注其他细节。
如下有一张更细节的图(来源于网络):