From 47a74abd306b8f0d98e15727f80c514aee993035 Mon Sep 17 00:00:00 2001 From: Jonathan Oddy Date: Fri, 31 Aug 2018 17:57:46 +0100 Subject: [PATCH] Avoid leaking Zookeeper znodes in tryLock Creating a EPHEMERAL_SEQUENTIAL node was being used to ensure the Zookeeper connection had been established. These were never explicitly removed, which led to tryLock effectively leaking zNodes until the client was terminated. This in turn lead to an extremely large number of ephemeral nodes being deleted whenever a long running service terminated! This fix replaces the creation of a node with a stat of "/" instead. This has the desired effect of re-establishing the Zookeeper connection, but is a read-only operation. * Remove unused import --- .../zookeeper/lock/ZookeeperLockRegistry.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/spring-integration-zookeeper/src/main/java/org/springframework/integration/zookeeper/lock/ZookeeperLockRegistry.java b/spring-integration-zookeeper/src/main/java/org/springframework/integration/zookeeper/lock/ZookeeperLockRegistry.java index 689d0ec5fd0..d20d9e899f9 100644 --- a/spring-integration-zookeeper/src/main/java/org/springframework/integration/zookeeper/lock/ZookeeperLockRegistry.java +++ b/spring-integration-zookeeper/src/main/java/org/springframework/integration/zookeeper/lock/ZookeeperLockRegistry.java @@ -29,7 +29,6 @@ import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.recipes.locks.InterProcessMutex; -import org.apache.zookeeper.CreateMode; import org.springframework.beans.factory.DisposableBean; import org.springframework.core.task.AsyncTaskExecutor; @@ -275,28 +274,24 @@ public boolean tryLock() { @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { - Future future = null; + Future future = null; try { long startTime = System.currentTimeMillis(); - future = this.mutexTaskExecutor.submit(new Callable() { + future = this.mutexTaskExecutor.submit(new Callable() { @Override - public String call() throws Exception { - return ZkLock.this.client.create() - .creatingParentContainersIfNeeded() - .withProtection() - .withMode(CreateMode.EPHEMERAL_SEQUENTIAL) - .forPath(ZkLock.this.path); + public Boolean call() throws Exception { + return ZkLock.this.client.checkExists().forPath("/") != null; } }); long waitTime = unit.toMillis(time); - String ourPath = future.get(waitTime, TimeUnit.MILLISECONDS); + boolean connected = future.get(waitTime, TimeUnit.MILLISECONDS); - if (ourPath == null) { + if (!connected) { future.cancel(true); return false; }