ZooKeeper学习笔记(三)之开发入门-续
这一节中我们要对上一节中的Barrier和Queue用例进行测试和分析,填补忽略的细节,加深印象。
Barrier
首先我们来看测试main方法,为了更方便地进行Debug和日志输出,暂没有使用不是太熟悉的Junit.
测试代码
|
|
大致的流程如下:
等待其它进程(总数3)就绪
开始工作
等待所有Node删除,退出
日志输出设置
enter方法中有如下打印语句:
监听也是在enter方法中设置的List<String> list = zk.getChildren(root, true);
第二个参数True
代表监听root Node,Node的任何更新都会被通知.
|
|
每次收到消息,即打印children node, 数量到达3时, 将进入工作阶段。
leave方法中也有类似日志输出,当数量为0时,退出程序。
运行结果与分析
首先运行nodej进程,再依次运行node1 和node2进程。
nodej输出:
|
|
Node1输出:
|
|
Node2 输出:
|
|
可以看到,Nodej Node1 Node2依次进入Barrier。每次有Node进入,在线的Node都会收到消息(广播),打印信息。当Node2进入时,达到预定数量3, 所有进程退出enter方法开始进入工作状态(只是打印一句日志),完成后开始进入退出状态。退出时,每个进程删除自己对应的Node,但是并不立即退出方法,而是待到所有Node删除后才返回。
这里测试模拟的工作时间很短,过程中出现过问题,即Node2刚创建,Node1 Nodej结束等待并瞬间工作完毕,删除自身Node,导致Node2尚未进入工作状态,因而将一直在等待。加一句sleep(1000)延长工作时间可解决。实际应用中如果任务运行时间很短,也需要考虑这个问题。
通过以上机制,分布式的三个进程实现了同时开始工作和同时退出,也就是达到了协同的效果。
Queue
我们之前介绍了RabbitMQ,它是一个专门的AMQP应用,使用ZooKeeper的znode的有序性,也可以实现类似的功能。
测试代码
依然采用了main方法来测试:
|
|
无参时作为consumer一直监听消息,有参时作为producer发送参数值(整数)。
输出与分析
producer:
|
|
consumer
|
|
这里我们可以看到,当创建模式为EPHEMERAL_SEQUENTIAL
时,ZooKeeper会为节点名自动添加序号,对应是创建的顺序。因为只有一个producer,任务也简单,所以Node数总是1。如果有多个consumer,上述代码就会出错,因为消息是广播的,获取节点数据之后二者都会执行删除操作。可见它用来实现1对1的通信还是比较便捷的,但如果要实现工作队列来在多个线程中分发任务,实现并行处理和负载平衡,就不是很方便。
附完整代码
实质上一节的代码有一些小Bug,这里附上完整的代码
SysncPrimitive
|
|
zkQueue
|
|
zkBarrier
|
|