
经过大海的一番磨砺,卵石才变得更加美丽光滑
【RPC---远程过程调用协议】
五、Zookeeper安装
1. Zookeeper简介
zookeeper分布式管理软件。常用它做注册中心(依赖zookeeper的发布/订阅功能)、配置文件中心、分布式锁配置、集群管理等。
zookeeper一共就有两个版本。主要使用的是java语言写的。
2. 安装
2.1 上传压缩文件
上传到 /usr/local/tmp中
2.2 解压
- # tar zxf apache-zookeeper-3.5.5-bin.tar.gz
- # cp -r apache-zookeeper-3.5.5-bin /usr/local/zookeeper
2.3 新建data数据目录
进入到zookeeper中
- # cd /usr/local/zookeeper
- # mkdir data
2.4 修改配置文件
进入conf中
- # cd conf
- # cp zoo_sample.cfg zoo.cfg
- # vim zoo.cfg
修改dataDir为data文件夹路径,用作Zookeeper的数据存储目录。

2.5 启动zookeeper
进入bin文件夹
- # cd /usr/local/zookeeper/bin
- # ./zkServer.sh start
通过status查看启动状态。稍微有个等待时间
- # ./zkServer.sh status

六、Zookeeper客户端常用命令
进入到./zkCli.sh命令行工具后,可以使用下面常用命令。【Zookeeper有个非常好的命令提示方式,只要输入的命令是Zookeeper不识别的命令,Zookeeper会立刻显示所有有效命令提示列表】
zkCli.sh 默认连接的是 localhost:2181 Zookeeper主机。
zkCli.sh -server ip:port 指定连接到 ip:port Zookeeper主机。
1. quit
退出ZK客户端控制台。
2. ls
ls [-s] [-R] /path
-s 详细信息,替代老版的ls2
-R 当前目录和子目录中内容都罗列出来
例如:ls -R / 显示根目录下所有内容
3. create
create /path [data]
[data] 包含内容
创建指定路径信息
例如:create /demo 创建/demo
4. get
get [-s] /path
[-s] 详细信息
查看指定路径下内容。
例如:get -s /demo

