pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<zookeeper.version>3.4.5</zookeeper.version>
<curator.version>2.12.0</curator.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>11.0.2</version>
</dependency>
<!-- zk客户端第三方Curator -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>${curator.version}</version>
</dependency>
</dependencies>
1、 zookeeper原生客户端
ZookeeperUtils .java
package com.syher.utils;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.Charset;
public class ZookeeperUtils {
private final static Logger logger = LoggerFactory.getLogger(ZookeeperUtils.class);
private final static Integer DEFAULT_SESSION_TIMEOUT = 10000;
private final static boolean DEFAULT_WATCHER_ABLE = true;
private final static Charset DEFAULT_CHARSET = Charsets.UTF_8;
private ZooKeeper zooKeeper;
private String zkHosts;
private String basePath;
private Watcher watcher;
private ThreadLocal<Transaction> transactionThreadLocal = new ThreadLocal<>();
public ZookeeperUtils(String zkHosts, String basePath) {
this(zkHosts, basePath, watchedEvent -> {
// TODO: 事件触发
});
}
public ZookeeperUtils(String zkHosts, String basePath, Watcher watcher) {
this.zkHosts = zkHosts;
this.basePath = basePath;
this.watcher = watcher;
}
public void begin() {
transactionThreadLocal.set(zooKeeper.transaction());
}
public String getBasePath() {
return this.basePath;
}
public void connect() {
try {
zooKeeper = new ZooKeeper(zkHosts, DEFAULT_SESSION_TIMEOUT, this.watcher);
} catch (Exception e) {
logger.info("cannot connect to zookeeper.", e);
}
}
public void commit() throws Exception {
Transaction transaction = transactionThreadLocal.get();
if (transaction != null) {
transaction.commit();
transaction = null;
transactionThreadLocal.remove();
}
}
public void create(String zNode, String content) throws Exception {
create(zNode, content.getBytes(DEFAULT_CHARSET));
}
public void create(String zNode, byte[] bytes) throws Exception {
zNode = this.formatZnode(zNode);
Transaction transaction = transactionThreadLocal.get();
Preconditions.checkArgument(transaction != null,
"transcation must be required.");
Stat stat = zooKeeper.exists(zNode, DEFAULT_WATCHER_ABLE);
if (stat == null) {
createNodeLoop(zNode);
stat = zooKeeper.exists(zNode, DEFAULT_WATCHER_ABLE);
}
transaction.setData(zNode, bytes, stat.getVersion());
}
public String get(String zNode) throws Exception {
zNode = formatZnode(zNode);
Stat stat = zooKeeper.exists(zNode, DEFAULT_WATCHER_ABLE);
if (stat != null)
return new String(zooKeeper.getData(zNode, DEFAULT_WATCHER_ABLE, stat), DEFAULT_CHARSET);
return null;
}
public String delete(String zNode) throws Exception {
zNode = formatZnode(zNode);
Stat stat = zooKeeper.exists(zNode, DEFAULT_WATCHER_ABLE);
if (stat != null) {
Transaction transaction = transactionThreadLocal.get();
Preconditions.checkArgument(transaction != null,
"transaction must be required.");
transaction.delete(zNode, stat.getVersion());
}
return zNode;
}
private String formatZnode(String zNode) {
zNode = zNode.startsWith("/") ? zNode : String.format("/%s", zNode);
return zNode.replaceAll("[/]{2,}", "/");
}
private void createNodeLoop(String zNode) throws Exception {
if (zNode ==null || zNode.isEmpty()) return;
zNode = formatZnode(zNode);
int index = zNode.lastIndexOf("/");
if (index != 0 && !zNode.isEmpty()) {
createNodeLoop(zNode.substring(0, index));
}
Stat stat = zooKeeper.exists(zNode, DEFAULT_WATCHER_ABLE);
if (stat == null) {
zooKeeper.create(zNode, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
}
public String buildPath(String ...paths) {
StringBuilder stringBuilder = new StringBuilder(256);
stringBuilder.append(this.basePath);
String path ;
if (paths != null && paths.length != 0) {
stringBuilder.append("/");
path = Joiner.on("/").appendTo(stringBuilder, paths).toString();
} else {
path = stringBuilder.toString();
}
return formatZnode(path);
}
}
2、 第三方客户端Curator
ZkCuratorUtil.java
package com.syher.utils;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
public class ZkCuratorUtil {
private final Logger logger = LoggerFactory.getLogger(ZkCuratorUtil.class);
private final static Integer DEFAULT_SESSION_TIMEOUT = 300000;
private final static Integer DEFAULT_CONNECT_TIMEOUT = 150000;
private final static Integer DEFAULT_BASE_SLEEP_TIME = 1000;
private final static Integer DEFAULT_MAX_RETRY = 5;
private final static Charset charset = Charsets.UTF_8;
private String zkHosts;
private String basePath;
private Integer connectTimeout;
private Integer sessionTimeout;
private Integer maxRetry;
private CuratorFramework client;
private final Map<String, TreeCache> treeCaches = Maps.newHashMap();
public ZkCuratorUtil(String zkHosts, String basePath) {
this(zkHosts, basePath, DEFAULT_CONNECT_TIMEOUT);
}
public ZkCuratorUtil(String zkHosts, String basePath, Integer connectTimeout) {
this(zkHosts, basePath, connectTimeout, DEFAULT_SESSION_TIMEOUT);
}
public ZkCuratorUtil(String zkHosts, String basePath, Integer connectTimeout, Integer sessionTimeout) {
this(zkHosts, basePath, connectTimeout, sessionTimeout, DEFAULT_MAX_RETRY);
}
public ZkCuratorUtil(String zkHosts, String basePath, Integer connectTimeout, Integer sessionTimeout, Integer maxRetry) {
this.zkHosts = zkHosts;
this.basePath = basePath;
this.connectTimeout = connectTimeout;
this.sessionTimeout = sessionTimeout;
this.maxRetry = maxRetry;
}
public CuratorFramework connect() {
client = CuratorFrameworkFactory.builder()
.connectString(zkHosts)
.retryPolicy(new ExponentialBackoffRetry(DEFAULT_BASE_SLEEP_TIME, this.maxRetry))
.sessionTimeoutMs(this.sessionTimeout)
.connectionTimeoutMs(this.connectTimeout)
.namespace(basePath)
.build();
return client;
}
public CuratorFramework getClient() {
return client == null ? connect() : client;
}
public void addListener(String node, TreeCacheListener listener) throws Exception {
if(treeCaches.containsKey(node)) return;
node = fixed(node);
TreeCache treeCache = new TreeCache(this.client, node);
treeCache.getListenable().addListener(listener);
treeCache.start();
treeCaches.put(node, treeCache);
}
public CuratorFramework start() {
if (client == null)
client = connect();
if (!client.isStarted())
client.start();
return client;
}
public Stat checkExists(String nodePath) throws Exception {
return client.checkExists().forPath(nodePath);
}
public String send(String nodePath, String content) throws Exception {
return send(nodePath, Strings.nullToEmpty(content).getBytes(charset));
}
public String send(String nodePath, byte[] bytes) throws Exception {
nodePath = fixed(nodePath);
Stat stat = checkExists(nodePath);
if (stat == null) {
client.create().creatingParentContainersIfNeeded()
.withMode(CreateMode.PERSISTENT)
.forPath(nodePath, bytes);
} else {
client.setData().forPath(nodePath, bytes);
}
return nodePath;
}
public String get(String nodePath) throws Exception {
nodePath = fixed(nodePath);
Stat stat = checkExists(nodePath);
if (stat != null) {
byte[] bytes = client.getData().forPath(nodePath);
if (bytes != null) {
return new String(bytes, charset);
}
}
return null;
}
public String delete(String nodePath) throws Exception {
nodePath = fixed(nodePath);
Stat stat = checkExists(nodePath);
if (stat != null)
client.delete().deletingChildrenIfNeeded().forPath(nodePath);
return nodePath;
}
public void close() throws Exception {
client.close();
client = null;
}
private static String fixed(String path) {
path = path.startsWith("/") ? path : String.format("/%s", path);
return path.replaceAll("[/]{2,}", "/");
}
public String buildPath(String... zNodeParts) {
StringBuilder builder = new StringBuilder(256);
String path;
if (zNodeParts != null && zNodeParts.length != 0) {
builder.append("/");
path = Joiner.on("/").appendTo(builder, zNodeParts).toString();
} else {
path = builder.toString();
}
builder = null;
return fixed(path);
}
public List<String> getChildren(String nodePath) throws Exception {
nodePath = fixed(nodePath);
Stat stat = checkExists(nodePath);
if (stat != null) {
return client.getChildren().forPath(nodePath);
}
return null;
}
}