window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = Fenster if (w.LeadBooster) { console.warn('LeadBooster existiert bereits') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Symfony: Microservices Kommunikation Teil I - The Codest
Der Codest
  • Über uns
  • Dienstleistungen
    • Software-Entwicklung
      • Frontend-Softwareentwicklung
      • Backend-Softwareentwicklung
    • Staff Augmentation
      • Frontend-Entwickler
      • Backend-Entwickler
      • Daten-Ingenieure
      • Cloud-Ingenieure
      • QS-Ingenieure
      • Andere
    • IT-Beratung
      • Prüfung und Beratung
  • Branchen
    • Fintech & Bankwesen
    • E-commerce
    • Adtech
    • Gesundheitstechnik
    • Herstellung
    • Logistik
    • Automobilindustrie
    • IOT
  • Wert für
    • CEO
    • CTO
    • Delivery Manager
  • Unser Team
  • Fallstudien
  • Gewusst wie
    • Blog
    • Begegnungen
    • Webinare
    • Ressourcen
Karriere Kontakt aufnehmen
  • Über uns
  • Dienstleistungen
    • Software-Entwicklung
      • Frontend-Softwareentwicklung
      • Backend-Softwareentwicklung
    • Staff Augmentation
      • Frontend-Entwickler
      • Backend-Entwickler
      • Daten-Ingenieure
      • Cloud-Ingenieure
      • QS-Ingenieure
      • Andere
    • IT-Beratung
      • Prüfung und Beratung
  • Wert für
    • CEO
    • CTO
    • Delivery Manager
  • Unser Team
  • Fallstudien
  • Gewusst wie
    • Blog
    • Begegnungen
    • Webinare
    • Ressourcen
Karriere Kontakt aufnehmen
Pfeil zurück ZURÜCK
2022-06-28
Software-Entwicklung

Symfony: Microservices Kommunikation Teil I

Der Codest

Sebastian Luczak

PHP Einheitsführer

Lesen Sie den ersten Teil unserer PHP-Serie, die sich mit der Kommunikation von Microservices im Symfony-Framework und dem beliebtesten Weg - AMQP-Kommunikation mit RabbitMQ - beschäftigt.

Die moderne Anwendungsarchitektur hat die Entwickler gezwungen, die Kommunikation zwischen den verschiedenen Komponenten von IT-Systemen anders zu betrachten. Früher war die Sache einfacher - die meisten Systeme wurden als monolithische Strukturen erstellt, die durch ein Netz von Geschäftslogikverbindungen miteinander verbunden waren. Die Aufrechterhaltung solcher Abhängigkeiten in einer PHP Projekt war eine große Herausforderung für PHP Entwicklerund die wachsende Beliebtheit von SaaS-Lösungen und die enorme Zunahme der Popularität von Wolke Services haben dazu geführt, dass wir heute immer mehr über Microservices und Anwendungsmodularität hören.

Wie können wir durch die Schaffung unabhängiger Microservices dafür sorgen, dass diese untereinander Informationen austauschen?

Dieser Artikel ist der erste in einer Reihe von Beiträgen über Microservices-Kommunikation in Symfony Framework und deckt den beliebtesten Weg ab - AMQP-Kommunikation mit RabbitMQ.

Ziel

Zwei unabhängige Anwendungen erstellen und die Kommunikation zwischen ihnen nur über den Nachrichtenbus erreichen.

Das Konzept

Wir haben zwei imaginäre, unabhängige Anwendungen:
* app1E-Mail- und SMS-Benachrichtigungen an die Mitarbeiter senden
* app2: Damit können Sie die Arbeit Ihrer Mitarbeiter verwalten und ihnen Aufgaben zuweisen.

Wir wollen ein modernes und einfaches System schaffen, bei dem die Zuweisung von Arbeit an einen Mitarbeiter in app2 sendet eine Benachrichtigung an den Kunden mit app1. Trotz des Anscheins ist dies sehr einfach!

Vorbereitung

Für die Zwecke dieses Artikels werden wir die neueste Symfony-Version (Version 6.1 zum Zeitpunkt der Erstellung dieses Artikels) und die neueste Version von PHP (8.1) verwenden. In wenigen, sehr einfachen Schritten werden wir eine funktionierende lokale Docker-Umgebung mit zwei Microservices erstellen. Alles, was Sie brauchen, ist:
* einen funktionierenden Computer,
* installiertes Docker + Docker Compose-Umgebung
* und eine lokal konfigurierte Symfony CLI und etwas freie Zeit.

Laufzeitumgebung

Wir werden die Fähigkeiten von Docker als Werkzeug zur Anwendungsvirtualisierung und Containerisierung nutzen. Beginnen wir mit der Erstellung eines Verzeichnisbaums, eines Rahmens für zwei Symfony-Anwendungenund beschreiben die Infrastruktur unserer Umgebungen mit Hilfe des docker-compose.yml Datei.

 cd ~
 mkdir microservices-in-symfony
 cd microservices-in-symfony
 symfony neu app1
 symfony neu app2
 touch docker-compose.yml

Wir haben zwei Verzeichnisse für zwei separate Symfony-Anwendungen erstellt und ein leeres docker-compose.yml Datei, um unsere Umgebung zu starten.

Fügen wir die folgenden Abschnitte zur docker-compose.yml file:

Version: '3.8'

Dienste:
app1:
containername: app1
bauen: app1/.
restart: bei Ausfall
Umgebungsdatei: app1/.env
Umgebung:
APPNAME: app1
tty: wahr
stdinopen: wahr

app2:
containername: app2
bauen: app2/.
restart: bei Fehlschlag
Umgebungsdatei: app2/.env
Umgebung:
APPNAME: app2
tty: wahr
stdinopen: wahr

rabbitmq:
containername: rabbitmq
Bild: rabbitmq:management
Ports:
- 15672:15672
- 5672:5672
Umgebung:
- RABBITMQDEFAULTUSER=Benutzer
- RABBITMQDEFAULT_PASS=Kennwort

Quelle Code direkt verfügbar: thecodest-co/microservices-in-symfony/blob/main/docker-compose.yml

Aber Moment, was ist hier passiert? Für diejenigen, die mit Docker nicht vertraut sind, mag die obige Konfigurationsdatei rätselhaft erscheinen, aber ihr Zweck ist sehr einfach. Mit Docker Compose bauen wir drei "Dienste" auf:

  • app1: ist ein Container für die erste Symfony-Anwendung
  • app2: ist der Container für die zweite Symfony-Anwendung
  • rabbitmq: das RabbitMQ-Anwendungsbild als Kommunikations-Middleware-Schicht

Für einen ordnungsgemäßen Betrieb benötigen wir noch Dockerdatei Dateien, die die Quelle für die Erstellung der Bilder sind. Lassen Sie uns diese also erstellen:

 touch app1/Dockerfile
 app2/Dockerfile berühren

Beide Dateien haben genau die gleiche Struktur und sehen wie folgt aus:

VON php:8.1

COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
COPY . /app/
WORKDIR /app/

ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/

RUN chmod +x /usr/local/bin/install-php-extensions && sync &&
install-php-erweiterungen amqp

RUN apt-get update
&& apt-get install -y libzip-dev wget --no-install-recommends
&& apt-get clean
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

Führen Sie docker-php-ext-install zip aus;

CMD bash -c "cd /app && composer install && php -a"

Quellcode direkt verfügbar: /thecodest-co/microservices-in-symfony/blob/main/app1/Dockerfile

Die obige Datei wird von Docker Compose verwendet, um einen Container aus einem PHP 8.1-Image mit Composer und der installierten AMQP-Erweiterung zu erstellen. Außerdem wird der PHP-Intepreter im Append-Modus ausgeführt, damit der Container im Hintergrund weiterläuft.

Ihr Verzeichnis- und Dateibaum sollte nun wie folgt aussehen:

 .
 ├── app1
 │ └── Dockerfile
 | (...) # Symfony App Struktur
 ├── app2
 │ └── Dockerfile
 | (...) # Symfony App Struktur
 └─── docker-compose.yml

Der erste Symfony-Microservice

Beginnen wir mit der app1 Verzeichnis und die erste Anwendung.
In unserem Beispiel handelt es sich um eine Anwendung, die Nachrichten aus der Warteschlange abhört und konsumiert, die von app2 wie in den Anforderungen beschrieben:

Zuweisung eines Jobs an einen Arbeiter in app2 sendet eine Benachrichtigung an den Kunden

Beginnen wir mit dem Hinzufügen der erforderlichen Bibliotheken. AMQP wird nativ unterstützt für die symfony/messenger Erweiterung. Wir werden zusätzlich installieren Monolog/Monolog um Systemprotokolle für eine einfachere Analyse des Anwendungsverhaltens aufzubewahren.

 cd app1/
 symfony composer req amqp ampq-messenger monolog

Nach der Installation wurde eine zusätzliche Datei unter config/packages/messenger.yaml. Es handelt sich um eine Konfigurationsdatei für die Symfony Messenger-Komponente und wir brauchen sie nicht. vollständige Konfiguration.
Ersetzen Sie sie durch die unten stehende YAML-Datei:

Rahmen:
messenger:
# Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
# failure_transport: failed

    Transporte:
        # https://symfony.com/doc/current/messenger.html#transport-configuration
        externe_nachrichten:
            dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
            Optionen:
                auto_setup: falsch
                Austausch:
                    name: nachrichten
                    type: direkt
                    default_publish_routing_key: from_external
                Warteschlangen:
                    nachrichten:
                        binding_keys: [from_external]

Quellcode direkt verfügbar: thecodest-co/microservices-in-symfony/blob/main/app1/config/packages/messenger.yaml

Symfony Messenger wird für synchrone und asynchrone Kommunikation in Symfony-Anwendungen verwendet. Er unterstützt eine Vielzahl von transportiertoder Quellen der Wahrheit der Transportschicht. In unserem Beispiel verwenden wir die AMQP-Erweiterung, die das RabbitMQ-Ereignis-Warteschlangensystem unterstützt.

Die obige Konfiguration definiert einen neuen Transport namens externe_Nachrichtendie sich auf den BOTEN_TRANSPORT_DSN Umgebungsvariable und definiert das direkte Abhören auf dem Nachrichten Kanal im Nachrichtenbus. Bearbeiten Sie zu diesem Zeitpunkt auch die app1/.env und fügen Sie die entsprechende Transportadresse hinzu.

"env

(...)
MESSENGERTRANSPORTDSN=amqp://user:password@rabbitmq:5672//messages
(...)
"
Nachdem wir das Anwendungsframework vorbereitet und die Bibliotheken konfiguriert haben, ist es an der Zeit, die Geschäftslogik zu implementieren. Wir wissen, dass unsere Anwendung auf die Zuweisung eines Auftrags an einen Arbeiter reagieren muss. Wir wissen auch, dass die Zuweisung eines Auftrags imapp2system den Status des Auftrags ändert. Also erstellen wir ein Modell, das die Statusänderung nachahmt, und speichern es im Pfad "app1/Message/StatusUpdate.php":
Bild
 {
public function __construct(protected string $status){}

public function getStatus(): string
{
    return $this->status;
}

}

Quellcode direkt verfügbar: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Message/StatusUpdate.php

Wir brauchen noch eine Klasse, die die Geschäftslogik implementiert, wenn unser Microservice das obige Ereignis von der Warteschlange erhält. Erstellen wir also eine Nachrichten-Handler im app1/Handler/StatusUpdateHandler.php Pfad:

Bild
 use PsrLogLoggerSchnittstelle;
use SymfonyComponentMessengerAttributeAsMessageHandler;

[AsMessageHandler]

class StatusUpdateHandler
{
public function __construct(
protected LoggerInterface $logger,
) {}

public function __invoke(StatusUpdate $statusUpdate): void
{
    $statusDescription = $statusUpdate->getStatus();

    $this->logger->warning('APP1: {STATUS_UPDATE} - '.$statusDescription);

    // der Rest der Geschäftslogik, d.h. das Senden einer E-Mail an den Benutzer
    // $this->emailService->email()
}

}

Quellcode direkt verfügbar: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Handler/StatusUpdateHandler.php

PHP Attribute machen die Dinge viel einfacher und bedeuten, dass wir uns in diesem speziellen Fall keine Gedanken über Autowiring oder Dienstdeklaration machen müssen. Unser Microservice für die Verarbeitung von Domänenereignissen ist fertig, es ist Zeit, sich mit der zweiten Anwendung zu befassen.

Zweiter Symfony-Microservice

Wir werden einen Blick auf die app2 Verzeichnis und das zweite Symfony-Anwendung. Unsere Idee ist es, eine Nachricht an die Warteschlange zu senden, wenn einem Worker eine Aufgabe im System zugewiesen wird. Lassen Sie uns also eine schnelle Konfiguration von AMQP durchführen und unseren zweiten Microservice mit der Veröffentlichung beginnen StatusUpdate Ereignisse an den Nachrichtenbus.

Die Installation der Bibliotheken erfolgt genauso wie bei der ersten Anwendung.

 cd ..
 cd app2/
 symfony composer req amqp ampq-messenger monolog

Wir müssen sicherstellen, dass die app2/.env Datei einen gültigen DSN-Eintrag für RabbitMQ enthält:

(...)
 MESSENGER_TRANSPORT_DSN=amqp://user:password@rabbitmq:5672//messages
 (...)

Alles, was bleibt, ist die Konfiguration von Symfony Messenger in der app2/config/packages/messenger.yaml file:

Rahmen:
messenger:
# Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
# failure_transport: failed

    Transporte:
        # https://symfony.com/doc/current/messenger.html#transport-configuration
        async:
            dsn: '%env(MESSENGER_TRANSPORT_DSN)%'

    Weiterleitung:
        # Leiten Sie Ihre Nachrichten an die Transporte weiter
        AppMessageStatusUpdate': async

Wie Sie sehen können, verweist die Transportdefinition diesmal direkt auf asynchron und definiert das Routing in Form des Sendens unserer StatusUpdate Nachricht an den konfigurierten DSN. Dies ist der einzige Bereich, der konfiguriert werden muss. Nun müssen nur noch die Logik und die Implementierungsschicht der AMQP-Warteschlange erstellt werden. Hierfür erstellen wir den Zwilling StatusUpdateHandler und StatusUpdate Klassen in app2.

Bild
 use PsrLogLoggerSchnittstelle;
use SymfonyComponentMessengerAttributeAsMessageHandler;

[AsMessageHandler]

class StatusUpdateHandler
{
public function __construct(
private readonly LoggerInterface $logger,
) {}

public function __invoke(StatusUpdate $statusUpdate): void
{
    $statusDescription = $statusUpdate->getStatus();

    $this->logger->warning('APP2: {STATUS_UPDATE} - '.$statusDescription);

    ## Geschäftslogik, d.h. Senden einer internen Benachrichtigung oder Einreihen in eine Warteschlange anderer Systeme
}

}
Bild
 {
public function __construct(protected string $status){}

public function getStatus(): string
{
    return $this->status;
}

}


Quellcode direkt verfügbar: /thecodest-co/microservices-in-symfony/blob/main/app2/src/Message/StatusUpdate.php

Schließlich muss nur noch eine Möglichkeit geschaffen werden, eine Nachricht an den Nachrichtenbus zu senden. Wir erstellen eine einfache Symfony-Befehl für diese:

Bild
use SymfonyComponentConsoleAttributeAsCommand;
use SymfonyComponentConsoleCommandBefehl;;
use SymfonyComponentConsoleEingabeEingabeSchnittstelle;
use SymfonyComponentConsoleOutputOutputInterface;
use SymfonyComponentMessengerMessageBusInterface;

[AsCommand(

Name: "app:send"

)]
class SendStatusCommand extends Command
{
public function construct(private readonly MessageBusInterface $messageBus, string $name = null)
{
parent::construct($name);
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
    $status = "Arbeiter X zugewiesen an Y";

    $this->messageBus->dispatch(
        Nachricht: new StatusUpdate($status)
    );

    return Befehl::SUCCESS;
}

}

Dank an Injektion von Abhängigkeiten können wir eine Instanz von MessageBusInterface in unserem Befehl und senden eine StatusUpdate Nachricht über die dispatch() Methode zu unserer Warteschlange. Zusätzlich verwenden wir hier auch PHP Attribute.

Das war's - jetzt müssen wir nur noch unsere Docker Compose-Umgebung ausführen und sehen, wie sich unsere Anwendungen verhalten.

Ausführen der Umgebung und Testen

Mit Docker Compose werden die Container mit unseren beiden Anwendungen als separate Instanzen erstellt und ausgeführt, die einzige Middleware-Schicht ist die rabbitmq Container und unsere Nachrichtenbus-Implementierung.

Führen Sie im Stammverzeichnis des Projekts die folgenden Befehle aus:

cd ../ # stellen Sie sicher, dass Sie sich im Hauptverzeichnis befinden
 docker-compose up --build -d

Dieser Befehl kann einige Zeit in Anspruch nehmen, da er zwei separate Container mit PHP 8.1 + AMQP erstellt und das RabbitMQ-Image zieht. Haben Sie Geduld. Nachdem die Images erstellt wurden, können Sie unseren Befehl von app2 und einige Nachrichten an eine Warteschlange senden.

 docker exec -it app2 php bin/console app:send

Du kannst es so oft machen, wie du kannst. Solange es keine Verbraucher werden Ihre Nachrichten nicht bearbeitet. Sobald Sie die app1 und konsumieren Sie alle Nachrichten, die auf Ihrem Bildschirm angezeigt werden.

docker exec -it app1 php bin/console messenger:consume -vv external_messages
Bild

Die vollständige Quellcode sowie die README finden Sie in unserem öffentlichen Repository The Codest Github

Zusammenfassung

Symfony mit seinen Bibliotheken und Tools ermöglicht einen schnellen und effizienten Ansatz zur Entwicklung moderner Webanwendungen. Mit ein paar Befehlen und ein paar Zeilen Code sind wir in der Lage, ein modernes Kommunikationssystem zwischen Anwendungen zu schaffen. Symfony, wie PHPist ideal für Entwicklung von Webanwendungen und dank seines Ökosystems und der einfachen Implementierung erreicht dieses Ökosystem einige der besten Markteinführungsindikatoren.

Schnell bedeutet jedoch nicht immer gut - im obigen Beispiel haben wir den einfachsten und schnellsten Weg der Kommunikation vorgestellt. Wissbegierigen wird sicherlich auffallen, dass es an der Trennung von Domänenereignissen außerhalb der Anwendungsschicht mangelt - in der aktuellen Version werden sie dupliziert, und es gibt keine vollständige Unterstützung für Umschlagunter anderem gibt es keine Briefmarken. Für diese und andere Fragen lade ich Sie ein, Teil II zu lesen, in dem wir das Thema der Vereinheitlichung der Domänenstruktur von Symfony-Anwendungen in einer Microservices-Umgebung behandeln und die zweite beliebte Microservices-Kommunikationsmethode diskutieren - diesmal synchron, basierend auf der REST-API.

Kooperationsbanner

Ähnliche Artikel

Software-Entwicklung

PHP 8.2: Was ist neu?

Die neue Version von PHP steht vor der Tür. Was sind die neuen Implementierungen, über die Sie Bescheid wissen sollten? Lesen Sie diesen Artikel, um es herauszufinden!

Der Codest
Sebastian Luczak PHP Einheitsführer
Software-Entwicklung

PHP Entwicklung. Symfony Konsolen-Komponente - Tipps & Tricks

Dieser Artikel wurde mit dem Ziel erstellt, Ihnen die nützlichsten und abrufbarsten Tipps und Tricks über Symfony Console Development zu zeigen.

Der Codest
Sebastian Luczak PHP Einheitsführer

Abonnieren Sie unsere Wissensdatenbank und bleiben Sie auf dem Laufenden über das Fachwissen aus dem IT-Sektor.

    Über uns

    The Codest - Internationales Software-Unternehmen mit technischen Zentren in Polen.

    Vereinigtes Königreich - Hauptsitz

    • Büro 303B, 182-184 High Street North E6 2JA
      London, England

    Polen - Lokale Tech-Hubs

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Warszawa, Polen

      Der Codest

    • Startseite
    • Über uns
    • Dienstleistungen
    • Fallstudien
    • Gewusst wie
    • Karriere
    • Wörterbuch

      Dienstleistungen

    • IT-Beratung
    • Software-Entwicklung
    • Backend-Softwareentwicklung
    • Frontend-Softwareentwicklung
    • Staff Augmentation
    • Backend-Entwickler
    • Cloud-Ingenieure
    • Daten-Ingenieure
    • Andere
    • QS-Ingenieure

      Ressourcen

    • Fakten und Mythen über die Zusammenarbeit mit einem externen Softwareentwicklungspartner
    • Aus den USA nach Europa: Warum entscheiden sich amerikanische Start-ups für eine Verlagerung nach Europa?
    • Tech Offshore Development Hubs im Vergleich: Tech Offshore Europa (Polen), ASEAN (Philippinen), Eurasien (Türkei)
    • Was sind die größten Herausforderungen für CTOs und CIOs?
    • Der Codest
    • Der Codest
    • Der Codest
    • Privacy policy
    • Website terms of use

    Urheberrecht © 2025 von The Codest. Alle Rechte vorbehalten.

    de_DEGerman
    en_USEnglish sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek de_DEGerman