Zookeeper是一种分布式程序协调服务,主要功能包括:配置管理、名字服务、分布式锁、集群管理。RPC框架中使用Zookeeper可以更加灵活,不仅可以存储
结构的数据,也可以存储树状结构的数据,同时Zookeeper相较于Redis支持分布式,当一台节点挂掉时,也可以用其他机器提供服务。
官网:https://zookeeper.apache.org/releases.html
ZooKeeper下载安装(Windows版本)
在使用zookeeper实现注册中心之前,我们采用开源Zookeeper客户端ZKClient,它对ZookeeperAPI进行了封装,实现了超时重连,Watcher反复注册等功能。
<dependency>
<groupId>com.101tecgroupId>
<artifactId>zkclientartifactId>
<version>0.11version>
dependency>
注意: zkclient中自带的日志的jar包可能会和maven项目自己引入的日志冲突。
解决方法: 排除依赖冲突包。
<dependency>
<groupId>com.101tecgroupId>
<artifactId>zkclientartifactId>
<version>0.11version>
<exclusions>
<exclusion>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
exclusion>
<exclusion>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
exclusion>
<exclusion>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
exclusion>
exclusions>
dependency>
在【手写RPC框架(四)】utils工具类的基础上,可以增加Zookeeper管理工具,即基于zookeeper实现注册中心。
public class ZooKeeperUtil {
private static final Logger logger = LoggerFactory.getLogger(ZooKeeperUtil.class);
private static final String ZK_ADDRESS = "127.0.0.1:2181";
private static ZkClient client;
static {
client = new ZkClient(ZK_ADDRESS);
}
public static void writeData(String path, String data) {
if (!client.exists(path)) {
// 创建持久化节点 ,初始化数据
client.createPersistent(path, true);
}
// 修改节点数据,并返回该节点的状态
client.writeData(path, data, -1);
}
public static <T> T readData(String path) {
// 获取节点数据
return client.readData(path);
}
}
public class RegisterCenter {
private static final String ROOT = "/cn/dhu";
private static final String PROVIDER_PATH = "%s/%s/server";
private static final String CONSUMER_PATH = "%s/%s/client";
public static void registerProvider(RpcRegisterEntity entity) {
ZooKeeperUtil.writeData(String.format(PROVIDER_PATH, ROOT, entity.getInterfaceClassFullName()), JSON.toJSONString(entity));
}
public static void registerConsumer(RpcRegisterEntity entity) {
ZooKeeperUtil.writeData(String.format(CONSUMER_PATH, ROOT, entity.getInterfaceClassFullName()), JSON.toJSONString(entity));
}
public static <T> T getProviderData(String path) {
return ZooKeeperUtil.readData(String.format(PROVIDER_PATH, ROOT, path));
}
public static <T> T getConsumerData(String path) {
return ZooKeeperUtil.readData(String.format(CONSUMER_PATH, ROOT, path));
}
}
服务端启动的时候,扫描service模块,将提供的服务进行服务注册。
RegisterCenter.registerProvider(rpcRegisterEntity);
客户端启动,扫描请求服务信息,在代理类的invoke方法中与服务端建立socket连接。因此需要从zookeeper中获取host、port、接口等服务信息。
String serviceObject= RegisterCenter.getProviderData(interfaceName);
注:其它逻辑与前一篇文章基本一致,不再赘述
参考:手写RPC框架(五)整合Zookeeper