转自:https://my.oschina.net/huangyong/blog/345164
在 Java 世界里,有一种技术可以实现“跨虚拟机”的调用,它就是 RMI(Remote Method Invocation,远程方法调用)。例如,服务A 在 JVM1 中运行,服务B 在 JVM2 中运行,服务A 与 服务B 可相互进行远程调用,就像调用本地方法一样,这就是 RMI。在分布式系统中,我们使用 RMI 技术可轻松将 服务提供者(Service Provider)与 服务消费者(Service Consumer)进行分离,充分体现组件之间的弱耦合,系统架构更易于扩展。使用 ZooKeeper 可轻松解决 RMI 调用过程中所涉及的问题。ZooKeeper 是 Hadoop 的一个子项目,用于解决分布式系统之间的数据一致性问题,如果读者尚不了解 ZooKeeper 的工作原理与使用方法,可以通过以下链接来了解:
本文假设读者已经对 ZooKeeper 有一定了解的前提下,对 RMI 的高可用性问题提供一个简单的解决方案。
要想解决 RMI 服务的高可用性问题,我们需要利用 ZooKeeper 充当一个 服务注册表(Service Registry),让多个 服务提供者(Service Provider)形成一个集群,让 服务消费者(Service Consumer)通过服务注册表获取具体的服务访问地址(也就是 RMI 服务地址)去访问具体的服务提供者。如下图所示:
需要注意的是,服务注册表并不是 Load Balancer(负载均衡器),提供的不是“反向代理”服务,而是“服务注册”与“心跳检测”功能。
利用服务注册表来注册 RMI 地址,这个很好理解,那么“心跳检测”又如何理解呢?说白了就是通过服务中心定时向各个服务提供者发送一个请求(实际上建立的是一个 Socket 长连接),如果长期没有响应,服务中心就认为该服务提供者已经“挂了”,只会从还“活着”的服务提供者中选出一个做为当前的服务提供者。
也许读者会考虑到,服务中心可能会出现单点故障,如果服务注册表都坏掉了,整个系统也就瘫痪了。看来要想实现这个架构,必须保证服务中心也具备高可用性。
ZooKeeper 正好能够满足我们上面提到的所有需求。
- 使用 ZooKeeper 的临时性 ZNode 来存放服务提供者的 RMI 地址,一旦与服务提供者的 Session 中断,会自动清除相应的 ZNode。
- 让服务消费者去监听这些 ZNode,一旦发现 ZNode 的数据(RMI 地址)有变化,就会重新获取一份有效数据的拷贝。
- ZooKeeper 与生俱来的集群能力(例如:数据同步与领导选举特性),可以确保服务注册表的高可用性。
总结: ZooKeeper从设计模式角度来看,是一个基于服务提供者(Service Provider)模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受服务提供者(Service Provider)的注册,一旦这些数据的状态发生变化,Zookeeper 就将负责通知已经在 Zookeeper 上注册的那些服务提供者(Service Provider)做出相应的反应,从而实现集群中类似 Master/Slave 管理模式,关于 Zookeeper 的详细架构等内部细节可以阅读 Zookeeper 的源码。