1. Introdução ao Curador
O Apache Curator é uma estrutura de cliente ZooKeeper relativamente completa que simplifica a operação do ZooKeeper por meio de um conjunto de APIs de alto nível encapsuladas. Ao verificar os documentos oficiais, podemos descobrir que o Curator resolve principalmente três tipos de problemas:
1. Encapsule o processamento de conexão entre o cliente ZooKeeper e o servidor ZooKeeper
2. Forneça um conjunto de API de operação de estilo Fluent
3. Forneça vários cenários de aplicação de ZooKeeper (receita, como: serviço de bloqueio distribuído, eleição de líder de cluster, contador compartilhado, mecanismo de cache, fila distribuída, etc.) encapsulamento abstrato
O Curator reduz principalmente a complexidade do uso de zk a partir dos seguintes aspectos:
Mecanismo de nova tentativa: fornece um mecanismo de nova tentativa plugável, ele irá configurar uma estratégia de nova tentativa para capturar todas as exceções recuperáveis e também fornece várias estratégias de nova tentativa padrão internas (como compensação exponencial) de
conexão monitoramento de status : o Curator sempre monitorará a conexão zk após a inicialização. Assim que o status da conexão mudar, ele lidará com isso de acordo.
zk client instance management : Curator enviará o cliente zk para A conexão do cluster de servidor é gerenciada, e o zk a instância é reconstruída quando necessário para garantir a confiabilidade
da conexão com o cluster zk. Suporte a vários cenários de uso : O Curator implementa a maioria dos cenários de uso suportados pelo zk (mesmo os cenários não suportados pelo próprio zk). Essas implementações seguem as melhores práticas de zk, e considere vários casos extremos
2. No projeto, o arquivo .pom apresenta a dependência do curador
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.0</version>
</dependency>
3. Use o cliente Curator para se conectar ao zkeeper para realizar a criação, modificação e exclusão de nós zk
public static void main(String[] args) throws Exception {
CuratorFramework cf = CuratorFrameworkFactory.builder()
.connectString("192.168.1.102:2181,192.168.1.102:2182,192.168.1.102:2183")//zk服务器地址
.sessionTimeoutMs(4000)// 超市时间
.retryPolicy(new ExponentialBackoffRetry(1000, 3))// 重试策略:初试时间为1s 重试10次
.namespace("curator-demo")//命名空间
.build();
cf.start();
System.out.println(States.CONNECTED);
System.out.println(cf.getState());
//创建持久化节点
cf.create().forPath("/che","123".getBytes());
//创建持久化有序节点
cf.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/che_seq","che_seq data".getBytes());
//创建临时节点
cf.create().withMode(CreateMode.EPHEMERAL)
.forPath("/che/tmp1","tmp1data01".getBytes());
//创建临时有序节点
cf.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL) .forPath("/che/tmp2","tmp2data".getBytes());
cf.create().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/che/tmp3","tmp3data".getBytes());
//测试检查某个节点是否存在
Stat stat1 = cf.checkExists().forPath("/che");
Stat stat2 = cf.checkExists().forPath("/che3");
System.out.println("'/che'是否存在: " + (stat1 != null ? true : false));
System.out.println("'/che3'是否存在: " + (stat2 != null ? true : false));
//获取某个节点的所有子节点
System.out.println(cf.getChildren().forPath("/"));
//获取某个节点数据
System.out.println(new String(cf.getData().forPath("/che")));
//设置某个节点数据
cf.setData().forPath("/che","new123".getBytes());
//创建测试节点
cf.create().orSetData().creatingParentContainersIfNeeded()
.forPath("/che/che005","che005data".getBytes());
cf.create().orSetData().creatingParentContainersIfNeeded()
.forPath("/che/che006","che006data".getBytes());
cf.create().forPath("/che/che007/che007001","che007001data".getBytes());
//删除该节点
cf.delete().forPath("/che/che005");
//级联删除子节点
cf.delete().guaranteed().deletingChildrenIfNeeded().forPath("/che/che007");
}
orSetData método () Se o nó existe, curador vai utilizar os dados fornecidos para definir o valor do nó, que é equivalente ao setDate () Método:
método creatingParentContainersIfNeeded () : Se o nó principal do nó especificado não existe, O Curator irá cascatear automaticamente Criar um nó pai
método garantido () : Se o servidor puder ser excluído com sucesso, mas o cliente não receber um prompt de exclusão bem-sucedido, o Curator continuará a tentar excluir o nó em segundo plano.
Método deletingChildrenIfNeeded () : Se o nó a ser excluído tiver nós filhos, o Curator excluirá em cascata os nós filhos deste nó
4. Exemplos de eventos do Watcher no cliente Curator
public class CuratorWatcherDemo {
public static void main(String[] args) throws Exception {
CuratorFramework cf = CuratorFrameworkFactory.builder()
.connectString("192.168.1.102:2181,192.168.1.102:2182,192.168.1.102:2183")//zk服务器地址
.sessionTimeoutMs(4000)// 超市时间
.retryPolicy(new ExponentialBackoffRetry(1000, 3))// 重试策略:初试时间为1s 重试10次
.namespace("curator-demo")//命名空间
.build();
cf.start();
System.out.println(States.CONNECTED);
System.out.println(cf.getState());
// PathChildCache 监听一个节点下子节点的创建、删除、修改事件
addListenerWithNodeChildCache(cf, "/che-test01");
// NodeCache 监听一个节点的修改和创建事件
addListenerWithNodeCache(cf, "/che-test01");
// TreeCache 监听所有节点的创建、删除、修改事件
addListenerWithTreeCache(cf, "/che-test01");
System.in.read();
}
/**
* PathChildCache 监听一个节点下子节点的创建、删除、修改事件
* @param cf
* @param path
* @throws Exception
*/
public static void addListenerWithNodeCache(CuratorFramework cf,String path) throws Exception {
@SuppressWarnings("resource")
final NodeCache nodeCache = new NodeCache(cf, path, false);
NodeCacheListener cacheListener = new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
System.out.println("监听到节点事件:" + " - " + nodeCache.getCurrentData().getPath());
}
};
nodeCache.getListenable().addListener(cacheListener);
nodeCache.start();
}
/**
* NodeCache 监听一个节点的修改和创建事件
* @param cf
* @param path
* @throws Exception
*/
public static void addListenerWithNodeChildCache(CuratorFramework cf,String path) throws Exception {
@SuppressWarnings("resource")
final PathChildrenCache pathChildrenCache = new PathChildrenCache(cf, path, true);
PathChildrenCacheListener cacheListener = new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
System.out.println("监听到子节点事件:" + event.getType());
}
};
pathChildrenCache.getListenable().addListener(cacheListener);
pathChildrenCache.start(PathChildrenCache.StartMode.NORMAL);
}
/**
* TreeCache 监听所有节点的创建、删除、修改事件
* @param cf
* @param path
* @throws Exception
*/
public static void addListenerWithTreeCache(CuratorFramework cf,String path) throws Exception {
@SuppressWarnings("resource")
final TreeCache treeCache = new TreeCache(cf, path);
TreeCacheListener cacheListener = new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
System.out.println("监听到节点事件:" + event.getType() + " - " + event.getData().getPath());
}
};
treeCache.getListenable().addListener(cacheListener);
treeCache.start();
}
}