RPC原理简析
概述
RPC(Remote Procedure Call)远程过程调用,概念就不再赘述了。个人的理解,不管是什么样的RPC框架,总体思路都是服务提供方暴露服务,消费方通过服务方提供的接口使用动态代理获取代理对象,然后调用代理对象的方法,代理对象在内部进行远程调用,获得计算结果。简要示意图如下图所示:

RPC示意图
在这个过程中,有两处关键点。第一是获取代理对象,第二是代理对象与服务提供方建立连接。对于获取代理对象的方式,需要了解Java的动态代理,可参考Java的三种代理模式。总的来说,Java的动态代理(此处只指JDK中生成代理对象的API,不包括cglib)把建立远程连接的细节封装起来,使服务消费方可以在仅已知服务提供方的接口的情况下,可以像调用本地对象的方法一样去调用远程服务。
简单实例
本实例使用socket建立连接,JDK的API做动态代理,主要有服务提供方暴露服务、服务消费方获取代理对象、代理对象与服务提供方建立远程连接并调用三个方面。忽略所有的参数校验、异常。
暴露服务
已知的某个服务的实例对象service,建立ServerSocket服务,并监听指定端口,当有远程连接建立时,创建一个线程,在线程中从输入流中依次读取方法名、参数类型、参数值等信息,并根据方法名和参数执行实例对象service中对应的方法,获得返回结果。
public class RpcExport {
private static int port = 1234;
/**
* 暴露服务
*
* @param service
* 服务的实现
* @param port
* 服务的端口
* @throws Exception
*/
public static void export(final Object service) throws Exception {
System.out.println("Export service " + service.getClass().getName() + " on port " + port);
// 创建socket,开始监听
ServerSocket server = new ServerSocket(port);
while (true) {
final Socket socket = server.accept();
new Thread(new Runnable() {
@Override
public void run() {
ObjectInputStream input = null;
ObjectOutputStream output = null;
try {
// 从监听的socket中获得输入流
input = new ObjectInputStream(socket.getInputStream());
String methodName = input.readUTF();
Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
Object[] arguments = (Object[]) input.readObject();
// 从监听的socket中获得输出流
output = new ObjectOutputStream(socket.getOutputStream());
Method method = service.getClass().getMethod(methodName, parameterTypes);
Object result = method.invoke(service, arguments);
output.writeObject(result);
} catch (Exception e) {
} finally {
try {
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
}
作者:峡客
链接:https://www.jianshu.com/p/d3c7a5bbca09
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

浙公网安备 33010602011771号