Whatsapp Telegram Telegram Call Anrufen

Die Messenger-Komponente in Symfony


Die Messenger-Komponente von Symfony ermöglicht es Entwicklern, Nachrichten zwischen verschiedenen Teilen einer Anwendung zu senden und zu empfangen, sowohl synchron als auch asynchron. Sie unterstützt die Verwendung von Nachrichtenwarteschlangen und bietet Integrationen mit Message Brokern wie RabbitMQ und Redis.

In diesem Artikel werden wir die folgenden Themen ausführlich behandeln:

  1. Einführung in die Messenger-Komponente
  2. Senden und Verarbeiten von Nachrichten
  3. Asynchrone Verarbeitung und Nachrichtenwarteschlangen
  4. Integration mit Message Brokern (RabbitMQ, Redis)

1. Einführung in die Messenger-Komponente

1.1 Was ist die Messenger-Komponente?

Die Messenger-Komponente ist ein Werkzeug zur Implementierung von Nachrichtenverarbeitung in Symfony-Anwendungen. Sie ermöglicht das Senden von Nachrichten (oder Befehlen) und die Verarbeitung dieser Nachrichten durch Handler. Dies fördert die Trennung von Anliegen und erleichtert die asynchrone Verarbeitung von Aufgaben.

1.2 Vorteile der Verwendung der Messenger-Komponente

  • Lose Kopplung: Komponenten kommunizieren über Nachrichten statt direkte Aufrufe.
  • Asynchrone Verarbeitung: Aufgaben können asynchron in Hintergrundprozessen ausgeführt werden.
  • Skalierbarkeit: Durch die Verwendung von Warteschlangen können Anwendungen besser skaliert werden.
  • Fehlerbehandlung: Verbesserte Kontrolle über die Fehlerbehandlung und Wiederholungsmechanismen.

1.3 Installation der Messenger-Komponente

Falls nicht bereits installiert, können Sie die Messenger-Komponente mit Composer hinzufügen:

composer require symfony/messenger

2. Senden und Verarbeiten von Nachrichten

2.1 Grundlagen des Nachrichtenversands

Eine Nachricht ist ein einfaches PHP-Objekt, das Daten enthält. Ein Handler ist eine Klasse, die die Nachricht empfängt und verarbeitet.

2.2 Erstellen einer Nachricht

Beispiel:

Angenommen, wir möchten eine E-Mail versenden, wenn ein Benutzer sich registriert.

// src/Message/SendWelcomeEmail.php

namespace App\Message;

class SendWelcomeEmail
{
    private int $userId;

    public function __construct(int $userId)
    {
        $this->userId = $userId;
    }

    public function getUserId(): int
    {
        return $this->userId;
    }
}

2.3 Erstellen eines Handlers

Der Handler verarbeitet die Nachricht und führt die gewünschte Aktion aus.

// src/MessageHandler/SendWelcomeEmailHandler.php

namespace App\MessageHandler;

use App\Message\SendWelcomeEmail;
use App\Repository\UserRepository;
use App\Service\MailerService;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

class SendWelcomeEmailHandler implements MessageHandlerInterface
{
    private UserRepository $userRepository;
    private MailerService $mailer;

    public function __construct(UserRepository $userRepository, MailerService $mailer)
    {
        $this->userRepository = $userRepository;
        $this->mailer = $mailer;
    }

    public function __invoke(SendWelcomeEmail $message)
    {
        $user = $this->userRepository->find($message->getUserId());

        if (!$user) {
            // Benutzer nicht gefunden, Fehlerbehandlung
            return;
        }

        // E-Mail senden
        $this->mailer->sendWelcomeEmail($user);
    }
}

2.4 Senden der Nachricht

In Ihrem Controller oder Service können Sie die Nachricht senden.

// src/Controller/RegistrationController.php

namespace App\Controller;

use App\Entity\User;
use App\Form\RegistrationFormType;
use App\Message\SendWelcomeEmail;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Routing\Annotation\Route;

class RegistrationController extends AbstractController
{
    #[Route('/register', name: 'user_register')]
    public function register(
        Request $request,
        EntityManagerInterface $entityManager,
        MessageBusInterface $messageBus
    ) {
        $user = new User();
        $form = $this->createForm(RegistrationFormType::class, $user);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            // Benutzer speichern
            $entityManager->persist($user);
            $entityManager->flush();

            // Nachricht senden
            $messageBus->dispatch(new SendWelcomeEmail($user->getId()));

            // Weiterleitung oder Antwort
            return $this->redirectToRoute('homepage');
        }

        return $this->render('registration/register.html.twig', [
            'registrationForm' => $form->createView(),
        ]);
    }
}

2.5 Wichtige Komponenten

  • MessageBusInterface: Schnittstelle zum Senden von Nachrichten.
  • Message: Die Nachricht, die gesendet wird.
  • MessageHandlerInterface: Schnittstelle für den Handler, der die Nachricht verarbeitet.

3. Asynchrone Verarbeitung und Nachrichtenwarteschlangen

3.1 Warum asynchron verarbeiten?

Asynchrone Verarbeitung ermöglicht es, langwierige oder ressourcenintensive Aufgaben im Hintergrund auszuführen, ohne die Benutzererfahrung zu beeinträchtigen.

3.2 Konfiguration der asynchronen Verarbeitung

Schritt 1: Transport konfigurieren

In der Konfigurationsdatei config/packages/messenger.yaml können Sie den Transport konfigurieren.

# config/packages/messenger.yaml

framework:
    messenger:
        transports:
            async: 'doctrine://default' # Verwenden der Datenbank als Warteschlange
        default_bus: messenger.bus.default
        buses:
            messenger.bus.default: ~

        routing:
            'App\Message\SendWelcomeEmail': async

Erklärung:

  • transports.async: Definiert einen Transport namens async mit der Datenbank als Backend.
  • routing: Weist Nachrichten einem Transport zu. In diesem Fall wird SendWelcomeEmail an den async-Transport gesendet.

Schritt 2: Nachrichten asynchron senden

Der Code zum Senden der Nachricht bleibt unverändert. Durch die Konfiguration wird die Nachricht nun in die Warteschlange gelegt.

Schritt 3: Worker starten

Um die Nachrichten in der Warteschlange zu verarbeiten, müssen Sie einen Worker starten.

php bin/console messenger:consume async

Der Worker liest die Nachrichten aus der Warteschlange und führt die Handler aus.

3.3 Verwendung von Serialisierern

Da Nachrichten über einen Transport gesendet werden, müssen sie serialisiert werden. Symfony verwendet den Serializer automatisch. Stellen Sie sicher, dass Ihre Nachrichten serialisierbar sind.

3.4 Wiederholungsmechanismen und Fehlerbehandlung

Die Messenger-Komponente bietet Mechanismen, um fehlgeschlagene Nachrichten erneut zu versuchen oder in eine Fehlerwarteschlange zu verschieben.

Konfiguration von Wiederholungen:

# config/packages/messenger.yaml

framework:
    messenger:
        failure_transport: failed

        transports:
            async: 'doctrine://default'
            failed: 'doctrine://default'

        # ...

Verarbeiten fehlgeschlagener Nachrichten:

Sie können fehlgeschlagene Nachrichten mit folgendem Befehl erneut versuchen:

php bin/console messenger:retry failed

Oder die fehlgeschlagenen Nachrichten anzeigen:

php bin/console messenger:failed:show

4. Integration mit Message Brokern (RabbitMQ, Redis)

4.1 Warum Message Broker verwenden?

Message Broker wie RabbitMQ oder Redis bieten robuste und skalierbare Lösungen für die Nachrichtenverarbeitung. Sie ermöglichen eine bessere Performance und Zuverlässigkeit als die Verwendung der Datenbank als Warteschlange.

4.2 Integration mit RabbitMQ

Schritt 1: Installation von RabbitMQ

Installieren Sie RabbitMQ auf Ihrem System oder verwenden Sie einen gehosteten Dienst.

Schritt 2: Installation des AMQP-Pakets

Symfony benötigt das AMQP-Paket, um mit RabbitMQ zu kommunizieren.

composer require symfony/amqp-messenger

Schritt 3: Konfiguration des Transports

Passen Sie die messenger.yaml an:

# config/packages/messenger.yaml

framework:
    messenger:
        transports:
            async: 'amqp://guest:guest@localhost:5672/%2f/messages'
        # ...

Erklärung:

  • amqp://guest:guest@localhost:5672/%2f/messages: AMQP-Verbindungszeichenfolge zu RabbitMQ.

Schritt 4: RabbitMQ Exchange und Queue konfigurieren

Die Messenger-Komponente erstellt automatisch die erforderlichen Exchanges und Queues. Sie können jedoch auch benutzerdefinierte Einstellungen vornehmen.

Schritt 5: Worker starten

php bin/console messenger:consume async

4.3 Integration mit Redis

Schritt 1: Installation von Redis

Installieren Sie Redis auf Ihrem System oder verwenden Sie einen gehosteten Dienst.

Schritt 2: Installation des Redis-Pakets

composer require symfony/redis-messenger

Schritt 3: Konfiguration des Transports

# config/packages/messenger.yaml

framework:
    messenger:
        transports:
            async: 'redis://localhost:6379/messages'
        # ...

Erklärung:

  • redis://localhost:6379/messages: Verbindungszeichenfolge zu Redis.

4.4 Verwendung von Middleware

Middleware ermöglicht es, zusätzliche Verarbeitungsschritte vor oder nach dem Nachrichtentransport hinzuzufügen.

Beispiel: Logging Middleware

// src/Middleware/LoggingMiddleware.php

namespace App\Middleware;

use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Messenger\Middleware\StackInterface;

class LoggingMiddleware implements MiddlewareInterface
{
    private LoggerInterface $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function handle(Envelope $envelope, StackInterface $stack): Envelope
    {
        $this->logger->info('Verarbeitung der Nachricht: ' . get_class($envelope->getMessage()));

        return $stack->next()->handle($envelope, $stack);
    }
}

Registrieren der Middleware

# config/packages/messenger.yaml

framework:
    messenger:
        buses:
            messenger.bus.default:
                middleware:
                    - 'App\Middleware\LoggingMiddleware'
                    - 'dispatch_after_current_bus'

4.5 Mehrere Busse verwenden

Sie können mehrere Message Busse definieren, um verschiedene Arten von Nachrichten zu trennen.

Konfiguration:

# config/packages/messenger.yaml

framework:
    messenger:
        default_bus: command.bus

        buses:
            command.bus:
                default_middleware: true
            event.bus:
                default_middleware: true

Verwendung in Ihrem Code:

// Senden einer Nachricht über den command.bus
$commandBus->dispatch(new SomeCommand());

// Senden einer Nachricht über den event.bus
$eventBus->dispatch(new SomeEvent());

Zusammenfassung

  • Messenger-Komponente: Ermöglicht das Senden und Verarbeiten von Nachrichten in Symfony-Anwendungen.
  • Senden und Verarbeiten von Nachrichten: Nachrichten werden gesendet und von Handlern verarbeitet, was eine lose Kopplung ermöglicht.
  • Asynchrone Verarbeitung: Durch die Verwendung von Transporten und Workern können Nachrichten asynchron verarbeitet werden.
  • Integration mit Message Brokern: Durch die Verwendung von RabbitMQ oder Redis können Sie skalierbare und robuste Nachrichtenverarbeitung implementieren.
  • Erweiterbarkeit: Middleware und mehrere Busse ermöglichen die Anpassung und Erweiterung der Nachrichtenverarbeitung.

Weiterführende Ressourcen

The Messenger Component 

Messenger: Sync & Queued Message Handling

Using RabbitMQ as a Message Broker

Redis Cache Adapter


CEO Image

Ali Ajjoub

info@ajjoub.com

Adresse 0049-15773651670

Adresse Jacob-winter-platz,1 01239 Dresden

Buchen Sie jetzt Ihren Termin für eine umfassende und individuelle Beratung.

Termin Buchen

Kontaktieren Sie uns

Lassen Sie uns K o n t a k t aufnehmen!