10分钟实现RPC框架
声明
参考自http://javatar.iteye.com/blog/1123915 这位大佬是阿里的专家,日后要多多向他取经。
其实整个流程是个很简单的rpc模型
1.服务端 接受客户端来的socket流, 接受约定为
1.1 方法名
1.2 参数类型
1.3 方法所需参数
2 客户端动态代理生成 代理service,调用该service的方法实则 交给invoke方法处理
逻辑,在该逻辑中实现远程连接,起多个线程。
一次完整的RPC调用流程(同步调用,异步另说)如下:
1)服务消费方(client)调用以本地调用方式调用服务;
2)client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
3)client stub找到服务地址,并将消息发送到服务端;
4)server stub收到消息后进行解码;
5)server stub根据解码结果调用本地的服务;
6)本地服务执行并将结果返回给server stub;
7)server stub将返回结果打包成消息并发送至消费方;
8)client stub接收到消息,并进行解码;
9)服务消费方得到最终结果。
RPC框架的目标就是要2~8这些步骤都封装起来,让用户对这些细节透明。
内容
RpcFramework核心类
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.ServerSocket;
import java.net.Socket;public class RpcFramework {/*** 暴露服务** @param service 服务实现* @param port 服务端口* @throws Exception*/public static void export(final Object service, int port) throws Exception {System.out.println("Export service " + service.getClass().getName() + " on port " + port);ServerSocket server = new ServerSocket(port);//一直轮询,相比while(true),这种方式性能更佳for(;;) {try {//此处阻塞一直等到有consumer请求过来final Socket socket = server.accept();//每来一个消费请求就开启一个新的线程new Thread(() -> {try {try {ObjectInputStream input = new ObjectInputStream(socket.getInputStream());try {//consumer会分三次发送所需要的方法信息,这里的readUTF(),readObject()都会发生阻塞String methodName = input.readUTF();Class<?>[] parameterTypes = (Class<?>[])input.readObject();Object[] arguments = (Object[])input.readObject();ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());try {//获取到目标方法Method method = service.getClass().getMethod(methodName, parameterTypes);//通过反射执行目标方法并返回结果Object result = method.invoke(service, arguments);//将执行结果返回给consumeroutput.writeObject(result);} catch (Throwable t) {output.writeObject(t);} finally {output.close();}} finally {input.close();}} finally {socket.close();}} catch (Exception e) {e.printStackTrace();}}).start();} catch (Exception e) {e.printStackTrace();}}}/*** 引用服务** @param <T> 接口泛型* @param interfaceClass 接口类型* @param host 服务器主机名* @param port 服务器端口* @return 远程服务* @throws Exception*/@SuppressWarnings("unchecked")public static <T> T refer(final Class<T> interfaceClass, final String host, final int port) throws Exception {System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port);//通过JDK动态代理的方式直接返回给调用refer方法的调用者一个被动态代理处理过的 对象return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] {interfaceClass}, new InvocationHandler() {@Override//调用该对象的每个方法都会先去调用下面的逻辑public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {//当方法真实被调用的时候才会发起RPC远程请求provider执行服务Socket socket = new Socket(host, port);try {ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());try {//分三次发送方法所需要的信息output.writeUTF(method.getName());output.writeObject(method.getParameterTypes());output.writeObject(arguments);ObjectInputStream input = new ObjectInputStream(socket.getInputStream());try {//得到服务执行的最终结果Object result = input.readObject();if (result instanceof Throwable) {throw (Throwable) result;}return result;} finally {input.close();}} finally {output.close();}} finally {socket.close();}}});}}
服务接口:
public interface HelloService {String hello(String name);}
服务接口实现:
public class HelloServiceImpl implements HelloService {@Overridepublic String hello(String name) {System.out.println("被调用了");return "Hello" + name;}}
暴露服务类
public class RpcProvider {public static void main(String[] args) throws Exception {HelloService service = new HelloServiceImpl();RpcFramework.export(service, 1234);}
}
引用服务类:
public class RpcConsumer {public static void main(String[] args) throws Exception {//此时获取到的service是被JDK动态代理包装后的service,在调用方法的时候会进行远程调用HelloService service = RpcFramework.refer(HelloService.class, "127.0.0.1", 1234);for (int i = 0; i < Integer.MAX_VALUE; i ++) {String hello = service.hello("World" + i);System.out.println(hello);Thread.sleep(1000);}}
}
总结
我觉得RPC的核心是动态代理和Socket 。
客户端看到的是接口的行为(这个行为没有被实现),服务端放的是接口行为的具体实现。
客户端把行为和行为入参提供给服务端,然后服务端的接口实现执行这个行为,最后再把执行结果返回给客户端。 看起来是客户端执行了行为,但其实是通过动态代理交给服务端执行的。其中,行为和入参这些数据通过socket由客户端传给了服务端。
10分钟实现RPC框架相关推荐
- 10分钟利用django搭建一个博客
以前老是听说ROR开发有多快多块,网上还有朋友为了证明这,专门制作了10分钟利用rails框架搭建一个简易博客的教程,最近学习django框架,觉得django给开发者的便捷也很多,心血来潮来写个10 ...
- RPC框架几行代码就够了
转于作者梁飞在公司的Blog: http://pt.alibaba-inc.com/wp/experience_1330/simple-rpc-framework.html 因为要给百技上实训课,让 ...
- 支持多序列化的RPC框架avro-rpc
为什么80%的码农都做不了架构师?>>> avro-rpc http://code.google.com/p/avro-rpc/ 1.开发背景 公司的运营管理平台建立在J2EE ...
- 10分钟带你彻底搞懂微内核架构
文章目录 十分钟搞懂系列 什么是微内核架构? 如何实现微内核架构? 总结 十分钟搞懂系列 序号 标题 链接 1 10分钟带你彻底搞懂企业服务总线 https://blog.csdn.net/belon ...
- 从零开始写一个RPC框架的详细步骤
http://blog.csdn.net/liu88010988/article/details/51547592 定位 所谓定位就是回答几个问题,我出于什么目的要写一个框架,我的这个框架是干什么的, ...
- 10分钟带你彻底搞懂负载均衡
文章目录 十分钟搞懂系列 负载均衡是如何保证软件系统的生产部署的? 负载均衡分发策略 请求由谁来分发? 服务器端负载均衡器 客户端负载均衡 请求分发到哪去? 静态负载均衡算法 动态负载均衡算法 十分钟 ...
- RPC 框架 Dubbo 从理解到使用(一)
技术架构演变 学习 Dubbo 之前我们有必要先来了解一下互联网技术架构的演变过程及通信方式,方便我们搞清楚为什么需要使用基于 RPC 思想的系列框架. 单一应用架构 通俗地讲,"单体应用( ...
- 10分钟内基于gpu的目标检测
10分钟内基于gpu的目标检测 Object Detection on GPUs in 10 Minutes 目标检测仍然是自动驾驶和智能视频分析等应用的主要驱动力.目标检测应用程序需要使用大量数据集 ...
- windows下rpc框架thrift的环境配置
windows下rpc框架thrift的环境配置 引用链接: https://www.cnblogs.com/49er/p/7193829.html 最近在弄windows下 的Facebook的rp ...
最新文章
- 清科-2018年中国金融科技领域10强
- 江湖永在:金庸先生和阿里人的那些记忆
- python编程15讲答案,[Python编程:从入门到实践] 第十五章:生成数据 习题答案
- OpenCV 色彩空间的改变
- ICLR 2020 | “同步平均教学”框架为无监督学习提供更鲁棒的伪标签
- oracle linux 双机,oracleforlinux双机热备实战完全手册
- 她在哭,但我没资格安慰她......​
- Netty工作笔记0044---Netty案例源码分析
- 【转】 谈谈C++中的swap函数
- socket网络字节序以及大端序小端序
- 《Maven_孔浩》Maven依赖
- unity2019汉化
- 配置华为防火墙ssh ASDM
- fseek函数、ftell函数和rewind函数
- 阿里 P6 到底应该具备哪些核心能力?
- RNN(三) 在SLU中的应用
- 服务器项目描述,项目服务器 2010 SP2 的描述
- asp.net英语四六级考试报名系统
- 我国有较大的AI大模型应用市场,在应用领域具有优势
- Android Studio Template模板 制作模板
热门文章
- 达摩院清华博士:摸鱼,有助于你灵光闪现
- svn增量打包部署_实现Jenkins+svn+bat批处理构建svn版本差异增量的自动化打zip包
- 澎思科技获IDG资本数千万元Pre-A轮融资,推出AI安防全场景软硬件解决方案
- 有哪些 Java 源代码看了后让你收获很多,代码思维和能力有较大的提升?...
- PHP debug_backtrace() 函数
- getconf 取系统配制 --CPU
- VS解决方案的目录结构设置和管理
- OpenFile基于浏览器的免费网络存储管理
- 小强的HTML5移动开发之路(27)—— JavaScript回顾2
- Linux有哪些目录命令,linux最常用的20个命令有哪些