JavaGuide-RPC框架项目学习笔记-未完待续
Posted rotk2015
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaGuide-RPC框架项目学习笔记-未完待续相关的知识,希望对你有一定的参考价值。
本笔记为JavaGuide哥RPC项目的学习笔记,感谢Guide哥的无私奉献!
-
RPC,Remote Procedure Call,远程过程(方法)调用,本地上某个服务的方法要调用远程主机上某个服务的方法。
-
RPC的原理。简单讲主要涉及三个问题:如何告知远程主机需调用的目标方法是哪个?(在两边同时维护一个<函数名,ID>映射表)将本地的参数传输给远程主机时,要将其转变为适合传输的字节流(序列化,反序列化)。使用什么协议传输?(TCP、UDP,HTTP)
-
首先,根据作者的教程以及POM文件查看项目依赖关系。
-
由于对mave不熟悉,即使理清了依赖关系,对应打了jar包,编译时也报了错。后来发现是因为没有将包install到本地仓库,导致不可见。(关键词:maven生命周期
-
SocketRpcClient/Server,serviceDiscovery/Registry,核心类:ExtensionLoader(),扩展加载器(写法上参照了dubbo,而dubbo的写法,个人感觉似乎与JDK的ClassLoader有点像)。维护加载器缓存(类级),以及扩展实例缓存(类级、对象级),扩展类型缓存(对象级)。
通过对应加载器,获取扩展实例时,先从“本地的”对象级缓存中找。若未命中,获取扩展类型,以之为Key从“全局的”类级实例缓存中找,命中则更新本地缓存。若仍未命中,则反射创建扩展实例并更新类级、对象级实例缓存。
获取扩展类型是通过“本地的”对象级扩展类型缓存获取,若未命中则解析本地配置文件,加载类型并更新缓存。
-
单例模式,DCL,指令重排,volatile(内部类、枚举)。
-
ConcurrentMap,get取值后判空用putIfAbsent而非put是为了DCL?
-
ExtensionLoader()的实现里用到了Holder类,该类将对象包裹,并提供一个volatile限定的引用(我看了下,ExtensionLoader不可变,成员均final修饰,故无法volatile限定,意思是可以加一层间接实现 final+volatile 共存?)。
-
行吧,进度有点慢,考虑到该项目迭代至今扩展了很多功能,如果一直纠结于细节,对于RPC的主旨部分很难快速了解。故在调研一番后,打算从该带佬发布的第一个正式版开始看,提纲挈领。
-
client使用动态代理的原因:
- 相同的模式:对于每种方法,进行RPC时我们都要做同样的事情:将相关信息打包、序列化发送给服务端,接受服务端回信并反序列化相关结果。故我们需要实现一个类做这些事情,但目前还不一定要用代理的方式。
- 未知的方法:我们希望像调用本地方法那样调用远程方法,因此要求那个类必须提供对应的方法。我们可以通过继承同一接口的方式实现方法的统一(这也是JDK动态代理的要求,只能代理实现接口实现类),但这个接口信息,要等到运行时才能确定,故我们必须用动态代理的方式。
-
lombok @Builder 建造者模式。实现方法,设置内部类作为中间对象传参,另:通过返回this可以实现method的链式调用。
-
RPC时要传送方法的名称、参数类型,以便通过反射匹配获取对应方法对象-Method。获取Method后,调用invoke即可实现方法调用(若方法有参数,此时传入,此外,这说明在客户端还需传送方法的实参)。
-
Java序列化通过ObjectOutputStream、ObjectInputStream的writeObject、readObject。序列化对象类需要继承Serializable标记接口。此外,为了避免序列化后,类发生改动产生的版本不一致问题,编译器为Serializable实现类自动添加serialVersionUID属性,当反序列化时,若检测到serialVersionUI与本地类的一致,则报错。serialVersionUID可手动添加,当进行兼容性升级时,不要改动serialVersionUID;反之则修改。
-
ver1.1改动:
- 为RpcRequest增加serialVersionUID;
- 服务端:增加异常消息枚举类、调用回执RpcResponse类;
- 客户端:RpcClient增加对RpcResponse的相应分析。
-
IDEA可以用git方便的查看每个文件的每个历史改动…不用自己在网页上慢慢点了…orz…太强了…
-
ver1.2改动:
- 服务端:将服务注册功能抽离成接口ServiceRegistry,以及实现类DefaultServiceRegistry(synchronized方法同步,服务多接口重复注册对象)。导致线程类不再直接获取服务对象,而是通过注册中心间接获取。
-
ver2.0改动:
- 客户端:RpcClient类抽出RpcClient接口,与RpcClientProxy解耦,原实现类改名为SocketRpcClient。
- 服务端:RpcRequestHandler与ServiceRegistry的初始化,从RpcServer推迟到线程类SocketRpcRequestHandlerRunnable,懒加载,线程池职责更明确单一。
- 增加对netty与kryo的支持
-
Netty:基于NIO的客户端-服务器框架,可以简化网络通信编程。
-
interface Constant<T extends Constant<T>> extends Comparable<T>
这个通配符在这里有意义吗?。。。 -
ThreadLocal(kryo并发不安全)。
参考资料:
以上是关于JavaGuide-RPC框架项目学习笔记-未完待续的主要内容,如果未能解决你的问题,请参考以下文章
[moka学习笔记]yii2.0数据库查询的多种方法(未完待整理)