如何写框架——高可用RMI远程通信框架篇
1、likab-rmi架构图
说明:
1.服务提供者在容器启动时,发布对象到rmi注册表
2.服务提供者将rmi服务注册JNDI注册到Zookeeper服务注册中心
3.服务消费者从Zookeeper服务注册中心获取服务地址列表,缓存至本地
4.如果某台服务提供者服务器宕机,Zookeeper服务注册中心通过心跳检测到该服务无法连接,将该服务上的注册的服务地址删除,异步发送给服务消费者
5.通过软负载均衡获取一个JNDI地址,访问RMI注册表,得到调用结果
2、模块分包
模块说明:
1.likab-core:核心组件模块,核心逻辑组件抽象,比如动态代理等
2.likab-registry-support:服务注册中心支持模块,服务注册中心通用模型抽象
3.likab-registry-zookeeper:Zookeeper服务中心模块,服务注册中心发布以及连接等业务逻辑
4.likab-loadbalance:负载均衡模块,软负载均衡
5.likab-rmi:rmi远程调用模块,高可用rmi服务发布和引用
3、服务暴露时序:
4、服务引用时序:
二、likab-rmi相关技术
1. zookeeper分布式协调服务
① 众所周知,zookeeper是hadoop下的一个子项目,它是一个针对大型分布式系统可靠地协调系统,提供的功能包括配置服务、名字服务、分布式服务、分布式同步等,大致架构如下:
②zookeeper可以集群复制,通过zookeeper自身的Zab协议保持数据一致性。它有两个阶段:leader election和Atomic
broadcas阶段。(备注:关于zookepper的相关知识,各位可以去网上,或者书籍中去学习,这里,我就不再赘述)
③我们在前面一直都在强调高可用的RMI框架,高可用就体现在likab-rmi使用了zookeepe集中式的配置管理,一旦服务端集群中某台服务器地址或者服务变更,都能够通知到集群中的每一个机器,同时也会异步通知服务调用端更新服务地址列表,避免了通过一个无效的服务地址调用相关服务所带来的服务无响应的问题
①Consistency(一致性)
②Availability(可用性)、
③Partition tolerance(分区容错性)
三者不可得兼
2. JDK和Cglib动态代理技术
①JDK动态代理只能对接口进行代理,不能对具体实现类做代理,JDK动态代理需要子类实现InvocationHandler,在invoke方法中加入自己的一些个性化逻辑,最后通过Proxy.newProxyInstance()创建动态代理对象
②Cglib动态代理通过生成java 字节码从而动态的产生代理对象,它既能对接口代理也能对具体类代理(这个是JDK动态代理所不能实现的),子类需实现MethodInterceptor接口类,在intercept中实现个性化逻辑,通过enhancer.create()创建动态代理对象。
备注:likab-rmi在客户端调用远程对象时,通过动态代理技术,在invoke或者intercept方法中实现了从zookepper注册中心获取服务地址,调用远程服务stub对象返回结果
3.Java原生RMI技术
RMI(Remote Method)远程方法调用
备注:Stub和Skeleton:这两个的身份是一致的,都是作为代理的存在。客户端的称作Stub,服务端的称作Skeleton。要做到对程序员屏蔽远程方法调用的细节,这两个代理是必不可少的,包括网络连接等细节。
4.Java SPI技术
SPI的全名为Service Provider Interface.
①SPI具体约定
java spi的具体约定为:当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader
②应用场景
1.common-logging(发现日志提供商是通过扫描 META-INF/services/org.apache.commons.logging.LogFactory配置文件,通过读取该文件的内容找到日志供应商)
2.JDBC4(jdbc4也基于spi的机制来发现驱动提供商了)
3.likab-rmi(通过SPI找到对应的负载均衡算法)
5.Java反射机制
Java反射在前面列举了一些常用的方法等,在这里就不详细介绍,在likab-rmi中主要应用场景在客户端调用远程对象时,通过将方法名,参数列表以及参数值传给服务端,服务端通过反射调用并返回结果,有兴趣的同学可以到github上查看RmiInvocation类的代码。
6.synchronized同步锁和并发容器
对于并发编程的知识,我在这里不再赘述,并发相关的知识对于框架开发者尤为重要,框架类似于一个集中系统,可能会有多个线程并发请求,这样的话,这就要求我们开发的框架需具备高并发的特性,以及保持数据完整性的功能。
源码仓库:
1、likab-rmi代码托管地址:https://github.com/xiapshen/likab-framework
2、likab-rmi-example示例托管地址:
https://github.com/xiapshen/likab-framework/tree/master/examples/likab-rmi-example