RPC(Remote Procedure Call)是指远程过程调用,在微服务架构中,各个微服务之间的通信一般使用RPC,比如用户微服务和订单微服务,需求是在用户微服务中查询当前用户的订单,此时用户服务是RPC的请求端,订单微服务是RPC的服务端。
2.1 要实现RPC有3个难点问题:
①如何让客户端知道服务端提供的RPC接口以及方法?
方法一:客户端和服务端在pom文件中同时依赖定义了接口的依赖,服务端需要实现这些接口,提供服务
方法二:比如Spring Cloud Feign是将请求通过动态代理加工成HTTP请求,返回时再将Response反加工过程
②客户端和服务端如何通信?
方法一:Java可以通过NIO/BIO
③客户端如何将参数传递到服务端?
将数据序列化获得二进制数据进行传输 序列化的技术也很多java默认序列化/Json/XML/Protobuf/Hessian 序列化和反序列化效率对比
main线程
public static void main( String[] args )
{
IOrderService orderService = null;
RpcProxyClient rpcProxyClient = new RpcProxyClient();
//代理类的实现
orderService = rpcProxyClient.clientProxy(IOrderService.class,"localhost",8080);
System.out.println(orderService.getOrderList());
}
代理类
public class RpcProxyClient {
public <T>T clientProxy(final Class<T> interfaceCls, String host, int port){
//为了更简洁,创建一个继承InvocationHandler的子类实现具体逻辑
return (T)Proxy.newProxyInstance(interfaceCls.getClassLoader(), new Class<?>[]{
interfaceCls}, new RpcInvocationHandler(host, port));
}
}
InvocationHandler的子类
public class RpcInvocationHandler implements InvocationHandler {
private String host;
private int port;
public RpcInvocationHandler(String host, int port) {
this.host = host;
this.port = port;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//通过socket创建连接
RpcNetTransport rpcNetTransport = new RpcNetTransport(host,port);
rpcNetTransport.createSocket();
//传输请求的数据 请求接口名称,方法名称,参数等
RpcRequest request = new RpcRequest();
request.setArgs(args);
request.setMethodName(method.getName());
request.setTypes(method.getParameterTypes());
request.setClassName(method.getDeclaringClass().getName());
return rpcNetTransport.send(request);
}
}
main线程
public static void main( String[] args ) throws IOException {
IOrderService service = new OrderImpl();
RpcProxyServer rpcProxyServer = new RpcProxyServer();
rpcProxyServer.publisher(service,8080);
}
RpcProxyServer接收客户端请求并处理
public class RpcProxyServer {
//使用多线程防止阻塞
private final ExecutorService executorService = Executors.newCachedThreadPool();
public void publisher(Object service, int port){
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(port);
while (true){
socket = serverSocket.accept();
//具体的处理类
executorService.submit(new ProcessHandler(socket, service));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ProcessHandler 反序列化处理以及反射调用目标方法
public class ProcessHandler implements Runnable {
private Socket socket;
private Object service;
public ProcessHandler(Socket socket, Object service) {
this.socket = socket;
this.service = service;
}
@Override
public void run() {
ObjectInputStream objectInputStream = null;
ObjectOutputStream objectOutputStream = null;
InputStream inputStream = null;
try {
inputStream = socket.getInputStream();
objectInputStream = new ObjectInputStream(inputStream);
RpcRequest request = (RpcRequest)objectInputStream.readObject();
//反射调用目标方法
Object rs = invoke(request);
System.out.println("服务端处理执行的结果" + rs);
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(rs);
objectOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} finally {
//TODO 关闭流
}
}
private Object invoke(RpcRequest request) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class clazz = Class.forName(request.getClassName());
Method method = clazz.getMethod(request.getMethodName(),request.getTypes());
return method.invoke(service, request.getArgs());
}
}
代码github链接:RPC V1