Skip to content

TEZ-4759: An external AM never re-registers after a ZooKeeper session loss - #543

Merged
abstractdog merged 2 commits into
apache:masterfrom
deniskuzZ:TEZ-4759
Nov 9, 2026
Merged

abstractdog merged 2 commits into
apache:masterfrom
deniskuzZ:TEZ-4759

Conversation

@deniskuzZ

Copy link
Copy Markdown
Member
  • ZkAMRegistry.add() wrote the AMRecord once, as a bare EPHEMERAL node; a session expiry deletes it and nothing re-creates it, so clients see an empty registry while the AM keeps running
  • Hold a Curator PersistentNode per AMRecord: it re-creates the node after a session loss or a delete; remove() closes it
  • add() fails when the node is not created within the ZooKeeper connection timeout
  • TestZkAMRegistry: after the ZooKeeper server is replaced, the AMRecord node is back

… loss

- ZkAMRegistry.add() wrote the AMRecord once, as a bare EPHEMERAL node; a session expiry deletes it and nothing
  re-creates it, so clients see an empty registry while the AM keeps running
- Hold a Curator PersistentNode per AMRecord: it re-creates the node after a session loss or a delete; remove()
  closes it
- add() fails when the node is not created within the ZooKeeper connection timeout
- TestZkAMRegistry: after the ZooKeeper server is replaced, the AMRecord node is back
@tez-yetus

Copy link
Copy Markdown

🎊 +1 overall

Vote Subsystem Runtime Logfile Comment
+0 🆗 reexec 0m 8s Docker mode activated.
_ Prechecks _
+1 💚 dupname 0m 0s No case conflicting files found.
+0 🆗 detsecrets 0m 0s detect-secrets was not available.
+1 💚 @author 0m 0s The patch does not contain any @author tags.
+1 💚 test4tests 0m 0s The patch appears to include 1 new or modified test files.
_ master Compile Tests _
+1 💚 mvninstall 3m 25s master passed
+1 💚 compile 2m 37s master passed
+1 💚 checkstyle 0m 31s master passed
+1 💚 javadoc 0m 21s master passed
+0 🆗 spotbugs 1m 2s tez-dag in master has 537 extant spotbugs warnings.
_ Patch Compile Tests _
+1 💚 mvninstall 2m 13s the patch passed
+1 💚 codespell 0m 50s No new issues.
+1 💚 compile 2m 34s the patch passed
+1 💚 javac 2m 34s the patch passed
+1 💚 blanks 0m 0s The patch has no blanks issues.
+1 💚 checkstyle 0m 23s the patch passed
+1 💚 javadoc 0m 20s the patch passed
+1 💚 spotbugs 1m 9s the patch passed
_ Other Tests _
+1 💚 unit 60m 51s root in the patch passed.
+1 💚 asflicense 0m 25s The patch does not generate ASF License warnings.
77m 56s
Subsystem Report/Notes
Docker ClientAPI=1.56 ServerAPI=1.56 base: https://ci-hadoop.apache.org/job/tez-multibranch/job/PR-543/2/artifact/out/Dockerfile
Optional Tests dupname compile unit asflicense javac javadoc spotbugs checkstyle codespell detsecrets
uname Linux fb13607be12e 5.15.0-190-generic #200-Ubuntu SMP Fri Aug 7 15:06:04 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
Build tool maven
Personality tez-personality.sh
git revision master / ae2756e
Default Java Eclipse Adoptium-21.0.12.1+1-LTS
Test Results https://ci-hadoop.apache.org/job/tez-multibranch/job/PR-543/2/testReport/
Max. process+thread count 1396 (vs. ulimit of 5500)
modules C: tez-dag U: tez-dag
Console output https://ci-hadoop.apache.org/job/tez-multibranch/job/PR-543/2/console
versions git=2.43.0 maven=3.9.15 spotbugs=4.9.3 codespell=2.4.1
Powered by Apache Yetus 0.15.1 https://yetus.apache.org

This message was automatically generated.

@abstractdog abstractdog left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits, otherwise looks good, thanks Denys

if (node != null) {
node.close(); // deletes the node
}
LOG.info("Deleted AMRecord from zkpath {}", path);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this logs "Deleted AMRecord from zkpath" even when nothing was deleted, how about:

  if (node == null) {
    LOG.debug("AMRecord {} was not registered by this instance, nothing to remove", server);
    return;
  }
  node.close(); // deletes the node
  LOG.info("Deleted AMRecord from zkpath {}", pathFor(server));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

byte[] json = AMRegistryUtils.recordToJsonString(server).getBytes(StandardCharsets.UTF_8);
PersistentNode node = new PersistentNode(client, CreateMode.EPHEMERAL, false, path, json);
node.start();
if (!node.waitForInitialCreate(zkConfig.getConnectionTimeoutMs(), TimeUnit.MILLISECONDS)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if waitForInitialCreate throws InterruptedException, the node is already started but never closed or put into amNodes, it stays active, so its reconnect listener and NodeDeleted watch keep re-creating the path until close() shuts the Curator client down

what about extra care by:

boolean created;
try {
  created = node.waitForInitialCreate(zkConfig.getConnectionTimeoutMs(), TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
  node.close();
  throw e;
}
if (!created) {
  node.close();
  throw new IOException("Timed out creating AMRecord at zkpath " + path);
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! It's now closed on any failure of the wait

byte[] json = AMRegistryUtils.recordToJsonString(server).getBytes(StandardCharsets.UTF_8);
PersistentNode node = new PersistentNode(client, CreateMode.EPHEMERAL, false, path, json);
node.start();
if (!node.waitForInitialCreate(zkConfig.getConnectionTimeoutMs(), TimeUnit.MILLISECONDS)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add() used to be bounded by the client's retry policy (tez.am.curator.max-retries/backoff-sleep), and now waits a single getConnectionTimeoutMs(). The setting still applies to generateNewId() and to PersistentNode's background creates, so it isn't dead, but someone tuning max-retries might expect registration to wait longer. Scaling the wait by getCuratorMaxRetries() would only make that setting mean something it doesn't, so I'd keep the single timeout and add a comment saying add() waits one connection timeout for the initial create and is not governed by the retry settings.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a comment

- remove() logs the delete only when this instance registered the AMRecord
- add() closes the node when waiting for the initial create fails, an interrupt included
- Comment: the initial create waits one connection timeout, not the Curator retry settings
@abstractdog
abstractdog self-requested a review November 9, 2026 12:23

@abstractdog abstractdog left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, pending tests

@tez-yetus

Copy link
Copy Markdown

🎊 +1 overall

Vote Subsystem Runtime Logfile Comment
+0 🆗 reexec 2m 32s Docker mode activated.
_ Prechecks _
+1 💚 dupname 0m 0s No case conflicting files found.
+0 🆗 detsecrets 0m 0s detect-secrets was not available.
+1 💚 @author 0m 0s The patch does not contain any @author tags.
+1 💚 test4tests 0m 0s The patch appears to include 1 new or modified test files.
_ master Compile Tests _
+1 💚 mvninstall 3m 11s master passed
+1 💚 compile 2m 37s master passed
+1 💚 checkstyle 0m 29s master passed
+1 💚 javadoc 0m 18s master passed
+0 🆗 spotbugs 1m 1s tez-dag in master has 537 extant spotbugs warnings.
_ Patch Compile Tests _
+1 💚 mvninstall 2m 28s the patch passed
+1 💚 codespell 0m 52s No new issues.
+1 💚 compile 2m 39s the patch passed
+1 💚 javac 2m 39s the patch passed
+1 💚 blanks 0m 0s The patch has no blanks issues.
+1 💚 checkstyle 0m 24s the patch passed
+1 💚 javadoc 0m 19s the patch passed
+1 💚 spotbugs 1m 8s the patch passed
_ Other Tests _
+1 💚 unit 60m 52s root in the patch passed.
+1 💚 asflicense 0m 23s The patch does not generate ASF License warnings.
80m 21s
Subsystem Report/Notes
Docker ClientAPI=1.56 ServerAPI=1.56 base: https://ci-hadoop.apache.org/job/tez-multibranch/job/PR-543/3/artifact/out/Dockerfile
Optional Tests dupname compile unit asflicense javac javadoc spotbugs checkstyle codespell detsecrets
uname Linux 35bcb1f2bae6 5.15.0-190-generic #200-Ubuntu SMP Fri Aug 7 15:06:04 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
Build tool maven
Personality tez-personality.sh
git revision master / b434f5c
Default Java Eclipse Adoptium-21.0.13+9-LTS
Test Results https://ci-hadoop.apache.org/job/tez-multibranch/job/PR-543/3/testReport/
Max. process+thread count 2125 (vs. ulimit of 5500)
modules C: tez-dag U: tez-dag
Console output https://ci-hadoop.apache.org/job/tez-multibranch/job/PR-543/3/console
versions git=2.43.0 maven=3.9.15 spotbugs=4.9.3 codespell=2.4.1
Powered by Apache Yetus 0.15.1 https://yetus.apache.org

This message was automatically generated.

@abstractdog
abstractdog merged commit f48668b into apache:master Nov 9, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants