PHP 8.2:新機能は?
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つの "サービス "を構築しているのだ:
適切な運用のためには ドッカーファイル
ファイルを作成しよう。それでは作ってみよう:
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
まずは アプリ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/%2f/messages
(…)
“
After preparing the application framework and configuring the libraries, it is time to implement the business logic. We know that our application must respond to the assignment of a job to a worker. We also know that assigning a job in theapp2system changes the status of the job. So let's create a model that mimics the status change and save it in theapp1/Message/StatusUpdate.php` path:
{
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
ディレクトリと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/%2f/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 に基づく同期通信 - について説明します。