-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Messenger Supervisor graceful shutdown #41906
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I think this is wrongly assumed (at least in 5.3).
pcntl_signal(\SIGTERM, static function () use ($event) {
$event->getWorker()->stop();
}); and It's the same flag that is used with In my case I needed to interrupt long running jobs so I've tweak it like: pcntl_signal(\SIGTERM, static function () use ($event, $jobManager) {
$event->getWorker()->stop();
$jobManager->stop(); // tell the sub system that it would be cool to let go when possible
}); But effectively there is something to do with supervisor regarding exit codes #42029 |
I made tests and it appears to be working correctly as long as the pcntl extension is installed, good news ! But still, I think we could add a short section in the documentation. I'm closing this issue and I'll try to make a PR on the docs repo. Thank you @quazardous ! |
This PR was squashed before being merged into the 4.4 branch. Discussion ---------- [Messenger] Supervisor graceful shutdown >[Messenger] Add details on graceful shutdown Added a section to Messenger's documentation on the workers SIGTERM signal handling when the pcntl extension is installed. I'm making this PR because I struggled to perform a graceful shutdown as described in symfony/symfony#41906 and I think this could help other users in the future. This is my first contribution, I'd be happy to rework anything which doesn't meet the documentation standards. Commits ------- 79d5a07 [Messenger] Supervisor graceful shutdown
Description:
I have a proposition to perform a graceful shutdown of the
messenger:consume
command with Supervisor, especially useful when the Symfony application is in a Docker container.Given a Docker image which entrypoint uses
supervisord
, stopping it sends aSIGTERM
signal to Supervisor which sends aSIGTERM
signal to the programs (themessenger:consume
commands), stopping the processes immediately. The issue I see here is that it could stop a message from being processed completely by its handler, thus loosing a message per worker process.Goal: make the
messenger:consume
command finish processing its current message before exiting.Failing workarounds:
Using a bind mount for the source code and calling
messenger:stop-workers
implies we can't update the Docker image itself.Calling
messenger:stop-workers
before shutting down the container does not work because the command returns as soon as the "signal" to stop the workers is sent, therefore Docker/Supervisor will kill the processes even if a message is currently being processed.Editing the supervisor.conf file on the fly (e.g. using
sed
) to setautorestart=false
and then callingsupervisorctl
toreread
andupdate
does not work assupervisorctl update
kills and restarts the processes immediately.And I tried a lot more of failing workarounds I just forgot about.
Example of a working solution:
Symfony 5.2 introduced the SignalableCommandInterface to allow commands to react to signals.
I created a clone of the
ConsumeMessagesCommand
implementing this feature:This service has been based on the original command as such:
Only this is needed in Symfony's codebase to make it work. I tested with a message handler which loops from 0 to 30 and prints a number per second (I'm not pasting it here to avoid making this issue longer): when calling
docker-compose down
in the middle of a handler's execution it waits for it to finish before exiting.Then comes the (shortened) Supervisor configuration to make use of it using the
stopsignal
(which signal to send to the program) andstopwaitsecs
(how long is the timeout before aSIGKILL
is sent):About Docker, if the shutdown is specified in a CLI command, there is a
-t
option for both docker stop and docker-compose down commands to define a timeout between theSIGTERM
andSIGKILL
sent to Supervisor.If using a docker-compose.yml file, the stop_grace_period key can be used instead.
The users would just have to set the grace period themselves depending on their message handlers, Symfony wouldn't be responsible for it. If the users don't want a graceful shutdown they just don't set a grace period nor specific signal.
Questions:
I think the
messenger:consume
command could implementSignalableCommandInterface
, and that the Docker/Supervisor configuration suggestion could be added to the documentation.Is this feature acceptable ?
I used
SIGUSR1
but wouldSIGTERM
be acceptable ? I can't think about any cases where someone would like to get the message processing being stop in the middle, but I may be wrong.I'd love to make the PR myself for this, should I target a specific branch as the interface was released in 5.2 and Messenger currently requires the Console component in
"^4.4|^5.0"
versions ? Do you have any hints for me to write a decent test for signal handling of the command ?Thanks for reading this long issue :-)
The text was updated successfully, but these errors were encountered: