非同期 PHP タスクは、cron ジョブが負荷のピーク、長い実行時間、透明性の欠如を引き起こす場合に、典型的なボトルネックを解決します。その方法をご紹介します。 非同期 PHP キューとワーカーを使って、Webリクエストの負荷を軽減し、ワークロードをスケーリングし、イライラすることなく障害を緩和します。.
中心点
はじめに、この記事の基礎となる、私が日常的に実践している重要な指針をまとめます。. 基本
- デカップリング リクエストとジョブ:Webリクエストは高速で、ジョブはバックグラウンドで実行されます。.
- スケーリング ワーカープールについて:インスタンス数が増え、待ち時間が短縮されます。.
- 信頼性 再試行:失敗したタスクを再起動します。.
- 透明性 モニタリングにより、キューの長さ、実行時間、エラー率を把握。.
- 分離 ワークロード別:short、default、long、適切な制限付き。.
Cronジョブがもはや十分ではない理由
cronジョブは、実際の時刻ではなく、厳密に設定された時刻に開始されます。 イベント. ユーザーが何かを実行したら、次の1分まで待つのではなく、すぐに対応したい。 多くのクロンジョブが同時に実行されると、データベース、CPU、I/O に一時的に過大な負荷がかかります。並行性は限定的であり、細かい優先順位を設定することは困難です。キューを使用すると、タスクをすぐにキューに入れ、複数のワーカーを並行して実行し、Web インターフェースを常に レスポンシブ. WordPress を使用しているユーザーは、さらに以下のメリットも享受できます。 WP-Cron を理解する そして、時間指定の計画が確実にキューに送られるように、きちんと設定したい。.
非同期処理:ジョブキューワーカーについて簡単に説明
私は高価なタスクを明確な 仕事, 、何をすべきかを記述した、データ参照を含むジョブです。このジョブは、負荷のピークに対するバッファとして私が使用している、複数のコンシューマーにサービスを提供するキューに送られます。 ワーカーは、キューからジョブを読み取り、実行し、結果を確認する永続的なプロセスです。ワーカーが故障した場合、ジョブはキューに残り、後で別のインスタンスによって処理されます。この疎結合により、アプリケーション全体が フォールトトレラント フロントエンドで一貫した応答時間を確保します。.
PHP環境におけるキューとワーカーの仕組み
PHPでは、ジョブを単純なクラスまたはシリアル化可能なクラスとして定義します。 ペイロード ハンドラーを使用します。キューは、サイズとレイテンシーの要件に応じて、データベーステーブル、Redis、RabbitMQ、SQS、または Kafka を使用できます。ワーカープロセスは、多くの場合、Supervisor、Systemd、またはコンテナサービスとして独立して実行され、ジョブを継続的に取得します。ACK/NACK メカニズムを使用して、処理の成功と失敗を明確に通知します。 重要なのは、私が スループット率 ワーカーが予想されるジョブ量に合わせて調整しないと、キューがどんどん増えていくよ。.
ホスティング環境におけるPHPワーカー:ボトルネックではなくバランス
PHPワーカーが少なすぎるとバックログが発生し、多すぎるとCPUとRAMに負荷がかかり、すべて(以下を含む)の速度が低下します。 ウェブリクエスト. 。短いタスクが長いレポートで滞留しないように、ワーカー数とキューごとの同時実行数を個別に計画しています。また、メモリ制限と定期的な再起動を設定して、リークを捕捉しています。制限、CPU コア、同時実行数について不安がある方は、私の簡潔な PHPワーカーに関するガイド 典型的なバランス戦略を用いて。このバランスは、最終的には必要な 計画性 成長と均一な応答時間のために。.
タイムアウト、再試行、および冪等性:信頼性の高い処理を確保する
私はすべての仕事に タイムアウト, これにより、ワーカーが欠陥のあるタスクに無限に縛られることがなくなります。ブローカーは、タスクが誤って二重に表示されないように、最大ジョブ時間より少し長い可視性タイムアウトを受け取ります。多くのシステムは「少なくとも 1 回」の配信を使用しているため、私は冪等なハンドラを実装しています。二重の呼び出しによって、二重の E メールや支払いが発生することはありません。 リトライにはバックオフを設定し、外部 API をオーバーライドしないようにしています。これにより、 エラー率 低く、問題を正確に診断することができます。.
ワークロードの分離:ショート、デフォルト、ロング
私は、短期的、中期的、長期的な仕事ごとに別々のキューを作成しています。これにより、1回のエクスポートによって10件もの通知がブロックされることを防ぎ、 ユーザー 待ち時間。各キューには、実行時間、同時実行数、メモリに関する適切な制限が設定された独自のワーカープールが割り当てられます。短いタスクは、より高い並列性と厳格なタイムアウトの恩恵を受け、長いプロセスはより多くの CPU とより長い実行時間を割り当てられます。優先度は、ワーカーをキューに割り当てることで制御します。この明確な分離により、予測可能な 遅延時間 システム全体において。.
キューオプションの比較:どのシステムがいつ適しているか
レイテンシ、持続性、運用、成長経路を慎重に考慮してキューを選択することで、後で高額の移行費用がかかることを避け、 スケーリング 制御下に留まる。.
| キューシステム | 用途 | レイテンシー | 特徴 |
|---|---|---|---|
| データベース(MySQL/PostgreSQL) | 小さなセットアップ、簡単なスタート | ミディアム | 取り扱いは簡単ですが、すぐに ボトルネック 高負荷時 |
| レディス | 小~中程度の負荷 | 低い | RAMで非常に高速、明確な 構成 信頼性のために |
| RabbitMQ / Amazon SQS / Kafka | 大規模分散システム | 低~中 | 豊富な機能、優れた スケーリング, 、より多くの運営費用 |
Redis を正しく使用する方法 – 典型的な障害を回避する
Redis は超高速に感じられますが、設定が間違っていたり、データ構造が適切でなかったりすると、奇妙な結果になることがあります。 待ち時間. 。AOF/RDB 戦略、ネットワークの遅延、大きすぎるペイロード、ブロックするコマンドに注意を払っています。また、キャッシュのピークがジョブの取得を遅らせないように、キャッシュとキューのワークロードを分離しています。設定ミスに関する簡潔なチェックリストについては、このガイドが参考になります。 Redis の設定ミス. 正しく設定すれば、迅速かつ信頼性の高い 待ち行列 多くの用途に。.
実践におけるモニタリングとスケーリング
私は、キューの長さを時間の経過とともに測定します。なぜなら、増加する バックログ ワーカーリソースの不足を示しています。平均ジョブ時間は、タイムアウトを現実的に設定し、キャパシティを計画するのに役立ちます。エラー率とリトライ回数は、外部依存関係やコードパスが不安定になっていることを示しています。コンテナでは、CPU およびキューのメトリクスに基づいてワーカーを自動的にスケーリングしますが、小規模なセットアップでは簡単なスクリプトで対応できます。数字だけが根拠のある判断材料となるため、可視性は依然として重要です。 決断 イネーブル
Cron plus Queue:競争ではなく、明確な役割分担
私は、時間制御でジョブをスケジュールするクロックとしてCronを使用し、ワーカーは実際の 労働 引き受けます。これにより、1 分間の負荷の急上昇は発生せず、突発的なイベントにも、キューに登録されたジョブが即座に対応します。定期的な集計レポートは Cron でスケジュールしますが、個々のレポートの詳細はワーカーが処理します。WordPress の設定については、「„WP-Cron を理解する“計画の一貫性を保つためです。これにより、スケジュールを整理し、確実に 柔軟性 実行において。.
最新の PHP ランタイム:RoadRunner と FrankenPHP のキューとの連携
永続的なワーカープロセスは、起動時のオーバーヘッドを節約し、接続を開いたまま維持し、 レイテンシー. RoadRunner と FrankenPHP は、長寿命のプロセス、ワーカープール、共有メモリを採用しており、負荷時の効率を大幅に向上させます。キューと組み合わせることで、均一なスループット率を維持し、リソースの再利用のメリットを享受できます。私は、Web トラフィックとバックグラウンドジョブが互いに干渉しないように、HTTP 処理とキューコンシューマーを別々のプールに分離することがよくあります。このような方法で作業することで、安定した パフォーマンス 需要が大きく変動する場合でも。.
セキュリティ:データを慎重に扱い、暗号化すること
私は、個人データをペイロードに直接入れることは決してなく、後で読み込むIDだけを入れます。 データ保護 を保護します。ブローカーへのすべての接続は暗号化されており、サービスが提供している場合は、休止時暗号化を使用しています。プロデューサーとコンシューマーは、最小限の権限を持つ別々の権限を取得します。アクセスデータは定期的にローテーションし、ログやメトリクスからシークレットを排除しています。このアプローチにより、攻撃対象領域が縮小され、保護されます。 守秘義務 機密情報。.
Async-PHP の実践的な使用シナリオ
私は、Webリクエストでメールを送信することはもうやめて、ユーザーが 発送 待つ。メディア処理では、画像をアップロードしてすぐに応答し、後でサムネイルを生成することで、アップロードの体験がすごくスムーズになるよ。データセットが多いレポートは非同期で起動して、ワーカーが完了したら結果をダウンロードできるようにするんだ。 決済、CRM、マーケティングシステムとの統合については、タイムアウトや散発的な障害を穏やかに緩和するために、API 呼び出しを分離しています。キャッシュのウォームアップと検索インデックスの更新は、バックグラウンドで実行するように変更しています。 UI は速いままだ。
ジョブ設計とデータフロー:ペイロード、バージョン管理、および冪等性キー
ペイロードはできるだけスリムに保ち、参照のみを保存します。 ID, 、タイプ、バージョン、相関キーまたは冪等性キー。バージョンを使用してペイロードスキーマを識別し、古いジョブがまだ正常に処理されている間に、ハンドラを安心して開発し続けることができます。冪等性キーは、二重の副作用を防止します。起動時にデータストレージに記録され、繰り返し時に照合されるため、2通目のメールや2回目の予約が発生することはありません。 複雑なタスクの場合は、ワークフロー全体を 1 つのタスクにまとめるのではなく、ジョブを小さく、明確に定義されたステップ(コマンド)に分割します。これにより、再試行やエラー処理が可能になります。 ターゲット つかむ。.
アップデートには、私はこれを使っています。 送信トレイのサンプル: 変更は、データベーストランザクション内でアウトボックステーブルに書き込まれ、その後、ワーカーによって実際のキューに公開されます。これにより、アプリケーションデータと送信されたジョブ間の不整合を回避し、堅牢な「„少なくとも一度“「副作用が明確に定義された配送。.
エラーパターン、DLQ、および「ポイズンメッセージ」„
すべてのエラーが一時的なものとは限りません。私は、以下の問題と明確に区別しています。 リトライ 解決(ネットワーク、レート制限)、および最終的なエラー(データ不足、検証)があります。後者については、 デッドレターキュー (DLQ) 限定された再試行回数に達すると、ジョブはそこに送られます。DLQ には、理由、スタックトレースの抜粋、再試行回数、関連エンティティへのリンクを保存します。これにより、手動で再起動するか、データを修正するか、ハンドラを修正するかを具体的に判断することができます。 「ポイズンメッセージ」(再現性のあるクラッシュを引き起こすジョブ)は、起動の失敗を即座に認識し、プール全体の速度を低下させることのないよう、早期にブロックします。.
優雅なシャットダウン、デプロイ、ローリング再起動
デプロイでは、私は以下に従います。 優雅なシャットダウン: このプロセスは、進行中のジョブを最後まで処理しますが、新しいジョブは受け付けません。そのため、SIGTERM をインターセプトし、「ドレニング」ステータスを設定し、必要に応じて可視性(可視性タイムアウト)を延長して、ブローカーがジョブを別のワーカーに割り当てないようにします。 コンテナ設定では、最大ジョブ期間に合わせて、終了猶予期間をたっぷり設定するよ。ローリング再起動は、小さなバッチに減らして、 定員 クラッシュしない。さらに、健全なワーカーだけがジョブを実行することを保証するハートビート/ヘルスチェックを設定します。.
バッチ処理、レート制限、バックプレッシャー
多くの小規模な手術は、必要に応じてまとめて行います。 バッチ まとめ:ワーカーは 100 個の ID をロードし、それらを一括で処理することで、ネットワークの遅延や接続確立によるオーバーヘッドを削減します。外部 API については、レート制限を遵守し、トークンバケットまたはリーキーバケットメカニズムを使用して、 問い合わせ率. エラー率が増加したり、レイテンシが増加したりすると、ワーカーは自動的に並列処理を低減します (適応的並行処理)が安定するまで続けます。バックプレッシャーとは、キューの長さが特定のしきい値を超えた場合に、プロデューサーがジョブの生産を抑制することを意味します。これにより、システムを圧倒する雪崩を回避することができます。.
優先順位、公平性、およびクライアントの分離
優先順位付けは、個別の優先度キューだけでなく、 加重 ワーカーの割り当て:プールは、70% が「ショート」、20% が「デフォルト」、10% が「ロング」で動作し、どのカテゴリも完全に枯渇することがないようにします。マルチテナントのセットアップでは、独自のキューまたは専用のワーカープールを使用して、重要なテナントを分離しています。 騒がしい隣人たち レポートについては、長時間かかるジョブを延々と後回しにするような厳格な優先順位付けは避けています。代わりに、時間帯(例えば夜間)を計画し、並行して実行される重いジョブの数を制限することで、日中はプラットフォームが snappy が残っている。
可観測性:構造化されたログ、相関、SLO
私は、ジョブ ID、相関 ID、期間、ステータス、再試行回数、および重要なパラメータを構造化して記録しています。これにより、フロントエンドリクエスト、キューに登録されたジョブ、およびワーカーの履歴を相関させることができます。このデータから、以下を定義します。 SLO:約 95% のすべての「ショート」ジョブを 2 秒以内に、「デフォルト」を 30 秒以内に、「ロング」を 10 分以内に実行します。 バックログの増加、エラー率の上昇、異常な実行時間、DLQ の増加時にアラートが作動します。ランブックには、スケーリング、スロットリング、再起動、DLQ 分析などの具体的な手順が記載されています。明確な指標があってこそ、私は良い判断を下せるのです。 キャパシティの決定.
開発とテスト:ローカル、再現性、信頼性
地域開発には、私は 偽のキュー または、開発モードで実際のインスタンスを起動し、フォアグラウンドでワーカーを起動して、ログがすぐに表示されるようにします。 ジョブをキューに入れ、ワーカーを実行し、期待されるページの結果(データベースの変更など)を確認する統合テストを作成します。 生成されたジョブで負荷テストをシミュレートし、スループット、95/99 パーセンタイル、エラー率を測定します。テストの安定性を維持するには、データの再現性のあるシードと決定論的なハンドラが重要です。メモリリークは継続的なテストで検出されます。定期的な再起動を計画し、 記憶曲線.
リソース管理:CPU 対 I/O、メモリ、および並列性
私は、CPU負荷の高いジョブとI/O負荷の高いジョブを区別しています。CPU負荷の高いタスク(画像変換など)は、並列処理を明確に制限し、コアを予約します。I/O負荷の高いタスク(ネットワーク、データベース)は、レイテンシとエラーが安定している限り、より多くの同時実行の恩恵を受けます。 PHP では、opcache を使用し、永続的なワーカーで再利用可能な接続(永続的な接続)に注意を払い、ジョブの終了時にオブジェクトを明示的に解放して、 フラグメンテーション 回避する。ジョブごとのハードリミット(メモリ/ランタイム)により、異常値がプール全体に影響を与えることを防ぎます。.
段階的な移行:cronジョブからキューファーストアプローチへ
私は段階的に移行します。まず、重要度の低いメールや通知タスクをキューに移します。次に、タイムアウトを頻繁に発生させるメディア処理と統合呼び出しを移します。既存のcronジョブはクロックとして残しますが、その作業をキューに移します。 次のステップでは、ワークロードを short/default/long に分類し、一貫して測定します。最後に、ワーカーが安定して動作したら、重い cron ロジックを削除し、 イベント・ドリブン エンキューポイント(例:「ユーザー登録」→「ウェルカムメール送信」)を設定します。これによりリスクが軽減され、チームとインフラストラクチャは新しいパターンに制御された形で成長します。.
ガバナンスと運用:ポリシー、クォータ、コスト管理
私は、最大ペイロードサイズ、許容実行時間、許可される外部ターゲット、クライアントごとのクォータ、高コストのジョブの日中時間帯など、明確なポリシーを定義しています。コストは、夜間にワーカープールをスケーリングし、オフピーク時にバッチジョブをまとめて、クラウドサービスに制限を設けることで管理しています。 アウトライアーズ インシデントについては、エスカレーションパスを用意しています:DLQアラーム→分析→ホットフィックスまたはデータ修正→管理された再処理。この規律により、システムが成長しても、その管理は可能となります。.
最終的な考察:Cronジョブからスケーラブルな非同期アーキテクチャへ
私は、遅いタスクを Web レスポンスから切り離し、 労働者 キューは負荷をバッファリングし、タスクの優先順位付けを行い、再試行やエラーパターンを整理します。分離されたワークロード、明確なタイムアウト、および冪等なハンドラにより、システムは予測可能な状態を維持します。ホスティング、ワーカーの制限、ブローカーの選択は、直感ではなく、実際のメトリクスに基づいて決定します。このアーキテクチャを早期に導入したユーザーは、より迅速な応答と、より優れた スケーリング そして、日々の業務においてより一層の落ち着きを得ることができます。.


