8.0 KiB
因收到Google相关通知,网站将会择期关闭。相关通知内容
23 如何在没有接口的情况下进行RPC调用?
你好,我是何小锋。上一讲我们学习了RPC如何通过动态分组来实现秒级扩缩容,其关键点就是“动态”与“隔离”。今天我们来聊聊如何在没有接口的情况下进行RPC调用。
应用场景有哪些?
在RPC运营的过程中,让调用端在没有接口API的情况下发起RPC调用的需求,不只是一个业务方和我提过,这里我列举两个非常典型的场景例子。
场景一:我们要搭建一个统一的测试平台,可以让各个业务方在测试平台中通过输入接口、分组名、方法名以及参数值,在线测试自己发布的RPC服务。这时我们就有一个问题要解决,我们搭建统一的测试平台实际上是作为各个RPC服务的调用端,而在RPC框架的使用中,调用端是需要依赖服务提供方提供的接口API的,而统一测试平台不可能依赖所有服务提供方的接口API。我们不能因为每有一个新的服务发布,就去修改平台的代码以及重新上线。这时我们就需要让调用端在没有服务提供方提供接口的情况下,仍然可以正常地发起RPC调用。
场景二:我们要搭建一个轻量级的服务网关,可以让各个业务方用HTTP的方式,通过服务网关调用其它服务。这时就有与场景一相同的问题,服务网关要作为所有RPC服务的调用端,是不能依赖所有服务提供方的接口API的,也需要调用端在没有服务提供方提供接口的情况下,仍然可以正常地发起RPC调用。
这两个场景都是我们经常会碰到的,而让调用端在没有服务提供方提供接口API的情况下仍然可以发起RPC调用的功能,在RPC框架中也是非常有价值的。
怎么做?
RPC框架要实现这个功能,我们可以使用泛化调用。那什么是泛化调用呢?我们带着这个问题,先学习下如何在没有接口的情况下进行RPC调用。
我们先回想下我在基础篇讲过的内容,通过前面的学习我们了解到,在RPC调用的过程中,调用端向服务端发起请求,首先要通过动态代理,正如[第 05 讲] 中我说过的,动态代理可以帮助我们屏蔽RPC处理流程,真正地让我们发起远程调用就像调用本地一样。
那么在RPC调用的过程中,既然调用端是通过动态代理向服务端发起远程调用的,那么在调用端的程序中就一定要依赖服务提供方提供的接口API,因为调用端是通过这个接口API自动生成动态代理的。那如果没有接口API呢?我们该如何让调用端仍然能够发起RPC调用呢?
所谓的RPC调用,本质上就是调用端向服务端发送一条请求消息,服务端接收并处理,之后向调用端发送一条响应消息,调用端处理完响应消息之后,一次RPC调用就完成了。那是不是说我们只要能够让调用端在没有服务提供方提供接口的情况下,仍然能够向服务端发送正确的请求消息,就能够解决这个问题了呢?
没错,只要调用端将服务端需要知道的信息,如接口名、业务分组名、方法名以及参数信息等封装成请求消息发送给服务端,服务端就能够解析并处理这条请求消息,这样问题就解决了。过程如下图所示:
现在我们已经清楚了解决问题的关键,但RPC的调用端向服务端发送消息是需要以动态代理作为入口的,我们现在得继续想办法让调用端发送我刚才讲过的那条请求消息。
我们可以定义一个统一的接口(GenericService),调用端在创建GenericService代理时指定真正需要调用的接口的接口名以及分组名,而GenericService接口的$invoke方法的入参就是方法名以及参数信息。
这样我们传递给服务端所需要的所有信息,包括接口名、业务分组名、方法名以及参数信息等都可以通过调用GenericService代理的$invoke方法来传递。具体的接口定义如下:
class GenericService {
Object $invoke(String methodName, String[] paramTypes, Object[] params);
}
这个通过统一的GenericService接口类生成的动态代理,来实现在没有接口的情况下进行RPC调用的功能,我们就称之为泛化调用。
通过泛化调用功能,我们可以解决在没有服务提供方提供接口API的情况下进行RPC调用,那么这个功能是否就完美了呢?
回顾下[第 17 讲] 我过的内容,RPC框架可以通过异步的方式提升吞吐量,还有如何实现全异步的RPC框架,其关键点就是RPC框架对CompletableFuture的支持,那么我们的泛化调用是否也可以支持异步呢?
当然可以。我们可以给GenericService接口再添加一个异步方法$asyncInvoke,方法的返回值就是CompletableFuture,GenericService接口的具体定义如下:
class GenericService {
Object $invoke(String methodName, String[] paramTypes, Object[] params);
CompletableFuture