Shopware 6 | Messaging mit RabbitMQ

Wer mit Shopware 6 arbeitet ist sicher schon mal über die Message Queue gestolpert. Diese sorgt dafür das Aufgaben die „warten können“ in einer Tabelle Form gespeichert werden und später abgearbeitet werden, aber mehr dazu im Beitrag.

Message Queuing

In der Informatik sind Message Queues und Mailboxen Kommunikationsprotokolle, die für die Interprozesskommunikation (IPC) oder für die Inter-Thread-Kommunikation innerhalb desselben Prozesses verwendet werden. Sie verwenden eine Warteschlange für die Nachricht (Messaging) und beinhalten Managementfunktionen zur Weitergabe der Kontrolle oder des Inhalts (Quelle: Wikipedia)

Symfony Messenger als Basis

Die Basis für die Message Queue von Shopware bildet die Symfony Messenger Komponente (finden könnt Ihr die Version in der composer.lock:

"symfony/messenger": "~4.4.13"

Da Shopware auf Symfony 4.4.* basiert werden die Komponenten in der Regel auch auf dieser Version laufen.

In Ihrer Doku erfahrt Ihr sicher noch das ein oder andere, was die Integration und Production angeht.

SaaS oder Selfhosted?

Saas

Einige Anbieter sahen vernünftig aus und liefen ganz gut, wenn Ihr nur einen Node braucht dann nehmt die günstige Variante von Stackhero – braucht Ihr hohe Verfügbarkeit und mehrere Node dann schaut euch mal CloudAMQP an.

wir fahren aktuell mit einer selbst gehosteten Lösung auf Digital Ocean ganz gut. Hier eine kurze Anleitung wie Ihr es unter Ubuntu 20.04 (Focal Fossa) installiert und startet.

Selfhosted

RabbitMQ basiert auf der Sprache Erlang („Erlang is a programming language used to build massively scalable soft real-time systems with requirements on high availability“ Quelle: Erlang) und muss vorab installiert sein.

Erl installieren

wget -O- https://packages.erlang-solutions.com/ubuntu/erlang_solutions.asc | sudo apt-key add -

echo "deb https://packages.erlang-solutions.com/ubuntu focal contrib" | sudo tee /etc/apt/sources.list.d/rabbitmq.list

sudo apt update
sudo apt install erlang

mit erl tested Ihr ob alles funktioniert.

Erlang/OTP 23 [erts-11.1.7] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1]

Eshell V11.1.7  (abort with ^G)

RabbitMQ installieren

sudo apt update && sudo apt install wget -y
sudo apt install apt-transport-https -y

wget -O- https://dl.bintray.com/rabbitmq/Keys/rabbitmq-release-signing-key.asc | sudo apt-key add -
wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add -


echo "deb https://dl.bintray.com/rabbitmq-erlang/debian focal erlang-22.x" | sudo tee /etc/apt/sources.list.d/rabbitmq.list

sudo apt update
sudo apt install rabbitmq-server

Start beim booten könnt Ihr so erzielen:

systemctl is-enabled rabbitmq-server.service 

prüft ob es aktiv ist

sudo systemctl enable rabbitmq-server

aktiviert es beim Start.

Das Dashboard kann ich euch am Anfang ans Herz legen:

sudo rabbitmq-plugins enable rabbitmq_management

UFW sollte übrigens schon aktiviert sein, bei so zielmich jedem Server, daher fügt IHr die Regel noch hinzu:

sudo ufw allow proto tcp from any to any port 5672,15672

um den Traffic zu erlauben für RMQ.

User erstellen
rabbitmqctl add_user admin DEINPASSWORT
rabbitmqctl set_user_tags admin administrator

PS: Im Standard habt ihr einen User guest mit PW guest. Der kann aber nur über localhost connecten.

VHost erstellen und zuweisen

„RabbitMQ is multi-tenant system: connections, exchanges, queues, bindings, user permissions, policies and some other things belong to virtual hosts, logical groups of entities.“ (Quelle: RabbitMQ)

Wir haben ein Multishop Cluster (mehrere Shops in einem Cluster in unterschiedlichen Docroots und benötigen daher verschiedene VHosts). Habt Ihr nur einen Shop, benötigt Ihr diesen Schritt nicht und könnt gleich auf / gehen.

rabbitmqctl list_vhosts
(sollte nur einen ausgeben und zwar /)

rabbitmqctl add_vhost /SHOP
erstellt den VHost fischen

rabbitmqctl add_user BENUTZER PASSWORT
erstelle wie oben einen User

rabbitmqctl set_permissions -p /SHOP BENUTZER ".*" ".*" ".*"
erstelle Rechte für User auf dem VHost

