@@ -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,132 @@ 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
+ [Journal]
708
+ Storage =persistent
709
+
710
+ [Install]
711
+ WantedBy =default.target
712
+
713
+ Now, tell systemd to enable and start one worker:
714
+
715
+ .. code-block :: terminal
716
+
717
+ $ systemctl --user enable [email protected]
718
+
719
+ $ systemctl --user start [email protected]
720
+
721
+ Then enable and start another 19:
722
+
723
+ .. code-block :: terminal
724
+
725
+ $ systemctl --user enable messenger-worker@{2..20}.service
726
+
727
+ $ systemctl --user start messenger-worker@{2..20}.service
728
+
729
+ If you would change your service config file, reload the daemon:
730
+
731
+ .. code-block :: terminal
732
+
733
+ $ systemctl --user daemon-reload
734
+
735
+ Restart all your consumers:
736
+
737
+ .. code-block :: terminal
738
+
739
+ $ systemctl --user restart messenger-consume@*.service
740
+
741
+ The systemd user instance is only started after the first login of the
742
+ particular user. We want to start our workers on system boot instead. Enable
743
+ lingering on the user to activate that behavior:
744
+
745
+ .. code-block :: terminal
746
+
747
+ $ loginctl enable-linger <your-username>
748
+
749
+ Logs are managed by journald and can be worked with using the journalctl
750
+ command, but you do need elevated privileges for that, or add your user to the
751
+ systemd-journal group:
752
+
753
+ .. code-block :: terminal
754
+
755
+ $ sudo usermod -a -G systemd-journal <your-username>
756
+
757
+ Now you can watch your service logs as your user, for example tail and follow
758
+ the logs of
[email protected] , or tail and follow all logs for your
759
+ user ID:
760
+
761
+ .. code-block :: terminal
762
+
763
+ $ journalctl -f --user-unit [email protected]
764
+
765
+ $ journalctl -f _UID=$UID
766
+
767
+ See the `systemd docs `_ for more details.
768
+
636
769
.. _messenger-retries-failures :
637
770
638
771
Retries & Failures
@@ -1541,6 +1674,8 @@ middleware and *only* include your own:
1541
1674
If a middleware service is abstract, a different instance of the service will
1542
1675
be created per bus.
1543
1676
1677
+ .. _middleware-doctrine :
1678
+
1544
1679
Middleware for Doctrine
1545
1680
~~~~~~~~~~~~~~~~~~~~~~~
1546
1681
@@ -1663,4 +1798,5 @@ Learn more
1663
1798
.. _`Enqueue's transport` : https://github.com/sroze/messenger-enqueue-transport
1664
1799
.. _`streams` : https://redis.io/topics/streams-intro
1665
1800
.. _`Supervisor docs` : http://supervisord.org/
1801
+ .. _`systemd docs` : https://www.freedesktop.org/wiki/Software/systemd/
1666
1802
.. _`SymfonyCasts' message serializer tutorial` : https://symfonycasts.com/screencast/messenger/transport-serializer
0 commit comments