window.pipedriveLeadboosterConfig={です。 ベース:'leadbooster-chat.pipedrive.com'、 companyId:11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2、 } ;(function () { var w = window もし (w.LeadBooster) {なら console.warn('LeadBooster already exists') } else { w.LeadBooster = { {. q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: 関数 (n) { { this.q.push({ t: 'o', n: n, h: h }) this.q.push({ t: 't', n: n }) }, } } })() symfony:マイクロサービスコミュニケーション part I - The Codest
The Codest
  • 会社概要
  • サービス
    • ソフトウェア開発
      • フロントエンド開発
      • バックエンド開発
    • Staff Augmentation
      • フロントエンド開発者
      • バックエンド開発者
      • データエンジニア
      • クラウドエンジニア
      • QAエンジニア
      • その他
    • アドバイザリー
      • 監査&コンサルティング
  • 産業
    • フィンテック&バンキング
    • E-commerce
    • アドテック
    • ヘルステック
    • 製造業
    • 物流
    • 自動車
    • アイオーティー
  • 価値
    • CEO
    • CTO
    • デリバリー・マネージャー
  • チーム
  • Case Studies
  • ノウハウ
    • ブログ
    • ミートアップ
    • ウェビナー
    • リソース
採用情報 連絡先
  • 会社概要
  • サービス
    • ソフトウェア開発
      • フロントエンド開発
      • バックエンド開発
    • Staff Augmentation
      • フロントエンド開発者
      • バックエンド開発者
      • データエンジニア
      • クラウドエンジニア
      • QAエンジニア
      • その他
    • アドバイザリー
      • 監査&コンサルティング
  • 価値
    • CEO
    • CTO
    • デリバリー・マネージャー
  • チーム
  • Case Studies
  • ノウハウ
    • ブログ
    • ミートアップ
    • ウェビナー
    • リソース
採用情報 連絡先
戻る矢印 戻る
2022-06-28
ソフトウェア開発

symfonyマイクロサービスコミュニケーション

The Codest

セバスチャン・ルザック

PHP ユニットリーダー

PHPシリーズの最初のパートを読んで、symfonyフレームワークでのマイクロサービス通信と最も一般的な方法であるRabbitMQを使ったAMQP通信を学びましょう。

現代のアプリケーション・アーキテクチャは、開発者にITシステムの異なるコンポーネント間のコミュニケーションについての考え方を変えることを余儀なくしている。かつては、問題はもっと単純だった。ほとんどのシステムは、ビジネス・ロジック接続のネットワークによって互いに接続されたモノリシック構造として作成されていた。このような依存関係を PHP プロジェクト にとって大きな挑戦だった。 PHP開発者そして、SaaSソリューションの人気の高まりと、SaaSソリューションの人気の大幅な高まりがある。 クラウド サービスが原因で、今日、マイクロサービスやアプリケーションのモジュール化について耳にする機会が増えている。

独立したマイクロサービスを作ることで、どのように相互に情報を交換できるのか?

この記事は、以下のシリーズ記事の第1回目である。 symfony におけるマイクロサービスコミュニケーション フレームワークで最も一般的な方法であるRabbitMQを使ったAMQP通信をカバーしている。

ゴール

独立した2つのアプリケーションを作成し、Message Busのみを使用してそれらの間の通信を実現する。

コンセプト

我々は2つの、架空の、独立したアプリケーションを持っている:
* アプリ1従業員にE-MailやSMSで通知を送信します。
* アプリ2従業員の仕事を管理し、タスクを割り当てることができます。

の従業員に仕事を割り当てることができる、現代的でシンプルなシステムを作りたい。 アプリ2 を使って顧客に通知を送る。 アプリ1.見かけによらず、これは非常にシンプルだ!

準備

この記事の目的のために、最新のSymfony(執筆時のバージョンは6.1)とPHPの最新バージョン(8.1)を使います。いくつかのとても簡単なステップで、2つのマイクロサービスで動作するローカルのDocker環境を作成します。必要なのは
* 動くコンピューター、
* Docker + をインストール Docker Compose環境
* およびローカルで設定された symfony CLI そして自由な時間。

ランタイム環境

アプリケーションの仮想化およびコンテナ化ツールとしてのDockerの機能を利用する。まずディレクトリ・ツリーを作成することから始めよう。 symfonyアプリケーションを使い、環境のインフラを説明する。 docker-compose.yml ファイル。

 cd ~
 mkdir microservices-in-symfony
 cd microservices-in-symfony
 symfonyの新しいapp1
 symfonyの新しいapp2
 docker-compose.yml をタッチする

2つの別々のsymfonyアプリケーションのために2つのディレクトリを作り、空の docker-compose.yml ファイルで環境を起動する。

以下のセクションを docker-compose.yml file:

バージョン: '3.8

サービス
app1:
コンテナ名:app1
build: app1/.
restart: 失敗時
envfile: app1/.env
環境ファイル:
APPNAME: app1
tty: true
stdinopen: true

app2
コンテナ名:app2
build: app2/.
restart: 失敗時
envfile: app2/.env
環境ファイル:
APPNAME: app2
tty: true
stdinopen: true

rabbitmq:
コンテナ名: rabbitmq
イメージ: rabbitmq:management
ポート
- 15672:15672
- 5672:5672
環境
- RABBITMQDEFAULTUSER=user
- RABBITMQDEFAULT_PASS=password

ソース コード 直接入手できる: thecodest-co/microservices-in-symfony/blob/main/docker-compose.yml

しかし待てよ、ここで何が起こったのだろうか?Dockerに馴染みのない人にとっては、上記の設定ファイルは謎めいて見えるかもしれないが、その目的はとてもシンプルだ。Docker Composeを使って3つの "サービス "を構築しているのだ:

  • app1: これは最初のsymfonyアプリケーションのコンテナです。
  • app2: 2番目のsymfonyアプリケーションのコンテナです。
  • rabbitmq: 通信ミドルウェア層としてのRabbitMQアプリケーションイメージ

適切な運用のためには ドッカーファイル ファイルを作成しよう。それでは作ってみよう:

 touch app1/Dockerfile
 touch app2/Dockerfile

どちらのファイルもまったく同じ構造で、以下のようになっている:

php:8.1 より

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

追加 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-extensions amqp

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/*

docker-php-ext-install zip を実行する;

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

ソースコードは直接入手可能: /thecodest-co/microservices-in-symfony/blob/main/app1/Dockerfile

上記のファイルは、Docker Compose が Composer と AMQP 拡張機能をインストールした PHP 8.1 イメージからコンテナをビルドするために使用する。さらに、PHP intepreter を append モードで実行し、コンテナをバックグラウンドで実行し続ける。

これで、ディレクトリとファイルツリーは以下のようになるはずだ:

 .
 ├── app1
 └── Dockerfile
 | # symfonyアプリの構造
 ├── app2
 └── Dockerfile
 | # symfonyアプリの構造
 └── docker-compose.yml

最初のsymfonyマイクロサービス

まずは アプリ1 ディレクトリと最初のアプリケーションの間にある。
この例では、以下のアプリケーションから送られるキューからのメッセージをリッスンし、消費する。 アプリ2 要求事項に記載されている通り:

の労働者に仕事を割り当てる。 アプリ2 はクライアントに通知を送る

必要なライブラリを追加することから始めよう。AMQPは メッセンジャー を拡張します。さらに モノローグ アプリケーションの動作分析を容易にするために、システムログを追跡する。

 cd app1/
 symfony composer req amqp ampq-messenger monolog

インストール後、以下のファイルが追加された。 config/packages/messenger.yaml.これはsymfonyのメッセンジャーコンポーネントの設定ファイルであり、このファイルは必要ありません。 フルコンフィギュレーション.
これを以下のYAMLファイルに置き換える:

フレームワーク
メッセンジャー
# 失敗したメッセージを後の処理のためにこのトランスポートに送るために、このコメント(および以下の failed トランスポート)を解除する。
# failure_transport: failed

    トランスポート:
        # https://symfony.com/doc/current/messenger.html#transport-configuration
        external_messages:
            DSN: '%env(MESSENGER_TRANSPORT_DSN)%'
            オプションを指定する:
                auto_setup: false
                交換:
                    名前:メッセージ
                    タイプ: ダイレクト
                    default_publish_routing_key: from_external
                キュー
                    メッセージ:
                        バインディングキー:[from_external]

ソースコードは直接入手可能: thecodest-co/microservices-in-symfony/blob/main/app1/config/packages/messenger.yaml

symfony Messenger は symfony アプリケーションにおいて同期と非同期の通信に使われます。さまざまな 輸送つまり、トランスポート・レイヤーの真実の情報源である。この例では、RabbitMQイベントキューシステムをサポートするAMQPエクステンションを使用している。

上記のコンフィギュレーションは 外部メッセージを参照している。 メッセンジャー・トランスポート 環境変数で メッセージ チャンネルを編集します。この時点で app1/.env ファイルに適切なトランスポートアドレスを追加する。

"`env

(...)
MESSENGERTRANSPORTDSN=amqp://user:password@rabbitmq:5672//messages
(...)
"
アプリケーションフレームワークを準備し、ライブラリを設定したら、いよいよビジネスロジックを実装します。アプリケーションは、ワーカーへのジョブの割り当てに応答しなければならないことがわかっています。また、app2systemでジョブを割り当てると、ジョブのステータスが変更されることもわかっています。そこで、ステータスの変更を模倣するモデルを作成し、app1/Message/StatusUpdate.php`パスに保存しましょう:
イメージ
 {
public function __construct(protected string $status){}。

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

}

ソースコードは直接入手可能: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Message/StatusUpdate.php

マイクロサービスがキューから上記のイベントを受け取ったときのビジネスロジックを実装するクラスがまだ必要です。そこで メッセージハンドラ での app1/Handler/StatusUpdateHandler.php をパスした:

イメージ
 PsrLogLoggerInterface を使います;
use SymfonyComponentMessengerAttributeAsMessageHandler;

[AsMessageHandler]

クラス StatusUpdateHandler
{
public function __construct(
protected LoggerInterface $logger、
) {}

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

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

    // 残りのビジネスロジック、つまりユーザーにメールを送信する
    // $this->emailService->email()
}

}

ソースコードは直接入手可能: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Handler/StatusUpdateHandler.php

PHP 属性は物事をより簡単にし、この特別なケースでは自動配線やサービス宣言について心配する必要がないことを意味します。ドメイン・イベントを処理するマイクロサービスの準備ができたので、2つ目のアプリケーションに取り掛かろう。

2番目のsymfonyマイクロサービス

を見てみよう。 アプリ2 ディレクトリと2番目の symfonyアプリケーション.私たちのアイデアは、ワーカーがシステムでタスクを割り当てられたときにキューにメッセージを送信することです。それでは、AMQPの簡単な設定を行い、2番目のマイクロサービスがパブリッシングを開始するようにしましょう。 ステータス更新 イベントをメッセージバスに送る。

ライブラリーのインストールは、最初のアプリケーションとまったく同じです。

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

を確認しよう。 app2/.env ファイルにはRabbitMQの有効なDSNエントリが含まれています:

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

残りの作業は app2/config/packages/messenger.yaml file:

フレームワーク
メッセンジャー
# 失敗したメッセージを後の処理のためにこのトランスポートに送るために、このコメント(および以下の failed トランスポート)を解除する。
# failure_transport: failed

    トランスポート:
        # https://symfony.com/doc/current/messenger.html#transport-configuration
        非同期:
            DSN: '%env(MESSENGER_TRANSPORT_DSN)%'

    ルーティング:
        # メッセージをトランスポートにルーティングする。
        'AppMessageStatusUpdate': 非同期

ご覧のように、今回のトランスポート定義は直接 非同期 を送るという形でルーティングを定義している。 ステータス更新 メッセージを設定された DSN に送信します。これが唯一の設定領域で、あとは AMQP キューのロジックと実装レイヤーを作成するだけである。このために、我々は双子の ステータス更新ハンドラ そして ステータス更新 クラス アプリ2.

イメージ
 PsrLogLoggerInterface を使います;
use SymfonyComponentMessengerAttributeAsMessageHandler;

[AsMessageHandler]

クラス StatusUpdateHandler
{
public function __construct(
private readonly LoggerInterface $logger、
) {}

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

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

    ##ビジネスロジック、つまり内部通知を送信したり、他のシステムのキューに入れたりします。
}

}
イメージ
 {
public function __construct(protected string $status){}。

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

}


ソースコードは直接入手可能: /thecodest-co/microservices-in-symfony/blob/main/app2/src/Message/StatusUpdate.php

最後に、メッセージバスにメッセージを送る方法を作るだけです。簡単な symfonyコマンド そのためだ:

イメージ
use SymfonyComponentConsoleAttributeAsCommand;
use SymfonyComponentConsoleCommandCommand;
use SymfonyComponentConsoleInputInterface;
を使います;
を使います;

[AsCommand(

name: "app:send"

)]
クラス 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 = "Worker X assigned to Y";

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

    return Command::SUCCESS;
}

}

ありがとう 依存性の注入 のインスタンスを使うことができる。 メッセージ・バス・インターフェース を送信する。 ステータス更新 メッセージは ディスパッチ() メソッドをキューに追加します。さらに、ここではPHP属性も使用している。

これで完了だ。あとはDocker Compose環境を実行し、アプリケーションの動作を確認するだけだ。

環境の実行とテスト

Docker Composeでは、2つのアプリケーションを含むコンテナは別々のインスタンスとしてビルドされ、実行されます。 ウサギmq コンテナとメッセージ・バスの実装。

プロジェクトのルート・ディレクトリから、以下のコマンドを実行してみよう:

cd ../ # メインディレクトリにいることを確認する。
 docker-compose up --build -d

このコマンドは、PHP 8.1 + AMQPとRabbitMQイメージをプルする2つの別々のコンテナを構築するため、時間がかかることがあります。しばらくお待ちください。イメージのビルドが完了したら、次のコマンドを実行します。 アプリ2 で、キューにメッセージを送る。

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

何度でもできる。何度でもできる。 消費者 メッセージは処理されません。を起動するとすぐに アプリ1 そして、画面に表示されるすべてのメッセージを消費する。

docker exec -it app1 php bin/console messenger:consume -vv external_messages
イメージ

完全な ソースコード とREADMEは私たちの公開リポジトリにあります。 The Codest Github

概要

symfony のライブラリとツールによって、モダンな ウェブアプリケーション.いくつかのコマンドと数行のコードでアプリケーション間のモダンな通信システムを作ることができます。symfony は PHPに最適である。 ウェブアプリケーションの開発 そして、そのエコシステムと実装の容易さのおかげで、このエコシステムは最高の市場投入までの時間指標を達成している。

上記の例では、最もシンプルで高速な通信方法を紹介した。より詮索好きな人なら、アプリケーション・レイヤーの外側でドメイン・イベントの接続が切れていないことに気づくだろう。 封筒特に、このような問題はない。 スタンプ.これらのトピックとその他のトピックについては、パート II を読んでください。パート II では、マイクロサービス環境で symfony アプリケーションのドメイン構造を統一するトピックと、2番目に人気のあるマイクロサービスの通信方法 - 今回は REST API に基づく同期通信 - について説明します。

協力バナー

関連記事

ソフトウェア開発

PHP 8.2:新機能は?

PHPの新バージョンは目前。あなたが知っておくべき新しい実装とは何でしょうか?この記事で確認してほしい!

The Codest
セバスチャン・ルザック PHP ユニットリーダー
ソフトウェア開発

PHPの開発symfony コンソールコンポーネント - ヒントとコツ

この記事は、symfony コンソール開発に関するもっとも便利で検索しやすいヒントとトリックをお見せする目的で作成されました。

The Codest
セバスチャン・ルザック PHP ユニットリーダー

ナレッジベースを購読して、IT部門の専門知識を常に最新の状態に保ちましょう。

    会社概要

    The Codest - ポーランドに技術拠点を持つ国際的なソフトウェア開発会社。

    イギリス - 本社

    • オフィス 303B, 182-184 High Street North E6 2JA
      イギリス、ロンドン

    ポーランド - ローカル・テック・ハブ

    • ファブリチュナ・オフィスパーク、アレハ
      ポコジュ18、31-564クラクフ
    • ブレイン・エンバシー, コンストルクトースカ
      11, 02-673 Warsaw, Poland

      The Codest

    • ホーム
    • 会社概要
    • サービス
    • Case Studies
    • ノウハウ
    • 採用情報
    • 辞書

      サービス

    • アドバイザリー
    • ソフトウェア開発
    • バックエンド開発
    • フロントエンド開発
    • Staff Augmentation
    • バックエンド開発者
    • クラウドエンジニア
    • データエンジニア
    • その他
    • QAエンジニア

      リソース

    • 外部ソフトウェア開発パートナーとの協力に関する事実と神話
    • 米国から欧州へ:アメリカの新興企業がヨーロッパへの移転を決断する理由
    • テックオフショア開発ハブの比較:テックオフショア ヨーロッパ(ポーランド)、ASEAN(フィリピン)、ユーラシア(トルコ)
    • CTOとCIOの課題は?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • ウェブサイト利用規約

    著作権 © 2025 by The Codest。無断複写・転載を禁じます。

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