Mohsen Rezaei created FLINK-41354:
-------------------------------------

             Summary: Dispatcher never terminates when it is stopped while a 
cleanup retry is pending, so the next leader never starts
                 Key: FLINK-41354
                 URL: https://issues.apache.org/jira/browse/FLINK-41354
             Project: Flink
          Issue Type: Bug
          Components: Runtime / Coordination
    Affects Versions: 2.1.3, 2.2.1, 2.3.0, 2.0.2, 2.4.1
            Reporter: Mohsen Rezaei


If the Dispatcher is stopped while the cleanup of a globally terminated job is 
waiting for a retry, it never finishes stopping. With Kubernetes HA this leaves 
the JobManager holding the leader lease while its REST API answers {{HTTP 503: 
Service temporarily unavailable
due to an ongoing leader election}} until the process is restarted, because 
{{DefaultDispatcherRunner}} only starts the next {{DispatcherLeaderProcess}} 
after the previous one has terminated.

h3. Observed

Flink 2.3.0, standalone session cluster, Kubernetes HA, one JobManager:
# A job reaches FAILED ({{restart-strategy: none}}; FINISHED and CANCELED 
behave the same).
# Its first global cleanup attempt fails and a retry is scheduled. I caused the 
failure by changing the holder in the leader {{ConfigMap}}: the execution plan 
store only writes while the JobManager is the leader ({{Could not remove 
execution plan with job id ... from KubernetesStateHandleStore}}).
# About 370 ms later: {{DefaultDispatcherRunner was revoked the leadership}}. 
About 8s later the JobManager regains the lease:
{{DefaultDispatcherRunner was granted leadership ... Creating new 
DispatcherLeaderProcess}}.
# Nothing is logged after that, and REST answers 503 for as long as the job is 
active (over 7 minutes in testing).

The same lease loss with a running job and no cleanup in flight recovers in 
about 9s. A new unit test reproduces the hang on {{release-2.3.0}} and on 
{{master}}. It is modelled on 
{{DispatcherCleanupITCase#testCleanupAfterLeadershipChange}}, with a retrying 
cleanup strategy instead of {{NONE}} and the {{Dispatcher}} stopped after the 
first failed attempt.

Any failed cleanup attempt shortly before the Dispatcher stops can trigger it, 
for example another JobManager taking over the lease, or the Kubernetes API 
failing.

h3. Cause

* {{RpcEndpoint#internalCallOnStop}} closes the resource registry first. That 
shuts down the {{MainThreadExecutor}}'s scheduled executor
(FLINK-25085) and drops every pending scheduled task.
* {{DefaultResourceCleaner}} schedules cleanup retries on that executor 
({{FutureUtils#retryWithDelay}}, FLINK-25433), so a pending retry
is dropped and its future never completes.
* {{Dispatcher#onStop}} waits for {{jobManagerRunnerTerminationFutures}}, which 
for a globally terminated job include that cleanup
({{Dispatcher#removeJob}}).

{{testCleanupAfterLeadershipChange}} uses cleanup strategy {{NONE}}, so this 
case is not covered. The default strategy ({{exponential-delay}}) retries 
without a limit.

h3. Possible fix

Let {{ResourceCleaner}} stop retrying, and call it at the start of 
{{Dispatcher#onStop}}. A cleanup waiting for a retry then fails instead of 
hanging, and a running attempt is not retried if it fails. An unfinished global 
cleanup stays dirty in the {{JobResultStore}}, and the next leader resumes it. 
I have this working with a unit test, and the 
{{org.apache.flink.runtime.dispatcher}} tests pass on 2.3.0.

[~mapohl], does this direction sound right to you? If so, you can assign the 
ticket to me and I'll open a PR for the fix.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to