@@ -462,22 +462,29 @@ Deploying to Production
462
462
463
463
On production, there are a few important things to think about:
464
464
465
- **Use Supervisor to keep your worker(s) running **
465
+ **Use a process manager like Supervisor or systemd to keep your worker(s) running **
466
466
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 >`.
468
469
469
470
**Don't Let Workers Run Forever **
470
471
Some services (like Doctrine's EntityManager) will consume more memory
471
472
over time. So, instead of allowing your worker to run forever, use a flag
472
473
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
474
475
are also other options like ``--memory-limit=128M `` and ``--time-limit=3600 ``.
475
476
477
+ **Stopping Workers That Encounter Errors **
478
+ If a worker dependency like your database server is down, or timeout is reached,
479
+ you can try to add :ref: `reconnect logic <middleware-doctrine >`, or just quit
480
+ the worker if it receives too many errors with the ``--failure-limit `` option of
481
+ the ``messenger:consume `` command.
482
+
476
483
**Restart Workers on Deploy **
477
484
Each time you deploy, you'll need to restart all your worker processes so
478
485
that they see the newly deployed code. To do this, run ``messenger:stop-workers ``
479
486
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
487
+ it's currently handling and shut down gracefully. Then, the process manager will create
481
488
new worker processes. The command uses the :ref: `app <cache-configuration-with-frameworkbundle >`
482
489
cache internally - so make sure this is configured to use an adapter you like.
483
490
@@ -633,6 +640,131 @@ config and start your workers:
633
640
634
641
See the `Supervisor docs `_ for more details.
635
642
643
+ It is possible to end up in a situation where the supervisor job gets into a
644
+ FATAL (too many start retries) state when trying to restart when something is
645
+ not yet available. You can prevent this by wrapping the Symfony script with a
646
+ shell script and sleep when the script fails:
647
+
648
+ .. code-block :: bash
649
+
650
+ #! /usr/bin/env bash
651
+
652
+ # Supervisor sends TERM to services when stopped.
653
+ # This wrapper has to pass the signal to it's child.
654
+ # Note that we send TERM (graceful) instead of KILL (immediate).
655
+ _term () {
656
+ echo " [GOT TERM, SIGNALING CHILD]"
657
+ kill -TERM " $child " 2> /dev/null
658
+ exit 1
659
+ }
660
+
661
+ trap _term SIGTERM
662
+
663
+ # Execute console.php with whatever arguments were specified to this script
664
+ " $@ " &
665
+ child=$!
666
+ wait " $child "
667
+ rc=$?
668
+
669
+ # Delay to prevent supervisor from restarting too fast on failure
670
+ sleep 30
671
+
672
+ # Return with the exit code of the wrapped process
673
+ exit $rc
674
+
675
+ The supervisor job would then look like this:
676
+
677
+ .. code-block :: ini
678
+
679
+ ; /etc/supervisor/conf.d/messenger-worker.conf
680
+ [program:messenger-consume]
681
+ command =/path/to/your/app/bin/console_wrapper php /path/to/your/app/bin/console messenger:consume async --time-limit =3600"
682
+ ...
683
+
684
+ .. _messenger-systemd :
685
+
686
+ Systemd Configuration
687
+ ~~~~~~~~~~~~~~~~~~~~~
688
+
689
+ While Supervisor is a great tool, it has the disadvantage that you need system
690
+ access to run it. Systemd has become the standard on most Linux distributions,
691
+ and has a good alternative called user services.
692
+
693
+ Systemd user service configuration files typically live in a ``~/.config/systemd/user ``
694
+ directory. For example, you can create a new ``messenger-worker.service `` file. Or a
695
+ ``
[email protected] `` file if you want more instances running at the same time:
696
+
697
+ .. code-block :: ini
698
+
699
+ [Unit]
700
+ Description =Symfony messenger-consume %i
701
+
702
+ [Service]
703
+ ExecStart =php /path/to/your/app/bin/console messenger:consume async --time-limit =3600
704
+ Restart =always
705
+ RestartSec =30
706
+
707
+ [Install]
708
+ WantedBy =default.target
709
+
710
+ Now, tell systemd to enable and start one worker:
711
+
712
+ .. code-block :: terminal
713
+
714
+ $ systemctl --user enable [email protected]
715
+
716
+ $ systemctl --user start [email protected]
717
+
718
+ Then enable and start another 19:
719
+
720
+ .. code-block :: terminal
721
+
722
+ $ systemctl --user enable messenger-worker@{2..20}.service
723
+
724
+ $ systemctl --user start messenger-worker@{2..20}.service
725
+
726
+ If you would change your service config file, reload the daemon:
727
+
728
+ .. code-block :: terminal
729
+
730
+ $ systemctl --user daemon-reload
731
+
732
+ Restart all your consumers:
733
+
734
+ .. code-block :: terminal
735
+
736
+ $ systemctl --user restart messenger-consume@*.service
737
+
738
+ The systemd user instance is only started after the first login of the
739
+ particular user. We want to start our workers on system boot instead. Enable
740
+ lingering on the user to activate that behavior:
741
+
742
+ .. code-block :: terminal
743
+
744
+ $ loginctl enable-linger <your-username>
745
+
746
+ Logs are managed by journald and can be worked with using the journalctl
747
+ command, but you do need elevated privileges for that, or add your user to the
748
+ systemd-journal group:
749
+
750
+ .. code-block :: terminal
751
+
752
+ $ sudo usermod -a -G systemd-journal <your-username>
753
+
754
+ Now you can watch your service logs as your user, for example tail and follow
755
+ the logs of
[email protected] , all messenger-consume services, or
756
+ tail and follow all logs for your user ID:
757
+
758
+ .. code-block :: terminal
759
+
760
+ $ journalctl -f --user-unit [email protected]
761
+
762
+ $ journalctl -f --user-unit messenger-consume@*
763
+
764
+ $ journalctl -f _UID=$UID
765
+
766
+ See the `systemd docs `_ for more details.
767
+
636
768
.. _messenger-retries-failures :
637
769
638
770
Retries & Failures
@@ -1541,6 +1673,8 @@ middleware and *only* include your own:
1541
1673
If a middleware service is abstract, a different instance of the service will
1542
1674
be created per bus.
1543
1675
1676
+ .. _middleware-doctrine :
1677
+
1544
1678
Middleware for Doctrine
1545
1679
~~~~~~~~~~~~~~~~~~~~~~~
1546
1680
@@ -1663,4 +1797,5 @@ Learn more
1663
1797
.. _`Enqueue's transport` : https://github.com/sroze/messenger-enqueue-transport
1664
1798
.. _`streams` : https://redis.io/topics/streams-intro
1665
1799
.. _`Supervisor docs` : http://supervisord.org/
1800
+ .. _`systemd docs` : https://www.freedesktop.org/wiki/Software/systemd/
1666
1801
.. _`SymfonyCasts' message serializer tutorial` : https://symfonycasts.com/screencast/messenger/transport-serializer
0 commit comments