You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by an...@apache.org on 2019/03/12 18:08:46 UTC

[zookeeper] branch master updated: ZOOKEEPER-2474: add a way for client to reattach to a session when using ZKClientConfig

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 <ma...@sina.com>
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 <ma...@sina.com>
    
    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 ? "<null>" : "<hidden>"));
+    	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.
+     * <p>
+     * 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.
+     * <p>
+     * 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).
+     * <p>
+     * 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).
+     * <p>
+     * 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.
+     * <p>
+     * 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 ? "<null>" : "<hidden>"));
+
+        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.
      * <p>
-     * 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();
+        }
+    }
+
 }