@@ -486,23 +486,30 @@ Deploying to Production
486
486
487
487
On production, there are a few important things to think about:
488
488
489
- **Use Supervisor to keep your worker(s) running **
489
+ **Use a Process Manager like Supervisor or systemd to keep your worker(s) running **
490
490
You'll want one or more "workers" running at all times. To do that, use a
491
- process control system like :ref: `Supervisor <messenger-supervisor >`.
491
+ process control system like :ref: `Supervisor <messenger-supervisor >`
492
+ or :ref: `systemd <messenger-systemd >`.
492
493
493
494
**Don't Let Workers Run Forever **
494
495
Some services (like Doctrine's ``EntityManager ``) will consume more memory
495
496
over time. So, instead of allowing your worker to run forever, use a flag
496
497
like ``messenger:consume --limit=10 `` to tell your worker to only handle 10
497
- messages before exiting (then Supervisor will create a new process). There
498
+ messages before exiting (then the process manager will create a new process). There
498
499
are also other options like ``--memory-limit=128M `` and ``--time-limit=3600 ``.
499
500
501
+ **Stopping Workers That Encounter Errors **
502
+ If a worker dependency like your database server is down, or timeout is reached,
503
+ you can try to add :ref: `reconnect logic <middleware-doctrine >`, or just quit
504
+ the worker if it receives too many errors with the ``--failure-limit `` option of
505
+ the ``messenger:consume `` command.
506
+
500
507
**Restart Workers on Deploy **
501
508
Each time you deploy, you'll need to restart all your worker processes so
502
509
that they see the newly deployed code. To do this, run ``messenger:stop-workers ``
503
510
on deployment. This will signal to each worker that it should finish the message
504
- it's currently handling and should shut down gracefully. Then, Supervisor will create
505
- new worker processes. The command uses the :ref: `app <cache-configuration-with-frameworkbundle >`
511
+ it's currently handling and should shut down gracefully. Then, the process manager
512
+ will create new worker processes. The command uses the :ref: `app <cache-configuration-with-frameworkbundle >`
506
513
cache internally - so make sure this is configured to use an adapter you like.
507
514
508
515
**Use the Same Cache Between Deploys **
@@ -669,11 +676,25 @@ times:
669
676
startsecs =0
670
677
autostart =true
671
678
autorestart =true
679
+ startretries =10
672
680
process_name =%(program_name)s_%(process_num)02d
673
681
674
682
Change the ``async `` argument to use the name of your transport (or transports)
675
683
and ``user `` to the Unix user on your server.
676
684
685
+ .. caution ::
686
+
687
+ During a deployment, something might be unavailable (e.g. the
688
+ database) causing the consumer to fail to start. In this situation,
689
+ Supervisor will try ``startretries `` number of times to restart the
690
+ command. Make sure to change this setting to avoid getting the command
691
+ in a FATAL state, which will never restart again.
692
+
693
+ Each restart, Supervisor increases the delay by 1 second. For instance, if
694
+ the value is ``10 ``, it will wait 1 sec, 2 sec, 3 sec, etc. This gives the
695
+ service a total of 55 seconds to become available again. Increase the
696
+ ``startretries `` setting to cover the maximum expected downtime.
697
+
677
698
If you use the Redis Transport, note that each worker needs a unique consumer
678
699
name to avoid the same message being handled by multiple workers. One way to
679
700
achieve this is to set an environment variable in the Supervisor configuration
@@ -696,7 +717,7 @@ Next, tell Supervisor to read your config and start your workers:
696
717
See the `Supervisor docs `_ for more details.
697
718
698
719
Graceful Shutdown
699
- ~~~~~~~~~~~~~~~~~
720
+ .................
700
721
701
722
If you install the `PCNTL `_ PHP extension in your project, workers will handle
702
723
the ``SIGTERM `` POSIX signal to finish processing their current message before
@@ -712,6 +733,88 @@ of the desired grace period in seconds) in order to perform a graceful shutdown:
712
733
[program:x]
713
734
stopwaitsecs =20
714
735
736
+ .. _messenger-systemd :
737
+
738
+ Systemd Configuration
739
+ ~~~~~~~~~~~~~~~~~~~~~
740
+
741
+ While Supervisor is a great tool, it has the disadvantage that you need system
742
+ access to run it. Systemd has become the standard on most Linux distributions,
743
+ and has a good alternative called *user services *.
744
+
745
+ Systemd user service configuration files typically live in a ``~/.config/systemd/user ``
746
+ directory. For example, you can create a new ``messenger-worker.service `` file. Or a
747
+ ``
[email protected] `` file if you want more instances running at the same time:
748
+
749
+ .. code-block :: ini
750
+
751
+ [Unit]
752
+ Description =Symfony messenger-consume %i
753
+
754
+ [Service]
755
+ ExecStart =php /path/to/your/app/bin/console messenger:consume async --time-limit =3600
756
+ Restart =always
757
+ RestartSec =30
758
+
759
+ [Install]
760
+ WantedBy =default.target
761
+
762
+ Now, tell systemd to enable and start one worker:
763
+
764
+ .. code-block :: terminal
765
+
766
+ $ systemctl --user enable [email protected]
767
+ $ systemctl --user start [email protected]
768
+
769
+ # to enable and start 20 workers
770
+ $ systemctl --user enable messenger-worker@{1..20}.service
771
+ $ systemctl --user start messenger-worker@{1..20}.service
772
+
773
+ If you change your service config file, you need to reload the daemon:
774
+
775
+ .. code-block :: terminal
776
+
777
+ $ systemctl --user daemon-reload
778
+
779
+ To restart all your consumers:
780
+
781
+ .. code-block :: terminal
782
+
783
+ $ systemctl --user restart messenger-consume@*.service
784
+
785
+ The systemd user instance is only started after the first login of the
786
+ particular user. Consumer often need to start on system boot instead.
787
+ Enable lingering on the user to activate that behavior:
788
+
789
+ .. code-block :: terminal
790
+
791
+ $ loginctl enable-linger <your-username>
792
+
793
+ Logs are managed by journald and can be worked with using the journalctl
794
+ command:
795
+
796
+ .. code-block :: terminal
797
+
798
+ # follow logs of consumer nr 11
799
+ $ journalctl -f --user-unit [email protected]
800
+
801
+ # follow logs of all consumers
802
+ $ journalctl -f --user-unit messenger-consume@*
803
+
804
+ # follow all logs from your user services
805
+ $ journalctl -f _UID=$UID
806
+
807
+ See the `systemd docs `_ for more details.
808
+
809
+ .. note ::
810
+
811
+ You either need elevated privileges for the ``journalctl `` command, or add
812
+ your user to the systemd-journal group:
813
+
814
+ .. code-block :: terminal
815
+
816
+ $ sudo usermod -a -G systemd-journal <your-username>
817
+
715
818
Stateless Worker
716
819
~~~~~~~~~~~~~~~~
717
820
@@ -2190,6 +2293,8 @@ middleware and *only* include your own:
2190
2293
If a middleware service is abstract, a different instance of the service will
2191
2294
be created per bus.
2192
2295
2296
+ .. _middleware-doctrine :
2297
+
2193
2298
Middleware for Doctrine
2194
2299
~~~~~~~~~~~~~~~~~~~~~~~
2195
2300
@@ -2377,6 +2482,7 @@ Learn more
2377
2482
.. _`streams` : https://redis.io/topics/streams-intro
2378
2483
.. _`Supervisor docs` : http://supervisord.org/
2379
2484
.. _`PCNTL` : https://www.php.net/manual/book.pcntl.php
2485
+ .. _`systemd docs` : https://www.freedesktop.org/wiki/Software/systemd/
2380
2486
.. _`SymfonyCasts' message serializer tutorial` : https://symfonycasts.com/screencast/messenger/transport-serializer
2381
2487
.. _`Long polling` : https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html
2382
2488
.. _`Visibility Timeout` : https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html
0 commit comments