null:存放的数据
cZxid:创建时zxid(znode每次改变时递增的事务id)
ctime:创建时间戳
mZxid:最近一次更近的zxid
mtime:最近一次更新的时间戳
pZxid:子节点的zxid
cversion:子节点更新次数
dataversion:节点数据更新次数
aclVersion:节点ACL(授权信息)的更新次数
ephemeralOwner:如果该节点为ephemeral节点(临时,生命周期与session一样), ephemeralOwner值表示与该节点绑定的session id. 如果该节点不是ephemeral节点, ephemeralOwner值为0.
dataLength:节点数据字节数
numChildren:子节点数量
5. set
set /path data
设置节点内容
6. delete
delete /path
删除节点,不能删除有子节点的节点。
deleteall /path
删除节点,可以删除带有子节点的节点。
七、向Zookeeper中注册内容
新建项目ZookeeperClient
1. 创建/demo节点
使用zookeeper的客户端命令工具创建/demo
./zkCli.sh
create /demos
2. 添加依赖
<dependencies>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.5</version>
</dependency>
</dependencies>
3. 编写代码
创建类com.bjsxt.MyApp。
ZooDefs.Ids.OPEN_ACL_UNSAFE 表示权限。
CreateMode.PERSISTENT_SEQUENTIAL 永久存储,文件内容编号递增。
public static void main(String [] args){
try {
ZooKeeper zookeeper = new ZooKeeper("192.168.32.128:2181", 10000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("获取连接");
}
});
String content = zookeeper.create("/demo/nn", "content".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
System.out.println("content"+content);
} catch (IOException e) {
e.printStackTrace();
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
4. 查看上传数据
ls -R /:查看列表
get /demo/nn0000000002:查看内容
八、从zookeeper中发现内容
在原有项目中新建一个类,类中编写主方法。
public static void main(String[] args) {
try {
ZooKeeper zookeeper = new ZooKeeper("192.168.32.128:2181", 10000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("获取连接");
}
});
//获取列表
List<String> list = zookeeper.getChildren("/demo", false);
for (String child : list) {
byte[] result = zookeeper.getData("/demo/" + child, false, null);
System.out.println(new String(result));
}
} catch (IOException e) {
e.printStackTrace();
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
九、手写RPC框架
使用Zookeeper作为注册中心,RMI作为连接技术,手写RPC框架。
1. 创建项目ParentDemo
创建父项目ParentDemo。
包含3个聚合子项目。
- ① service:包含被serviceimpl和consumer依赖的接口。
- ② serviceimpl:provider提供的服务内容
- ③ consumer:消费者,调用服务内容。

2. 在父项目中添加依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.10.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.5</version>
</dependency>
</dependencies>
3. 创建service项目
项目结构如下:此项目中重点编写需要被两个项目依赖的接口。

4. 创建DemoService接口
创建com.bjsxt.DemoService,具体内容如下:
public interface DemoService extends Remote {
String demo(String param) throws RemoteException;
}
5. 创建serviceimpl项目
此项目编写接口具体实现,RMI服务发布和把信息发送到Zookeeper中。
项目结构如下:

在pom.xml中添加对service项目的依赖
<dependencies>
<dependency>
<artifactId>service</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
6. 创建DemoServiceImpl
创建com.bjsxt.service.impl.DemoServiceImpl
public class DemoServiceImpl extends UnicastRemoteObject implements DemoService {
public DemoServiceImpl() throws RemoteException {
}
@Override
public String demo(String param) throws RemoteException{
return param+"123";
}
}
7. 创建RmiRun
创建com.bjsxt.RmiRun。实现RMI服务的发布和Zookeeper消息的发布。
public class RmiRun {
public static void main(String[] args) {
try {
DemoService demoService = new DemoServiceImpl();
LocateRegistry.createRegistry(8888);
String url = "rmi://localhost:8888/demoService";
Naming.bind(url,demoService);
ZooKeeper zookeeper = new ZooKeeper("192.168.32.128:2181", 10000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("获取连接");
}
});
String content = zookeeper.create("/demo/demoService",url.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("服务发布成功。。。。");
} catch (AlreadyBoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
8. 创建Consumer项目
新建consumer项目,此项目需要从zookeeper中获取rmi信息,并调用rmi服务

在pom.xml中添加对service项目的依赖
<dependencies>
<dependency>
<artifactId>service</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
9. 创建接口和实现类
创建com.bjsxt.service.ConsumerService接口
public interface ConsumerService {
String consumerService(String param);
}
创建com.bjsxt.service.impl.ConsumerServiceImpl实现类
@Service
public class ConsumerServiceImpl implements ConsumerService {
@Override
public String consumerService(String param) {
try {
ZooKeeper zookeeper = new ZooKeeper("192.168.32.128:2181", 10000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("获取连接");
}
});
byte[] urlByte = zookeeper.getData("/demo/demoService", false, null);
DemoService demoService =(DemoService) Naming.lookup(new String(urlByte));
String result = demoService.demo(param);
System.out.println(result);
return result;
} catch (IOException e) {
e.printStackTrace();
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
return null;
}
}
10. 创建控制器
创建com.bjsxt.controller.DemoController控制器
@Controller
public class DemoController {
@Autowired
private ConsumerService consumerService;
@RequestMapping("/demo")
@ResponseBody
public String demo(String param){
return consumerService.consumerService(param);
}
}
11. 创建启动器
创建com.bjsxt.ConsumerApplication
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
12. 测试
在浏览器输入:http://localhost:8080/demo?param=demo
观察结果是否是:demo123

RPC到这里就讲完了,需要更多java学习资料的小伙伴可以到评论区留言或私信我,我发给你
