Java客户端
https://github.com/etcd-io/jetcd
客户端和etcd之间使用基于http2.0协议的grpc通信;
pom.xml :
<dependency>
<groupId>io.etcd</groupId>
<artifactId>jetcd-core</artifactId>
<version>5.0.6</version>
</dependency>
基于etcd的分布式锁实现
/**
* 这里只是模拟,注意Client、Lock、Lease是单例,注意关闭问题
* @param args
*/
public static void main(String[] args) {
// create client
Client client = Client.builder().endpoints("http://192.168.40.129:2379").build();
Lock lockClient = client.getLockClient();
Lease leaseClient = client.getLeaseClient();
//name-锁标识
ByteSequence name = ByteSequence.from("mutex1".getBytes());
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
//创建一个租约
LeaseGrantResponse ttl = leaseClient.grant(30).get();
log.info("创建租约...ID: {}, ttl: {}", ttl.getID(), ttl.getTTL());
//自动续约-防止ttl超时线程未执行完
leaseClient.keepAlive(ttl.getID(), new StreamObserver() {
@Override
public void onNext(Object value) {
//执行续约之后的回调
log.info("执行续约...ID: {}, ttl: {}", ttl.getID(), ttl.getTTL());
}
@Override
public void onError(Throwable t) {
//异常,就会停止续约,比如调用revoke取消续约,租约不存在
log.info("停止续约...{} 原因: {}", ttl.getID(), t.getMessage());
}
@Override
public void onCompleted() {
log.info("onCompleted...");
}
});
log.info("尝试获取锁...");
//尝试获取锁
ByteSequence key = lockClient.lock(name, ttl.getID()).get().getKey();
long start = System.currentTimeMillis();
log.info("获得锁...key: {}", new String(key.getBytes()));
//模拟线程执行时长
TimeUnit.SECONDS.sleep(3);
log.info("执行时长... {} ms", System.currentTimeMillis() - start);
//取消租约
leaseClient.revoke(ttl.getID());
log.info("取消租约...{}", ttl.getID());
lockClient.unlock(key);
log.info("释放锁...");
} catch (Exception e) {
e.printStackTrace();
}
}, "线程" + i).start();
}
}
额外加个watch监听demo:
/**
* watch监听demo,watch可监听数据变化,基于此可实现服务注册发现
* @param args
*/
public static void main(String[] args) {
// create client
Client client = Client.builder().endpoints("http://192.168.40.129:2379").build();
Watch watchClient = client.getWatchClient();
ByteSequence key = ByteSequence.from("test_key".getBytes());
try {
watchClient.watch(key, new Watch.Listener() {
@Override
public void onNext(WatchResponse response) {
for (WatchEvent event : response.getEvents()) {
System.out.println("操作: " + event.getEventType());
KeyValue kv = event.getKeyValue();
System.out.println("当前kv: ");
System.out.println(new String(kv.getKey().getBytes()));
System.out.println(new String(kv.getValue().getBytes()));
System.out.println(kv.getVersion());
System.out.println(kv.getCreateRevision());
System.out.println(kv.getModRevision());
System.out.println(kv.getLease());
}
}
@Override
public void onError(Throwable throwable) {
System.out.println(throwable.getMessage());
}
@Override
public void onCompleted() {
System.out.println("结束监听...");
}
});
System.out.println("键盘输入结束监听!");
Scanner sc = new Scanner(System.in);
sc.nextLine();
} finally {
if (watchClient != null) {
watchClient.close();
}
}
}