CreeperBeatz commented on PR #70690:
URL: https://github.com/apache/airflow/pull/70690#issuecomment-5662117805

   Independent production reproduction of this, on released versions, in case a 
real-world
   data point is useful while the PR is under review.
   
   **Versions:** Airflow 3.3.0, `apache-airflow-providers-celery` 3.21.0, 
celery 5.6.3,
   kombu 5.6.2, redis-py 6.4.0, Python 3.12, 6 cores, redis broker local to the 
scheduler,
   Postgres result backend. `[celery] sync_parallelism` unset, so it resolved to
   `max(1, cpu_count()-1)` = 5.
   
   The scheduler stopped scheduling at 08:20:09 UTC and stayed wedged for 23 
minutes until
   restarted by hand. Its last log line is the enqueue itself:
   
   ```
   08:20:09 Trying to enqueue tasks: [...] for executor: 
CeleryExecutor(parallelism=256)
   ```
   
   Rather than py-spy I captured `/proc/<pid>/stack` from the host, which shows 
the same
   thing from the kernel side and may be a useful complement to the dump in the 
description:
   
   ```
   child 2747820 -- Threads: 1
     [<0>] futex_do_wait+0x3a/0x70      <-- waiting on a lock, but the process 
has ONE thread,
     [<0>] __futex_wait+0x99/0x100          so no thread in it can ever release 
that lock
     [<0>] futex_wait+0x72/0x120
   
   child 2747819 -- Threads: 1
     [<0>] ksys_read+0xc6/0xf0          <-- blocked reading the result pipe
   
   parent 2774404 -- Threads: 2
     [<0>] futex_do_wait+0x3a/0x70      <-- waiting on the pool
   ```
   
   Both children were forked at 08:20:10, matching the last log line exactly. 
The single-thread
   child blocked in `futex_wait` is, I think, the clearest possible signature 
of the inherited-lock
   mechanism described here: there is no owning thread left in that process to 
release it.
   
   Supporting evidence that nothing else was involved:
   
   - redis healthy: 2.6 MB used, every queue at depth 0, 
`rejected_connections:0` - the
     workloads were never published
   - Postgres: no lock waits, no long-running queries, connection count well 
under the limit
   - `SchedulerJob` heartbeat age 1036 s, while `TriggererJob` and 
`DagProcessorJob` on the same
     host kept beating every 5-7 s
   - the host itself was not resource constrained - CPU load and free memory 
both well within
     normal for this deployment
   
   Two notes that may be worth folding into the docs part of this change:
   
   **1. Nothing can restart a scheduler in this state** 
   
   The process never exits, so a container restart policy never
   fires and the orchestrator reports a perfectly healthy container throughout. 
Meanwhile
   `[scheduler] enable_health_check` defaults to `False`, so there is no 
scheduler-side
   liveness signal either, and the webserver's `/api/v2/monitor/health` kept 
reporting the
   scheduler healthy right up until we queried the `Job` heartbeat directly. 
The failure is
   therefore invisible to every automatic recovery path at once, and only 
manual intervention
   ended it. A line in the docs pointing out that this hang cannot be caught 
without
   `enable_health_check` (or an `airflow jobs check --job-type SchedulerJob` 
probe) would have
   saved us the outage.
   
   **2. `[celery] sync_parallelism = 1` is an effective mitigation on the 
released versions above, and is what we deployed.** 
   
   It takes the existing in-process branch and never forks,
   so the hazard is gone rather than made less likely. Worth noting the cost is 
close to zero
   in a setup like ours: publishing is one short round-trip to a local broker,
   `[scheduler] max_tis_per_query` defaults to 16 so batches are far below 
where a pool could
   pay back its own startup, and with a `DatabaseBackend` result backend 
`BulkStateFetcher`
   already uses the bulk `SELECT ... WHERE task_id IN (...)` path, so lowering 
it has no effect
   on state fetching at all. That last point may be worth stating explicitly 
for anyone on an
   affected version who wants to mitigate before this lands.


-- 
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