@@ -476,23 +476,30 @@ Deploying to Production
476
476
477
477
On production, there are a few important things to think about:
478
478
479
- **Use Supervisor to keep your worker(s) running **
479
+ **Use a Process Manager like Supervisor or systemd to keep your worker(s) running **
480
480
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 >`.
482
483
483
484
**Don't Let Workers Run Forever **
484
485
Some services (like Doctrine's ``EntityManager ``) will consume more memory
485
486
over time. So, instead of allowing your worker to run forever, use a flag
486
487
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
488
489
are also other options like ``--memory-limit=128M `` and ``--time-limit=3600 ``.
489
490
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
+
490
497
**Restart Workers on Deploy **
491
498
Each time you deploy, you'll need to restart all your worker processes so
492
499
that they see the newly deployed code. To do this, run ``messenger:stop-workers ``
493
500
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 >`
496
503
cache internally - so make sure this is configured to use an adapter you like.
497
504
498
505
**Use the Same Cache Between Deploys **
@@ -655,11 +662,25 @@ times:
655
662
startsecs =0
656
663
autostart =true
657
664
autorestart =true
665
+ startretries =10
658
666
process_name =%(program_name)s_%(process_num)02d
659
667
660
668
Change the ``async `` argument to use the name of your transport (or transports)
661
669
and ``user `` to the Unix user on your server.
662
670
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
+
663
684
If you use the Redis Transport, note that each worker needs a unique consumer
664
685
name to avoid the same message being handled by multiple workers. One way to
665
686
achieve 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:
682
703
See the `Supervisor docs `_ for more details.
683
704
684
705
Graceful Shutdown
685
- ~~~~~~~~~~~~~~~~~
706
+ .................
686
707
687
708
If you install the `PCNTL `_ PHP extension in your project, workers will handle
688
709
the ``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:
698
719
[program:x]
699
720
stopwaitsecs =20
700
721
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
+
701
804
Stateless Worker
702
805
~~~~~~~~~~~~~~~~
703
806
@@ -2026,6 +2129,8 @@ middleware and *only* include your own:
2026
2129
If a middleware service is abstract, a different instance of the service will
2027
2130
be created per bus.
2028
2131
2132
+ .. _middleware-doctrine :
2133
+
2029
2134
Middleware for Doctrine
2030
2135
~~~~~~~~~~~~~~~~~~~~~~~
2031
2136
@@ -2209,6 +2314,7 @@ Learn more
2209
2314
.. _`streams` : https://redis.io/topics/streams-intro
2210
2315
.. _`Supervisor docs` : http://supervisord.org/
2211
2316
.. _`PCNTL` : https://www.php.net/manual/book.pcntl.php
2317
+ .. _`systemd docs` : https://www.freedesktop.org/wiki/Software/systemd/
2212
2318
.. _`SymfonyCasts' message serializer tutorial` : https://symfonycasts.com/screencast/messenger/transport-serializer
2213
2319
.. _`Long polling` : https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html
2214
2320
.. _`Visibility Timeout` : https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html
0 commit comments