1
| RPC框架称为远程调用框架,其实现的核心原理就是消费者端使用动态代理来代理一个接口的方法(基于JDK的动态代理,当然如果使用CGLib可以直接使用无接口类的方法),通过加入网络传输编程,传输。..
|
1
| RPC框架称为远程调用框架,其实现的核心原理就是消费者端使用动态代理来代理一个接口的方法(基于JDK的动态代理,当然如果使用CGLib可以直接使用无接口类的方法),通过加入网络传输编程,传输调用接口方法名称,方法参数来给提供者获取,再通过反射,来执行该接口的方法,再将反射执行的结果通过网络编程传回消费者端。
|
现在我们来依次实现这些概念。这里我们做最简单的实现,网络编程使用的是BIO,大家可以使用Reactor模式的Netty来改写性能更好的方式。而网络传输中使用的序列化和反序列化也是Java自带的,当然这样的传输字节比较大,可以使用google的protoBuffer或者kryo来处理。这里只为了方便说明原理。
pom
1 2 3 4 5
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
|
1 2 3
| <groupId>com.guanjian</groupId> <artifactId>rpc-framework</artifactId> <version>1.0-SNAPSHOT</version>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> </project>
|
首先当然是我们要进行远程调用的接口以及接口的方法。
1 2
| public interface HelloService { String sayHello(String content);
|
}
接口实现类
1 2 3
| public class HelloServiceImpl implements HelloService { public String sayHello(String content) { return "hello," + content;
|
}
消费者端的动态代理,如果你是把提供者和消费者写在两个工程中,则提供者端需要上面的接口和实现类,而消费者端只需要上面的接口。
1 2 3 4 5 6 7 8
| public class ConsumerProxy {
|
*/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @SuppressWarnings("unchecked") public static <T> T consume(final Class<T> interfaceClass,final String host,final int port) { return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, (proxy,method,args) -> { Socket socket = new Socket(host, port); try { ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); try { output.writeUTF(method.getName()); output.writeObject(args); ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); try { Object result = input.readObject(); if (result instanceof Throwable) { throw (Throwable) result;
|
}
1 2 3
| return result; } finally { input.close();
|
}
}
}
);
}
提供者端的网络传输和远程方式调用服务
1 2
| public class ProviderReflect { private static final ExecutorService executorService = Executors.newCachedThreadPool();
|
1 2 3 4 5
| /** * RPC监听和远程方法调用 * @param service RPC远程方法调用的接口实例 * @param port 监听的端口 * @throws Exception
|
*/
1 2
| public static void provider(final Object service,int port) throws Exception {
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ServerSocket serverSocket = new ServerSocket(port); while (true) { final Socket socket = serverSocket.accept(); executorService.execute(() -> { try { try { String methodName = input.readUTF(); Object[] args = (Object[]) input.readObject(); Class[] argsTypes = new Class[args.length]; for (int i = 0;i < args.length;i++) { argsTypes[i] = args[i].getClass();
|
}
1 2 3 4 5 6 7 8 9
|
try { Class<?>[] interfaces = service.getClass().getInterfaces(); Method method = null; for (int i = 0;i < interfaces.length;i++) { method = interfaces[i].getDeclaredMethod(methodName,argsTypes); if (method != null) { break;
|
}
1 2 3 4 5
| Object result = method.invoke(service, args); //将反射执行结果写入对外传输的对象流中 output.writeObject(result); } catch (Throwable t) { output.writeObject(t);
|
}
1 2
| } catch (Exception e) { e.printStackTrace();
|
}
}
}
启动提供者端的网络侦听和远程调用
1 2 3 4
| public class RPCProviderMain { public static void main(String[] args) throws Exception { HelloService service = new HelloServiceImpl(); ProviderReflect.provider(service,8083);
|
}
启动消费者的动态代理调用
1 2 3 4 5 6 7
| public class RPCConsumerMain { public static void main(String[] args) throws InterruptedException { HelloService service = ConsumerProxy.consume(HelloService.class,"127.0.0.1",8083); for (int i = 0;i < 1000;i++) { String hello = service.sayHello("你好_" + i); System.out.println(hello); Thread.sleep(1000);
|
}
运行结果
hello,你好_0 hello,你好_1 hello,你好_2 hello,你好_3 hello,你好_4 hello,你好_5
…..
本文标题: 自己实现一个RPC框
发布时间: 2021年01月11日 00:00
最后更新: 2025年12月30日 08:54
原始链接: https://haoxiang.eu.org/2a99d64a/
版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!