Skip to content

Commit 7f069be

Browse files
committed
ZOOKEEPER-4923: Add timeout to control brand-new session establishment
The default behavior is retrying endlessly to establish a brand-new session. This partially rollback ZOOKEEPER-4508 to keep consistent with versions prior to 3.9.3 (excluded), so to maintain compatibility with third party libraries. Refs: ZOOKEEPER-4508, ZOOKEEPER-4921, ZOOKEEPER-4923 and https://lists.apache.org/thread/nfb9z7rhgglbjzfxvg4z2m3pks53b3c1
1 parent 840a666 commit 7f069be

File tree

7 files changed

+179
-20
lines changed

7 files changed

+179
-20
lines changed

zookeeper-server/src/main/java/org/apache/zookeeper/ClientCnxn.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ static class AuthData {
168168

169169
private final int sessionTimeout;
170170

171+
private final long newSessionTimeout;
172+
171173
private final ZKWatchManager watchManager;
172174

173175
private long sessionId;
@@ -398,6 +400,36 @@ public ClientCnxn(
398400
long sessionId,
399401
byte[] sessionPasswd,
400402
boolean canBeReadOnly
403+
) throws IOException {
404+
this(hostProvider, sessionTimeout, Long.MAX_VALUE, clientConfig, defaultWatcher, clientCnxnSocket, sessionId, sessionPasswd, canBeReadOnly);
405+
}
406+
407+
/**
408+
* Creates a connection object. The actual network connect doesn't get
409+
* established until needed. The start() instance method must be called
410+
* after construction.
411+
*
412+
* @param hostProvider the list of ZooKeeper servers to connect to
413+
* @param sessionTimeout the timeout for connections.
414+
* @param newSessionTimeout the timeout before giving up brand-new session establishment.
415+
* @param clientConfig the client configuration.
416+
* @param defaultWatcher default watcher for this connection
417+
* @param clientCnxnSocket the socket implementation used (e.g. NIO/Netty)
418+
* @param sessionId session id if re-establishing session
419+
* @param sessionPasswd session passwd if re-establishing session
420+
* @param canBeReadOnly whether the connection is allowed to go to read-only mode in case of partitioning
421+
* @throws IOException in cases of broken network
422+
*/
423+
public ClientCnxn(
424+
HostProvider hostProvider,
425+
int sessionTimeout,
426+
long newSessionTimeout,
427+
ZKClientConfig clientConfig,
428+
Watcher defaultWatcher,
429+
ClientCnxnSocket clientCnxnSocket,
430+
long sessionId,
431+
byte[] sessionPasswd,
432+
boolean canBeReadOnly
401433
) throws IOException {
402434
this.hostProvider = hostProvider;
403435
this.sessionTimeout = sessionTimeout;
@@ -413,6 +445,7 @@ public ClientCnxn(
413445
this.connectTimeout = sessionTimeout / hostProvider.size();
414446
this.readTimeout = sessionTimeout * 2 / 3;
415447
this.expirationTimeout = sessionTimeout * 4 / 3;
448+
this.newSessionTimeout = newSessionTimeout == 0 ? expirationTimeout : newSessionTimeout;
416449

417450
this.sendThread = new SendThread(clientCnxnSocket);
418451
this.eventThread = new EventThread();
@@ -1192,7 +1225,12 @@ public void run() {
11921225
to = connectTimeout - clientCnxnSocket.getIdleSend();
11931226
}
11941227

1195-
int expiration = expirationTimeout - clientCnxnSocket.getIdleRecv();
1228+
long expiration;
1229+
if (sessionId == 0) {
1230+
expiration = newSessionTimeout - clientCnxnSocket.getIdleRecv();
1231+
} else {
1232+
expiration = expirationTimeout - clientCnxnSocket.getIdleRecv();
1233+
}
11961234
if (expiration <= 0) {
11971235
String warnInfo = String.format(
11981236
"Client session timed out, have not heard from server in %dms for session id 0x%s",

zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeper.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,7 @@ public ZooKeeper(
671671
ClientCnxn createConnection(
672672
HostProvider hostProvider,
673673
int sessionTimeout,
674+
long newSessionTimeout,
674675
ZKClientConfig clientConfig,
675676
Watcher defaultWatcher,
676677
ClientCnxnSocket clientCnxnSocket,
@@ -681,6 +682,7 @@ ClientCnxn createConnection(
681682
return new ClientCnxn(
682683
hostProvider,
683684
sessionTimeout,
685+
newSessionTimeout,
684686
clientConfig,
685687
defaultWatcher,
686688
clientCnxnSocket,
@@ -1110,6 +1112,7 @@ public ZooKeeper(ZooKeeperOptions options) throws IOException {
11101112
cnxn = createConnection(
11111113
hostProvider,
11121114
sessionTimeout,
1115+
options.getNewSessionTimeout(),
11131116
this.clientConfig,
11141117
watcher,
11151118
getClientCnxnSocket(),

zookeeper-server/src/main/java/org/apache/zookeeper/client/ZooKeeperBuilder.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
2222
import java.io.IOException;
2323
import java.net.InetSocketAddress;
24+
import java.time.Duration;
2425
import java.util.Collection;
2526
import java.util.function.Function;
27+
import javax.annotation.Nullable;
2628
import org.apache.yetus.audience.InterfaceAudience;
2729
import org.apache.yetus.audience.InterfaceStability;
2830
import org.apache.zookeeper.Watcher;
@@ -37,6 +39,7 @@
3739
public class ZooKeeperBuilder {
3840
private final String connectString;
3941
private final int sessionTimeout;
42+
private long newSessionTimeout = Long.MAX_VALUE;
4043
private Function<Collection<InetSocketAddress>, HostProvider> hostProvider;
4144
private Watcher defaultWatcher;
4245
private boolean canBeReadOnly = false;
@@ -126,6 +129,21 @@ public ZooKeeperBuilder withSession(long sessionId, byte[] sessionPasswd) {
126129
return this;
127130
}
128131

132+
/**
133+
* Specifies timeout to establish a brand-new session.
134+
*
135+
* @param timeout timeout to get {@link org.apache.zookeeper.Watcher.Event.KeeperState#Expired} in
136+
* establishing a brand-new session. {@code null}, which is the default, means endless
137+
* retry until connected, {@code Duration.ZERO} means a sensible value deduced from
138+
* specified session timeout.
139+
* @return this
140+
* @since 3.10.0
141+
*/
142+
public ZooKeeperBuilder withNewSessionTimeout(@Nullable Duration timeout) {
143+
this.newSessionTimeout = timeout == null ? Long.MAX_VALUE : timeout.toMillis();
144+
return this;
145+
}
146+
129147
/**
130148
* Specifies the client config used to construct ZooKeeper instances.
131149
*
@@ -150,6 +168,7 @@ public ZooKeeperOptions toOptions() {
150168
return new ZooKeeperOptions(
151169
connectString,
152170
sessionTimeout,
171+
newSessionTimeout,
153172
defaultWatcher,
154173
hostProvider,
155174
canBeReadOnly,

zookeeper-server/src/main/java/org/apache/zookeeper/client/ZooKeeperOptions.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
public class ZooKeeperOptions {
3333
private final String connectString;
3434
private final int sessionTimeout;
35+
private final long newSessionTimeout;
3536
private final Watcher defaultWatcher;
3637
private final Function<Collection<InetSocketAddress>, HostProvider> hostProvider;
3738
private final boolean canBeReadOnly;
@@ -41,6 +42,7 @@ public class ZooKeeperOptions {
4142

4243
ZooKeeperOptions(String connectString,
4344
int sessionTimeout,
45+
long newSessionTimeout,
4446
Watcher defaultWatcher,
4547
Function<Collection<InetSocketAddress>, HostProvider> hostProvider,
4648
boolean canBeReadOnly,
@@ -49,6 +51,7 @@ public class ZooKeeperOptions {
4951
ZKClientConfig clientConfig) {
5052
this.connectString = connectString;
5153
this.sessionTimeout = sessionTimeout;
54+
this.newSessionTimeout = newSessionTimeout;
5255
this.hostProvider = hostProvider;
5356
this.defaultWatcher = defaultWatcher;
5457
this.canBeReadOnly = canBeReadOnly;
@@ -65,6 +68,10 @@ public int getSessionTimeout() {
6568
return sessionTimeout;
6669
}
6770

71+
public long getNewSessionTimeout() {
72+
return newSessionTimeout;
73+
}
74+
6875
public Watcher getDefaultWatcher() {
6976
return defaultWatcher;
7077
}

zookeeper-server/src/test/java/org/apache/zookeeper/ClientCnxnSocketFragilityTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ class CustomClientCnxn extends ClientCnxn {
282282
public CustomClientCnxn(
283283
HostProvider hostProvider,
284284
int sessionTimeout,
285+
long newSessionTimeout,
285286
ZKClientConfig zkClientConfig,
286287
Watcher defaultWatcher,
287288
ClientCnxnSocket clientCnxnSocket,
@@ -292,6 +293,7 @@ public CustomClientCnxn(
292293
super(
293294
hostProvider,
294295
sessionTimeout,
296+
newSessionTimeout,
295297
zkClientConfig,
296298
defaultWatcher,
297299
clientCnxnSocket,
@@ -357,6 +359,7 @@ public boolean isAlive() {
357359
ClientCnxn createConnection(
358360
HostProvider hostProvider,
359361
int sessionTimeout,
362+
long newSessionTimeout,
360363
ZKClientConfig clientConfig,
361364
Watcher defaultWatcher,
362365
ClientCnxnSocket clientCnxnSocket,
@@ -369,6 +372,7 @@ ClientCnxn createConnection(
369372
ClientCnxnSocketFragilityTest.this.cnxn = new CustomClientCnxn(
370373
hostProvider,
371374
sessionTimeout,
375+
newSessionTimeout,
372376
clientConfig,
373377
defaultWatcher,
374378
clientCnxnSocket,

zookeeper-server/src/test/java/org/apache/zookeeper/ClientRequestTimeoutTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ class CustomClientCnxn extends ClientCnxn {
225225
CustomClientCnxn(
226226
HostProvider hostProvider,
227227
int sessionTimeout,
228+
long newSessionTimeout,
228229
ZKClientConfig clientConfig,
229230
Watcher defaultWatcher,
230231
ClientCnxnSocket clientCnxnSocket,
@@ -235,6 +236,7 @@ class CustomClientCnxn extends ClientCnxn {
235236
super(
236237
hostProvider,
237238
sessionTimeout,
239+
newSessionTimeout,
238240
clientConfig,
239241
defaultWatcher,
240242
clientCnxnSocket,
@@ -286,6 +288,7 @@ public CustomZooKeeper(String connectString, int sessionTimeout, Watcher watcher
286288
ClientCnxn createConnection(
287289
HostProvider hostProvider,
288290
int sessionTimeout,
291+
long newSessionTimeout,
289292
ZKClientConfig clientConfig,
290293
Watcher defaultWatcher,
291294
ClientCnxnSocket clientCnxnSocket,
@@ -296,6 +299,7 @@ ClientCnxn createConnection(
296299
return new CustomClientCnxn(
297300
hostProvider,
298301
sessionTimeout,
302+
newSessionTimeout,
299303
clientConfig,
300304
defaultWatcher,
301305
clientCnxnSocket,

0 commit comments

Comments
 (0)