Das war es „schon“ – sieht kompliziert ist aus, ist aber mit Erfahrung in 10 min gemacht.

Shopware 6 konfigurieren

Shopware hat hier bereits etwas in Ihrer Doku geschrieben.

Erstellen einer enqueue.yaml Datei im oben stehenden Pfad, ich lege die AMQP Url nicht in der enqueue.yaml Datei ab, da ich diese Daten nicht mit ins Repository pushen möchte.

# config/packages/enqueue.yaml
enqueue:
    amqp:
        transport: '%env(AMQP_URL)%'
        client: ~
# .env
AMQP_URL="amqp://guest:guest@rabbitmq:5672/%2FVIRTUAL_HOST?connection_timeout=50&heartbeat=0"

bei guest:guest tragt Ihr entsprechend eure eben angelegten Daten ein und rabbitmq tauscht Ihr mit eurere IP oder Domain aus. Euren VHost müsst Ihr unbedingt so angeben wie oben, sonst wird dieser nicht gefunden (der mit aus URL encoded und nicht ist etwas strange mMn)

Erstellen einer framework.yaml Datei im oben stehenden Pfad, falls Ihr nicht schon eine habt für Redis o.Ä.

# config/packages/framework.yaml
framework:
    messenger:
        transports:
            default: enqueue://amqp

In der Doku von Shopware steht das man eine eigene Queue anlegen soll, die Parameter Übergabe hat bei mir allerdings nicht geklappt, daher arbeite ich mit dem default Namen „messages“ und lege diese in meinem neuen VHost an.

Queue in RabbitMQ erstellen

Danach benötigt Ihr noch einen Exchange:

Und danach bindet Ihr diesen noch zu eurer Queue:

Bind exchange to queue

Danach sollte alles passen und Ihr könnt testen. Denkt daran den Cache zu leeren und etwas zu triggern was die queue füllt:

bin/console cache:clear
bin/console dal:refresh:index --use-queue -v

Danach sollte eure Message Rates im Bereich publish hochgehen.

RabbitMQ Übersicht

Wenn Ihr jetzt noch eure worker startet, sollten die Messages entsprechend auf euren Servern konsumiert werden.

screen bin/console messenger:consume-messages default --memory-limit=512M --time-limit=180
# Startet einen Worker mit entweder 512MB Limit oder einem Zeitlimit von 180 Sekunden. Ich habe noch keine schönen Production Lösung gefunden um beim z.B. dal:refresh:index schnell 15-20 worker zu starten.

Aktuell haben wir dafür einen crontab

*/2 * * * * cd /home/www-data/shops/******/ && bin/console messenger:consume-messages default --memory-limit=512M --time-limit=180
Hier mal ein Vergleich wie schnell sich die queue entsprechend abarbeitet wenn X worker gestartet wurden

Die Load auf dem Server hält sich in Grenzen:

Etwas strange ist das Verhalten am Ende der Verarbeitung, hier scheinen einige hundert bis tausend Messages nach weniger Sekunden verarbeitet oder ignoriert zu werden:

Fazit

Das Setup ist am Ende doch etwas aufwändiger geworden als ich dachte, da man sich erstmal in die Materie einlesen muss und die Begrifflichkeiten lernen muss. Allerdings führt hier bei größeren Setups kein Weg dran vorbei, die die DB locks doch zunehmen werden und wenn das ERP System 5000 Produktpreise per queue pusht, kann das teilweise zu Fehlern/Abbrüchen führen (zmd. wenn dies Standardmäßig das use-queue flag nutzt)

Ich würde mir wünschen, dass Shopware noch etwas mehr Infos auf Ihre Doku Seite packt. Die angegebene Konfiguration hat bei mir zmd. nicht funktioniert. Ich weiß, dass diese Infos auch selbst erarbeitet werden können, daher nutzt Shopware ja Standardkomponenten von Symfony. Sicher würde es aber den Einstieg in die Messenger Komponente vereinfachen. Alles in allem bin ich aber sehr glücklich darüber das Shopware bereits einige Aufgaben vorgefertigt in die queue packt. Eine Liste welche dies sind, gibt es später.

Nachtrag 31.05.2021

Für das abarbeiten von „delayed messages“ benötigt Ihr noch das Plugin https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases – wenn das nicht installiert ist, kann das dazu führen das eure Message queue hängen bleibt.

Bei mir musste die Datei in den Ordner

/usr/lib/rabbitmq/lib/rabbitmq_server-3.8.16/plugins

cp ~/rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez

und danach einfach aktivieren mit

rabbitmq-plugins enable rabbitmq_delayed_message_exchange

Eine Antwort auf „Shopware 6 | Messaging mit RabbitMQ“

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert