Message Queue mit Redis konfigurieren

Sofern mehrere Prozesse zur Abarbeitung von Nachrichten aus der Message Queue von Shopware 6 eingesetzt werden sollen, muss sichergestellt werden, dass identische Nachrichten nicht von denselben Consumern abgearbeitet werden. Hierzu ist die Verwendung einer Technologie notwendig, die das atomare Sperren von Nachrichten unterstützt. Hierfür eignen sich Redis oder RabbitMQ.


Voraussetzungen

  • Redis-Server
  • Shopware-Server

Vorbereitung in Shopware

Zunächst muss der Admin Worker deaktiviert werden, damit die Message Queue über einen Hintergrundprozess abgearbeitet werden kann. Mehr Informationen zum Deaktivieren des Admin Workers und der initialen Einrichtung über einen Supervisor-Prozess erfahren Sie hier: Shopware 6 Frontend Message Queue Worker deaktivieren.


Konfiguration der Shopware 6 Background Queue Worker

Die Konfiguration der Supervisor-Prozesse wird in folgenden Hilfecenter-Artikeln behandelt:



Konfiguration in Redis

Da Message-Queue-Jobs standardmäßig keine TTL wie in Redis besitzen, empfiehlt sich der Einsatz geeigneter Key-Eviction-Policies, deren Konfiguration im verlinkten Hilfecenter-Artikel beschrieben wird.


Wird die Message-Queue auf einem dedizierten Server betrieben, der ausschließlich diesem Zweck dient, kann problemlos die Standard-Policy noeviction verwendet werden.


Alternativ besteht die Möglichkeit, die Message-Queue gemeinsam mit dem App-Cache auf demselben Redis-Server zu betreiben. In diesem Fall sollte jedoch die Key-Eviction-Policy volatile-lru gewählt werden. Dadurch wird sichergestellt, dass bei Erreichen des maxmemory-Limits ausschließlich Cache-Einträge entfernt werden, da nur diese über eine TTL verfügen. Die Jobs der Message-Queue bleiben somit erhalten und werden nicht unbeabsichtigt gelöscht.



Konfiguration in Shopware

Erstellen Sie eine neue Konfigurationsdatei unter dem Pfad: config/packages/messenger.yaml. Mithilfe dieser Konfigurationsdatei kann der Shopware Messenger Transport-Dienst konfiguriert werden.


Fügen Sie anschließend folgenden Inhalt in die Datei ein:

Bis Shopware 6.4

parameters:
  env(MESSENGER_CONSUMER_NAME): 'consumer'

framework:
  messenger:
    transports:
      default:
        dsn: "redis://%env(REDIS_HOST_MESSENGER)%:%env(REDIS_PORT_MESSENGER)%/messages/symfony/consumer-%env(MESSENGER_CONSUMER_NAME)%/?delete_after_ack=true&delete_after_reject=true&dbindex=%env(REDIS_DB_MESSENGER)%"


Ab Shopware 6.5

Bestehenden Shopware-Scheduler-Prozess stoppen

supervisorctl stop shopware-scheduled-tasks:shopware-scheduled-tasks_00


Zur Überprüfung, ob die Message Queue leer ist, kann der folgende Befehl ab Shopware 6.5 verwendet werden:

bin/console messenger:stats

Die Ausgabe sollte für jeden Transport einen 0 zeigen. Warten Sie in jedem Fall so lange, bis alle Jobs abgearbeitet sind.


Stoppen Sie anschließend alle Shopware Message-Queue Worker:


Der/Die Prozessname(n) können variieren und mit dem Befehl supervisorctl status eingesehen werden.

supervisorctl stop shopware-consumer:shopware-consumer_00


Anschließend kann die Message Queue seitens Shopware-Konfiguration auf Redis umgestellt werden:

# File: config/packages/messenger.yaml

parameters:
  env(MESSENGER_CONSUMER_NAME): 'consumer'

framework:
  messenger:
    transports:
      # shopware default transports
      async:
        dsn: "redis://%env(REDIS_HOST_MESSENGER)%:%env(REDIS_PORT_MESSENGER)%/messages_async?dbindex=%env(REDIS_DB_MESSENGER)%"
        options:
          consumer: "%env(MESSENGER_CONSUMER_NAME)%"
      failed:
        dsn: "redis://%env(REDIS_HOST_MESSENGER)%:%env(REDIS_PORT_MESSENGER)%/messages_failed?dbindex=%env(REDIS_DB_MESSENGER)%"
        options:
          consumer: "%env(MESSENGER_CONSUMER_NAME)%"
      low_priority:
        dsn: "redis://%env(REDIS_HOST_MESSENGER)%:%env(REDIS_PORT_MESSENGER)%/messages_low_priority?dbindex=%env(REDIS_DB_MESSENGER)%"
        options:
          consumer: "%env(MESSENGER_CONSUMER_NAME)%"


Sofern weitere (zukünftig neue) Transports über Redis abgearbeitet werden müssen, müssen diese ebenfalls wie oben in der messenger.yaml vorgegeben konfiguriert werden.


Beschreibung eines Transports

Die von uns verwendete Transport-DSN Variante für Redis ist wie folgt aufgebaut:

<transport-name>:
  dsn: "redis://<hostname>:<port>/<stream_key_name>?<options>"
  options:
    consumer: "custom-consumer-name-defined-in-environment-variable"    


Beispiel für async

async:
  dsn: "redis://%env(REDIS_HOST_MESSENGER)%:%env(REDIS_PORT_MESSENGER)%/messages_async?dbindex=%env(REDIS_DB_MESSENGER)%"
  options:
    consumer: "%env(MESSENGER_CONSUMER_NAME)%"


Variable Beschreibung
redis:// Definiert das Protokoll für Symfony Redis-Transport
%(REDIS_HOST_MESSENGER)% Hostname oder IP-Adresse zum Redis-Server Definition in der .env.local
%(REDIS_PORT_MESSENGER)% TCP-Port für Redis-Verbindungen (Standard: 6379) Definition in der .env.local
messages_async Redis Keyname (empfohlen, in dem Format nach dem Transport zu benennen)
%(MESSENGER_CONSUMER_NAME)% Eindeutiger Name des Consumers (pro Consumer)Definition in den Supervisor-Prozessen
dbindex Definiert den Redis Datenbank-Index
%(REDIS_DB_MESSENGER)% Redis-Datenbank für den Messenger Definition in der .env.local


Die Umgebungsvariable MESSENGER_CONSUMER_NAME muss durch den Supervisor-Service überschrieben werden, sodass auch die Ausführung von mehreren gleichzeitigen Consumern unterstützt werden kann.


Die hier verwendeten Variablen müssen anschließend in der Umgebungskonfiguration .env.local von Shopware hinzugefügt werden. Öffnen Sie hierzu die .env.local Datei im Shopware Root-Verzeichnis und ergänzen Sie folgenden Teil in der bestehenden Konfiguration:

# [...]

REDIS_HOST_MESSENGER=127.0.0.1
REDIS_PORT_MESSENGER=6379
REDIS_DB_MESSENGER=1


Prüfen Sie unbedingt vorher, ob die Redis Datenbank 1 frei ist und von keiner anderen Konfiguration verwendet wird.


Speichern Sie die Datei anschließend und leeren Sie den Shopware Cache über die Konsole:

bin/console cache:clear


Starten Sie alle Supervisor-Prozesse mit folgendem Befehl wieder:

supervisorctl start all


Anschließend wird die Message Queue über Redis ausgeführt.