This is an automated email from the ASF dual-hosted git repository. andor pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/zookeeper.git The following commit(s) were added to refs/heads/master by this push: new c000f96 ZOOKEEPER-2474: add a way for client to reattach to a session when using ZKClientConfig c000f96 is described below commit c000f96504198d999daee2b0ccb3c4217f16dc97 Author: maoling AuthorDate: Tue Mar 12 11:08:39 2019 -0700 ZOOKEEPER-2474: add a way for client to reattach to a session when using ZKClientConfig - Thanks the original work from [arshad.mohammad](https://issues.apache.org/jira/secure/ViewProfile.jspa?name=arshad.mohammad) and [timothyjward](https://github.com/timothyjward). Plz call me code-carrier(:D). - more details in [ZOOKEEPER-2474](https://issues.apache.org/jira/browse/ZOOKEEPER-2474).if cannot backport to branch-3.5 successfully,I will give another hit. Author: maoling Reviewers: andor@apache.org Closes #825 from maoling/ZOOKEEPER-2474 and squashes the following commits: f782b16d3 [maoling] add the version info 8238dc488 [maoling] ZOOKEEPER-2474:add a way to reattach to a session when using ZKClientConfig --- .../main/java/org/apache/zookeeper/ZooKeeper.java | 97 ++++++++++++++++++++-- .../java/org/apache/zookeeper/ZooKeeperTest.java | 28 +++++++ 2 files changed, 116 insertions(+), 9 deletions(-) diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeper.java b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeper.java index b99e729..c606421 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeper.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeper.java @@ -1140,17 +1140,96 @@ public class ZooKeeper implements AutoCloseable { public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, long sessionId, byte[] sessionPasswd, boolean canBeReadOnly, HostProvider aHostProvider) throws IOException { - LOG.info("Initiating client connection, connectString=" + connectString - + " sessionTimeout=" + sessionTimeout - + " watcher=" + watcher - + " sessionId=" + Long.toHexString(sessionId) - + " sessionPasswd=" - + (sessionPasswd == null ? "" : "")); + this(connectString, sessionTimeout, watcher, sessionId, sessionPasswd, + canBeReadOnly, aHostProvider, null); + } - this.clientConfig = new ZKClientConfig(); + /** + * To create a ZooKeeper client object, the application needs to pass a + * connection string containing a comma separated list of host:port pairs, + * each corresponding to a ZooKeeper server. + *

+ * Session establishment is asynchronous. This constructor will initiate + * connection to the server and return immediately - potentially (usually) + * before the session is fully established. The watcher argument specifies + * the watcher that will be notified of any changes in state. This + * notification can come at any point before or after the constructor call + * has returned. + *

+ * The instantiated ZooKeeper client object will pick an arbitrary server + * from the connectString and attempt to connect to it. If establishment of + * the connection fails, another server in the connect string will be tried + * (the order is non-deterministic, as we random shuffle the list), until a + * connection is established. The client will continue attempts until the + * session is explicitly closed (or the session is expired by the server). + *

+ * Added in 3.2.0: An optional "chroot" suffix may also be appended to the + * connection string. This will run the client commands while interpreting + * all paths relative to this root (similar to the unix chroot command). + *

+ * Use {@link #getSessionId} and {@link #getSessionPasswd} on an established + * client connection, these values must be passed as sessionId and + * sessionPasswd respectively if reconnecting. Otherwise, if not + * reconnecting, use the other constructor which does not require these + * parameters. + *

+ * For backward compatibility, there is another version + * {@link #ZooKeeper(String, int, Watcher, long, byte[], boolean)} which uses + * default {@link StaticHostProvider} + * + * @param connectString + * comma separated host:port pairs, each corresponding to a zk + * server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" + * If the optional chroot suffix is used the example would look + * like: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a" + * where the client would be rooted at "/app/a" and all paths + * would be relative to this root - ie getting/setting/etc... + * "/foo/bar" would result in operations being run on + * "/app/a/foo/bar" (from the server perspective). + * @param sessionTimeout + * session timeout in milliseconds + * @param watcher + * a watcher object which will be notified of state changes, may + * also be notified for node events + * @param sessionId + * specific session id to use if reconnecting + * @param sessionPasswd + * password for this session + * @param canBeReadOnly + * (added in 3.4) whether the created client is allowed to go to + * read-only mode in case of partitioning. Read-only mode + * basically means that if the client can't find any majority + * servers but there's partitioned server it could reach, it + * connects to one in read-only mode, i.e. read requests are + * allowed while write requests are not. It continues seeking for + * majority in the background. + * @param aHostProvider + * use this as HostProvider to enable custom behaviour. + * @param clientConfig + * (added in 3.5.2) passing this conf object gives each client the flexibility of + * configuring properties differently compared to other instances + * @throws IOException in cases of network failure + * @throws IllegalArgumentException if an invalid chroot path is specified + * + * @since 3.5.5 + */ + public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, + long sessionId, byte[] sessionPasswd, boolean canBeReadOnly, + HostProvider aHostProvider, ZKClientConfig clientConfig) throws IOException { + LOG.info("Initiating client connection, connectString=" + connectString + + " sessionTimeout=" + sessionTimeout + + " watcher=" + watcher + + " sessionId=" + Long.toHexString(sessionId) + + " sessionPasswd=" + + (sessionPasswd == null ? "" : "")); + + if (clientConfig == null) { + clientConfig = new ZKClientConfig(); + } + this.clientConfig = clientConfig; watchManager = defaultWatchManager(); watchManager.defaultWatcher = watcher; - + ConnectStringParser connectStringParser = new ConnectStringParser( connectString); hostProvider = aHostProvider; @@ -1191,7 +1270,7 @@ public class ZooKeeper implements AutoCloseable { * reconnecting, use the other constructor which does not require these * parameters. *

- * This constructor uses a StaticHostProvider; there is another one + * This constructor uses a StaticHostProvider; there is another one * to enable custom behaviour. * * @param connectString diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java index f8be441..9c67374 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java @@ -29,6 +29,10 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.zookeeper.AsyncCallback.VoidCallback; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.cli.*; +import org.apache.zookeeper.client.ConnectStringParser; +import org.apache.zookeeper.client.HostProvider; +import org.apache.zookeeper.client.StaticHostProvider; +import org.apache.zookeeper.client.ZKClientConfig; import org.apache.zookeeper.common.StringUtils; import org.apache.zookeeper.data.Stat; import org.apache.zookeeper.test.ClientBase; @@ -591,4 +595,28 @@ public class ZooKeeperTest extends ClientBase { // /e is unset, its acl should remain the same. Assert.assertEquals(Ids.OPEN_ACL_UNSAFE, zk.getACL("/e", new Stat())); } + + @Test + public void testClientReconnectWithZKClientConfig() throws Exception { + ZooKeeper zk = null; + ZooKeeper newZKClient = null; + try { + zk = createClient(); + ZKClientConfig clientConfig = new ZKClientConfig(); + clientConfig.setProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET, + "org.apache.zookeeper.ClientCnxnSocketNetty"); + CountdownWatcher watcher = new CountdownWatcher(); + HostProvider aHostProvider = new StaticHostProvider( + new ConnectStringParser(hostPort).getServerAddresses()); + newZKClient = new ZooKeeper(hostPort, zk.getSessionTimeout(), watcher, + zk.getSessionId(), zk.getSessionPasswd(), false, aHostProvider, clientConfig); + watcher.waitForConnected(CONNECTION_TIMEOUT); + assertEquals("Old client session id and new clinet session id must be same", + zk.getSessionId(), newZKClient.getSessionId()); + } finally { + zk.close(); + newZKClient.close(); + } + } + }