@@ -476,23 +476,30 @@ Deploying to Production
476476
477477On production, there are a few important things to think about:
478478
479- **Use Supervisor to keep your worker(s) running **
479+ **Use a Process Manager like Supervisor or systemd to keep your worker(s) running **
480480 You'll want one or more "workers" running at all times. To do that, use a
481- process control system like :ref: `Supervisor <messenger-supervisor >`.
481+ process control system like :ref: `Supervisor <messenger-supervisor >`
482+ or :ref: `systemd <messenger-systemd >`.
482483
483484**Don't Let Workers Run Forever **
484485 Some services (like Doctrine's ``EntityManager ``) will consume more memory
485486 over time. So, instead of allowing your worker to run forever, use a flag
486487 like ``messenger:consume --limit=10 `` to tell your worker to only handle 10
487- messages before exiting (then Supervisor will create a new process). There
488+ messages before exiting (then the process manager will create a new process). There
488489 are also other options like ``--memory-limit=128M `` and ``--time-limit=3600 ``.
489490
491+ **Stopping Workers That Encounter Errors **
492+ If a worker dependency like your database server is down, or timeout is reached,
493+ you can try to add :ref: `reconnect logic <middleware-doctrine >`, or just quit
494+ the worker if it receives too many errors with the ``--failure-limit `` option of
495+ the ``messenger:consume `` command.
496+
490497**Restart Workers on Deploy **
491498 Each time you deploy, you'll need to restart all your worker processes so
492499 that they see the newly deployed code. To do this, run ``messenger:stop-workers ``
493500 on deployment. This will signal to each worker that it should finish the message
494- it's currently handling and should shut down gracefully. Then, Supervisor will create
495- new worker processes. The command uses the :ref: `app <cache-configuration-with-frameworkbundle >`
501+ it's currently handling and should shut down gracefully. Then, the process manager
502+ will create new worker processes. The command uses the :ref: `app <cache-configuration-with-frameworkbundle >`
496503 cache internally - so make sure this is configured to use an adapter you like.
497504
498505**Use the Same Cache Between Deploys **
@@ -655,11 +662,25 @@ times:
655662 startsecs =0
656663 autostart =true
657664 autorestart =true
665+ startretries =10
658666 process_name =%(program_name)s_%(process_num)02d
659667
660668 Change the ``async `` argument to use the name of your transport (or transports)
661669and ``user `` to the Unix user on your server.
662670
671+ .. caution ::
672+
673+ During a deployment, something might be unavailable (e.g. the
674+ database) causing the consumer to fail to start. In this situation,
675+ Supervisor will try ``startretries `` number of times to restart the
676+ command. Make sure to change this setting to avoid getting the command
677+ in a FATAL state, which will never restart again.
678+
679+ Each restart, Supervisor increases the delay by 1 second. For instance, if
680+ the value is ``10 ``, it will wait 1 sec, 2 sec, 3 sec, etc. This gives the
681+ service a total of 55 seconds to become available again. Increase the
682+ ``startretries `` setting to cover the maximum expected downtime.
683+
663684If you use the Redis Transport, note that each worker needs a unique consumer
664685name to avoid the same message being handled by multiple workers. One way to
665686achieve this is to set an environment variable in the Supervisor configuration
@@ -682,7 +703,7 @@ Next, tell Supervisor to read your config and start your workers:
682703 See the `Supervisor docs `_ for more details.
683704
684705Graceful Shutdown
685- ~~~~~~~~~~~~~~~~~
706+ .................
686707
687708If you install the `PCNTL `_ PHP extension in your project, workers will handle
688709the ``SIGTERM `` POSIX signal to finish processing their current message before
@@ -698,6 +719,88 @@ of the desired grace period in seconds) in order to perform a graceful shutdown:
698719 [program:x]
699720 stopwaitsecs =20
700721
722+ .. _messenger-systemd :
723+
724+ Systemd Configuration
725+ ~~~~~~~~~~~~~~~~~~~~~
726+
727+ While Supervisor is a great tool, it has the disadvantage that you need system
728+ access to run it. Systemd has become the standard on most Linux distributions,
729+ and has a good alternative called *user services *.
730+
731+ Systemd user service configuration files typically live in a ``~/.config/systemd/user ``
732+ directory. For example, you can create a new ``messenger-worker.service `` file. Or a
733+ ``messenger-worker@.service `` file if you want more instances running at the same time:
734+
735+ .. code-block :: ini
736+
737+ [Unit]
738+ Description =Symfony messenger-consume %i
739+
740+ [Service]
741+ ExecStart =php /path/to/your/app/bin/console messenger:consume async --time-limit =3600
742+ Restart =always
743+ RestartSec =30
744+
745+ [Install]
746+ WantedBy =default.target
747+
748+ Now, tell systemd to enable and start one worker:
749+
750+ .. code-block :: terminal
751+
752+ $ systemctl --user enable messenger-worker@1.service
753+ $ systemctl --user start messenger-worker@1.service
754+
755+ # to enable and start 20 workers
756+ $ systemctl --user enable messenger-worker@{1..20}.service
757+ $ systemctl --user start messenger-worker@{1..20}.service
758+
759+ If you change your service config file, you need to reload the daemon:
760+
761+ .. code-block :: terminal
762+
763+ $ systemctl --user daemon-reload
764+
765+ To restart all your consumers:
766+
767+ .. code-block :: terminal
768+
769+ $ systemctl --user restart messenger-consume@*.service
770+
771+ The systemd user instance is only started after the first login of the
772+ particular user. Consumer often need to start on system boot instead.
773+ Enable lingering on the user to activate that behavior:
774+
775+ .. code-block :: terminal
776+
777+ $ loginctl enable-linger <your-username>
778+
779+ Logs are managed by journald and can be worked with using the journalctl
780+ command:
781+
782+ .. code-block :: terminal
783+
784+ # follow logs of consumer nr 11
785+ $ journalctl -f --user-unit messenger-consume@11.service
786+
787+ # follow logs of all consumers
788+ $ journalctl -f --user-unit messenger-consume@*
789+
790+ # follow all logs from your user services
791+ $ journalctl -f _UID=$UID
792+
793+ See the `systemd docs `_ for more details.
794+
795+ .. note ::
796+
797+ You either need elevated privileges for the ``journalctl `` command, or add
798+ your user to the systemd-journal group:
799+
800+ .. code-block :: terminal
801+
802+ $ sudo usermod -a -G systemd-journal <your-username>
803+
701804 Stateless Worker
702805~~~~~~~~~~~~~~~~
703806
@@ -2026,6 +2129,8 @@ middleware and *only* include your own:
20262129 If a middleware service is abstract, a different instance of the service will
20272130 be created per bus.
20282131
2132+ .. _middleware-doctrine :
2133+
20292134Middleware for Doctrine
20302135~~~~~~~~~~~~~~~~~~~~~~~
20312136
@@ -2209,6 +2314,7 @@ Learn more
22092314.. _`streams` : https://redis.io/topics/streams-intro
22102315.. _`Supervisor docs` : http://supervisord.org/
22112316.. _`PCNTL` : https://www.php.net/manual/book.pcntl.php
2317+ .. _`systemd docs` : https://www.freedesktop.org/wiki/Software/systemd/
22122318.. _`SymfonyCasts' message serializer tutorial` : https://symfonycasts.com/screencast/messenger/transport-serializer
22132319.. _`Long polling` : https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html
22142320.. _`Visibility Timeout` : https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html
0 commit comments