代码如下
public class ZookeeperSceneTest {
/**
* zookeeper地址
*/
static final String CONNECT_ADDR = "192.168.1.187:2181";
/**
* session超时时间
*/
static final int SESSION_OUTTIME = 2000;//ms
/**
* 信号量,阻塞程序执行,用于等待zookeeper连接成功,发送成功信号
*/
static final CountDownLatch connectedSemaphore = new CountDownLatch(1);
public static void main(String[] args) throws Exception {
ZooKeeper zk = getInstance();
//puSu(zk);
nameServer(zk);
ntegrateTranstion(zk);
//disLock();
}
public static ZooKeeper getInstance() throws KeeperException, IOException, InterruptedException {
ZooKeeper zk = new ZooKeeper(CONNECT_ADDR, SESSION_OUTTIME, new Watcher() {
@Override
public void process(WatchedEvent event) {
//获取事件的状态
Event.KeeperState keeperState = event.getState();
Event.EventType eventType = event.getType();
//如果是建立连接
if (Event.KeeperState.SyncConnected == keeperState) {
if (Event.EventType.None == eventType) {
//如果建立连接成功,则发送信号量,让后续阻塞程序向下执行
connectedSemaphore.countDown();
System.out.println("zk 建立连接");
}
}
}
});
//进行阻塞
connectedSemaphore.await();
return zk;
}
/**
* @return void
* @Description //发布订阅:一个节点的变更并在变更发生时执行我们预先设置好的回调函数
* @Param []
**/
public static void puSu(ZooKeeper zk) throws KeeperException, InterruptedException, IOException {
zk.create("/config", "config test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
zk.getData("/config", new Watcher() {
public void process(WatchedEvent watchedEvent) {
System.out.println(watchedEvent.toString());
}
}, null);
zk.setData("/config", "draven".getBytes(), 0);
// WatchedEvent state:SyncConnected type:NodeDataChanged path:/config
}
/**
* @return void
* @Description //命名服务:使用了命名空间和顺序节点解决唯一标志符的问题。
* @Param []
**/
public static void nameServer(ZooKeeper zk) throws KeeperException, InterruptedException, IOException {
zk.create("/metrics", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
zk.create("/metrics", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
List children = zk.getChildren("/", null);
System.out.println(children);
// [metrics0000000001, metrics0000000002]
}
/**
* @return void
* @Description //协调分布式事务:当前节点作为协调者在每次发起分布式事务时都会创建一个 /transfer/tx 的持久顺序节点,然后为几个事务的参与者创建几个空白的节点,
* 事务的参与者在收到事务时会向这些空白的节点中写入信息并监听这些节点中的内容。
* @Param []
**/
public static void ntegrateTranstion(ZooKeeper zk) throws KeeperException, InterruptedException, IOException {
//协调者
String parentPath = zk.create("/transfer", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
String path = zk.create(parentPath + "/tx", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
//事务参与者
List ops = Arrays.asList(
Op.create(path + "/cohort", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL),
Op.create(path + "/cohort", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL),
Op.create(path + "/cohort", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL)
);
zk.multi(ops);
}
/**
* @return void
* @Description //分布式锁(示例代码)
* @Param []
**/
public static void disLock(ZooKeeper zk) throws KeeperException, InterruptedException, IOException {
//共享资源
final String resource = "/resource";
//创建临时顺序节点
final String lockNumber = zk.create("/resource/lock-", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
//通过 getChildren 获取当前等待锁的全部节点
List<String> locks = zk.getChildren(resource, false, null);
Collections.sort(locks);
//如果当前节点是所有节点中序号最小的就得到了当前资源的使用权限,在对资源进行处理后,就可以通过删除 /resource/lock-xxx 来释放锁
if (locks.get(0).equals(lockNumber.replace("/resource/", ""))) {
System.out.println("Acquire Lock");
zk.delete(lockNumber, 0);
} else {
//如果当前节点不是最小值,就会注册一个 Watcher 等待 /resource 子节点的变化直到当前节点的序列号成为最小值。
zk.getChildren(resource, new Watcher() {
public void process(WatchedEvent watchedEvent) {
try {
List locks = zk.getChildren(resource, null, null);
Collections.sort(locks);
if (locks.get(0).equals(lockNumber.replace("/resource/", ""))) {
System.out.println("Acquire Lock");
zk.delete(lockNumber, 0);
}
} catch (Exception e) {
}
}
}, null);
}
}