Skip to content

Commit 96f6f40

Browse files
committed
Messenger process managers
Add information about mysql timeouts, supervisor FATAL, systemd user services.
1 parent 5514b60 commit 96f6f40

File tree

1 file changed

+132
-4
lines changed

1 file changed

+132
-4
lines changed

messenger.rst

+132-4
Original file line numberDiff line numberDiff line change
@@ -462,22 +462,23 @@ Deploying to Production
462462

463463
On production, there are a few important things to think about:
464464

465-
**Use Supervisor to keep your worker(s) running**
465+
**Use a process manager like Supervisor or systemd to keep your worker(s) running**
466466
You'll want one or more "workers" running at all times. To do that, use a
467-
process control system like :ref:`Supervisor <messenger-supervisor>`.
467+
process control system like :ref:`Supervisor <messenger-supervisor>`
468+
or :ref:`systemd <messenger-systemd>`.
468469

469470
**Don't Let Workers Run Forever**
470471
Some services (like Doctrine's EntityManager) will consume more memory
471472
over time. So, instead of allowing your worker to run forever, use a flag
472473
like ``messenger:consume --limit=10`` to tell your worker to only handle 10
473-
messages before exiting (then Supervisor will create a new process). There
474+
messages before exiting (then the process manager will create a new process). There
474475
are also other options like ``--memory-limit=128M`` and ``--time-limit=3600``.
475476

476477
**Restart Workers on Deploy**
477478
Each time you deploy, you'll need to restart all your worker processes so
478479
that they see the newly deployed code. To do this, run ``messenger:stop-workers``
479480
on deploy. This will signal to each worker that it should finish the message
480-
it's currently handling and shut down gracefully. Then, Supervisor will create
481+
it's currently handling and shut down gracefully. Then, the process manager will create
481482
new worker processes. The command uses the :ref:`app <cache-configuration-with-frameworkbundle>`
482483
cache internally - so make sure this is configured to use an adapter you like.
483484

@@ -633,6 +634,132 @@ config and start your workers:
633634
634635
See the `Supervisor docs`_ for more details.
635636

637+
If a worker dependency like your database server is down, or timeout is reached,
638+
you can try to add reconnect logic, or just quit the worker (catch Exception,
639+
PDOException or do something more fine grained):
640+
641+
// SomeMessageHandler.php
642+
public function __invoke(SomeMessage $message): void
643+
{
644+
try {
645+
$thing = $this->someRepository->find($message->getThingId());
646+
if (null === $thing) {
647+
return;
648+
}
649+
$this->thingService->doStuff($thing);
650+
} catch (\Exception $e) {
651+
echo 'Received exception "'.$e->getMessage().'" from "'.get_class($e).'". Quitting worker';
652+
exit(1);
653+
}
654+
}
655+
656+
But, then you can end up in a situation where the supervisor job gets into a
657+
FATAL (too many start retries) state. You can prevent this by wrapping the
658+
Symfony script with a shell script:
659+
660+
.. code-block:: bash
661+
662+
#!/bin/bash
663+
664+
# Supervisor sends TERM to services when stopped.
665+
# This wrapper has to pass the signal to it's child.
666+
# Note that we send TERM (graceful) instead of KILL (immediate).
667+
_term() {
668+
echo "[GOT TERM, SIGNALING CHILD]"
669+
kill -TERM $child 2>/dev/null
670+
exit 1
671+
}
672+
673+
trap _term SIGTERM
674+
675+
# Execute console.php with whatever arguments were specified to this script
676+
"$@" &
677+
child=$!
678+
wait "$child"
679+
680+
# Delay to prevent supervisor from restarting too fast on failure
681+
sleep 30
682+
683+
# Return 1 so supervisor will restart the script
684+
exit 1
685+
686+
The worker would then look like this:
687+
688+
.. code-block:: ini
689+
690+
;/etc/supervisor/conf.d/messenger-worker.conf
691+
[program:messenger-consume]
692+
command=/path/to/your/console_wrapper php /path/to/your/app/bin/console messenger:consume async --time-limit=3600
693+
...
694+
695+
.. _messenger-systemd:
696+
697+
Systemd Configuration
698+
~~~~~~~~~~~~~~~~~~~~~
699+
700+
While Supervisor is a great tool, it has the disadvantage that you need system
701+
access to run it. Systemd has become the standard on most Linux distributions,
702+
and has a good alternative called user services.
703+
704+
Systemd user service configuration files typically live in a ``~/.config/systemd/user``
705+
directory. For example, you can create a new ``messenger-worker.service`` file. Or a
706+
``[email protected]`` file if you want more instances running at the same time:
707+
708+
.. code-block:: text
709+
710+
[Unit]
711+
Description=Symfony messenger-consume %i
712+
713+
[Service]
714+
ExecStart=php /path/to/your/app/bin/console messenger:consume async --time-limit=3600
715+
Restart=always
716+
RestartSec=30
717+
718+
[Journal]
719+
Storage=persistent
720+
721+
[Install]
722+
WantedBy=default.target
723+
724+
Now, tell systemd to enable and start one worker:
725+
726+
.. code-block:: terminal
727+
728+
$ systemctl --user enable [email protected]
729+
730+
$ systemctl --user start [email protected]
731+
732+
Then enable and start another 19:
733+
734+
.. code-block:: terminal
735+
736+
$ systemctl --user enable messenger-worker@{2..20}.service
737+
738+
$ systemctl --user start messenger-worker@{2..20}.service
739+
740+
If you would change your service config file, reload the daemon:
741+
742+
.. code-block:: terminal
743+
744+
$ systemctl --user daemon-reload
745+
746+
Restart all your consumers:
747+
748+
.. code-block:: terminal
749+
750+
$ systemctl --user restart messenger-consume@*.service
751+
752+
Logs are manged by journald and can be worked with using the journalctl
753+
command, but you do need elevated privileges (sudo) for that:
754+
755+
.. code-block:: terminal
756+
757+
$ sudo journalctl -f [email protected]
758+
759+
$ sudo journalctl -f _UID=$UID
760+
761+
See the `systemd docs`_ for more details.
762+
636763
.. _messenger-retries-failures:
637764

638765
Retries & Failures
@@ -1663,4 +1790,5 @@ Learn more
16631790
.. _`Enqueue's transport`: https://github.com/sroze/messenger-enqueue-transport
16641791
.. _`streams`: https://redis.io/topics/streams-intro
16651792
.. _`Supervisor docs`: http://supervisord.org/
1793+
.. _`systemd docs`: https://www.freedesktop.org/wiki/Software/systemd/
16661794
.. _`SymfonyCasts' message serializer tutorial`: https://symfonycasts.com/screencast/messenger/transport-serializer

0 commit comments

Comments
 (0)