jkrauss82 opened a new issue, #9098:
URL: https://github.com/apache/storm/issues/9098

   ## Intro and AI Disclaimer
   
   I am a long time storm user of a small storm cluster. In general, the 
cluster stays robust and stable over the course of weeks but every now and then 
we run into a situation where seemingly an error in a topology and, following 
up, a zookeeper connection loss brings a supervisor down and then the whole 
cluster becomes unstable as topologies get re-assigned, supervisors 
blacklisted, and we have to wipe the whole thing and start fresh.
   
   Since I never really could pin that down to a specific reason I used local 
AI to dig through our logs and the storm code. It came up with the report seen 
below, it also suggested a fix which I am happy to open a PR for, if that is 
okay in this repo. We currently have the fix running in production, seems to 
hold up so far.
   
   Depending on the assessment of the storm dev team I can also overwork the 
fix and implement a more suitable solution, should the proposed new class 
`ConnectionAwareRetryPolicy` in storm-client not be ideal.
   
   Everything below is written by AI but carefully reviewed by me.
   
   ## Bug Description
   
   A transient ZooKeeper connection loss (e.g. a single ensemble member closing 
its socket) causes the entire supervisor process to exit within ~600ms. All 
topology workers on that node are killed as a result.
   
   **Storm version:** 3.1.0
   **Component:** `storm-server` (supervisor), `storm-client` (CuratorUtils / 
ZK retry)
   
   ## Expected Behavior
   
   The supervisor should survive transient ZK connection blips. The ZK client's 
`SendThread` is already failovering to another ensemble member - the supervisor 
should wait for that reconnection and retry the operation, not die.
   
   ## Actual Behavior
   
   The supervisor process exits with code 20 within 629ms of the connection 
loss.
   
   ## Root Cause
   
   Three compounding issues:
   
   1. **Curator `RetryLoop` races the ZK `SendThread`.** Both operate on the 
same TCP connection. The `RetryLoop` (driven by 
`StormBoundedExponentialBackoffRetry`) blindly sleeps between retries without 
checking whether the `SendThread` has already reconnected to another ensemble 
member.
   
   2. **The retry window is too short.** With defaults 
(`storm.zookeeper.retry.times=5`, `storm.zookeeper.retry.interval=1000`), the 
total retry budget is ~30s. In practice the exception escapes before even one 
retry sleep completes, because the `RetryLoop` and `SendThread` are racing on 
the same connection.
   
   3. **`DefaultUncaughtExceptionHandler` kills the process.** Any uncaught 
`Throwable` on a `StormTimer` thread calls `Runtime.getRuntime().exit(20)`. A 
transient `KeeperException$ConnectionLoss` is treated the same as a fatal bug.
   
   ## Evidence
   
   From a supervisor daemon log:
   
   ```
   08:39:53.907  ZK server closes socket (EndOfStreamException)
   08:39:54.489  Curator ConnectionState → SUSPENDED          (+582ms)
   08:39:54.510  SupervisorHeartbeat → existsNode() → 
KeeperException$ConnectionLoss  (+603ms)
   08:39:54.536  DefaultUncaughtExceptionHandler → Utils.exitProcess(20)        
       (+629ms) ← JVM exits
   ```
   
   The ZK ensemble was healthy throughout - the restarted supervisor 
reconnected to the same ensemble within 100ms.
   
   ## Proposed Fix
   
   Two layers:
   
   ### 1. `ConnectionAwareRetryPolicy` (new class in `storm-client`)
   
   A `RetryPolicy` wrapper that tracks the `ConnectionState` via a 
`ConnectionStateListener`. When the connection is `SUSPENDED` or `LOST`, it 
calls `CuratorFramework.blockUntilConnected(sessionTimeout)` to **yield to the 
`SendThread`'s failover** instead of blind sleep+retry. On reconnection, the 
operation retries immediately on the new connection. Uses 
`storm.zookeeper.session.timeout` as the wait bound.
   
   Wired up in `CuratorUtils.newCurator()` via `AtomicReference` late binding.
   
   ### 2. Safety net in `SupervisorHeartbeat`
   
   Wrap the heartbeat body in a `try/catch` so that a total ZK outage (beyond 
the session timeout) skips the cycle instead of killing the process. A missed 
heartbeat is harmless: `nimbus.supervisor.timeout.secs` (default 30s) allows 6 
missed beats.
   
   ## Files Changed
   
   - 
`storm-client/src/jvm/org/apache/storm/utils/ConnectionAwareRetryPolicy.java` 
(new)
   - `storm-client/src/jvm/org/apache/storm/utils/CuratorUtils.java`
   - 
`storm-server/src/main/java/org/apache/storm/daemon/supervisor/timer/SupervisorHeartbeat.java`


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to