分布式框架是最近几年的热门。可是要想理解分布式框架着实不易,为了努力跟上时代潮流,特此开了一个专题,起名“我要学好分布式”,通过博客来分享一下我的学习过程,加深我对分布式整体框架的理解。
想要解锁更多新姿势?请访问我的博客
什么是RPC
英文就不说了。中文名远程进程调用协议。顾名思义,客户端在不知道细节的情况下,可以调用远程计算机的api,就像是调用本地方法一样。
RPC协议是一个规范。主流的PRC协议有Dubbo
、Thrif
、RMI
、Webservice
、Hessain
他又一个非常大的特点,网络协议和网络IO对于调用端和服务端来说是透明的(动态代理)
一个RPC框架包含的要素:
RMI
RMI(remote method invocation) , 可以认为是RPC的java版本
RMI使用的是JRMP(Java Remote Messageing Protocol), JRMP是专门为java定制的通信协议,所以他是纯java的分布式解决方案 。
RMI Demo
- 先写个测试用的远程接口,注意接口要抛异常
1 | public interface ISayHello extends Remote { |
2.实现远程接口,并且继承:`UnicastRemoteObject`
1 | public class SayHelloImpl extends UnicastRemoteObject implements ISayHello{ |
3.创建服务器程序: `createRegistry`方法注册远程对象
1 | import java.net.MalformedURLException; |
4.创建客户端程序
1 | public class HelloClient { |
RMI调用过程
流程:
1.去注册中心注册,server端启动服务。
2.注册中心联系stub(存根)。stub用于客户端 ,在j2ee中是这么说的:为屏蔽客户调用远程主机上的对象,必须提供某种方式来模拟本地对象,这种本地对象称为存根(stub),存根负责接收本地方法调用,并将它们委派给各自的具体实现对象
3.server注册对象,然后返回注册对象
4.客户端访问注册中心,(动态代理)返回stub对象
5.stub(存根)远程调用skeleton (骨架 )
6.skeleton 调用相应接口
源码
让我看看核心的注册服务的源码实现
1 | public RegistryImpl(final int var1) throws RemoteException { |
点进UnicastServerRef,找出实现的关系~
点进setup方法,用idea反编码
1 | public Remote exportObject(Remote var1, Object var2, boolean var3) throws RemoteException { |
发现在创建代理,判断当前的var是不是远程stub,如果是就设置骨架。如果不是,就构建target对象。点开代理
1 | public static Remote createProxy(Class<?> var0, RemoteRef var1, boolean var2) throws StubNotFoundException { |
发现在调用远程服务,然后创建了stub。继续点开getRemoteClass()方法
1 | private static Class<?> getRemoteClass(Class<?> var0) throws ClassNotFoundException { |
发现现在在创建实例
好吧,回到createProxy方法,再看看顺着往下走,看看Target var6 = new Target(var1, this, var5, this.ref.getObjID(), var3);
this.ref.exportObject(var6);
的出口对象方法
1 | public void exportObject(Target var1) throws RemoteException { |
1 | public interface Endpoint { |
1 | public void exportObject(Target var1) throws RemoteException { |
一路点下去,找到了tcp出口的方法。这是属于协议层的玩意。
1 | public void exportObject(Target var1) throws RemoteException { |
一路点下去,发现listen。
1 | private void listen() throws RemoteException { |
发现newServerSocket!!!
综上,总体流程和上图一样。
RMI缺陷
1.基于java,支持语言单一
2.服务注册只能注册到我上面分析的那个源码。注册中心挂了以后就完了
3.序列化是用java原生那个方法,效率不好
4.服务端底层是bio方式,性能不好
手写个RMI?
步骤:
编写服务器程序,暴露一个监听, 可以使用socket
编写客户端程序,通过ip和端口连接到指定的服务器,并且将数据做封装(序列化)
服务器端收到请求,先反序列化。再进行业务逻辑处理。把返回结果序列化返回
源码:https://github.com/tengshe789/ForRMI
把源码发布到GitHub了,在把源码粘贴太麻烦了。
结束
此片完了~ 想要了解更多精彩新姿势?
请访问我的个人博客 本篇为原创内容,已在个人博客率先发表,随后CSDN,segmentfault,掘金,简书,开源中国同步发出。如有雷同,缘分呢兄弟。赶快加个好友~