リクエストが特定のプロセスに集中する

現象

時々、php start.php status コマンドを使って確認すると、リクエストが特定のプロセスに集中して処理されており、他のプロセスは完全にアイドル状態になっていることがあります。

先取メカニズム

Workermanの複数プロセスが接続を取得する方法はデフォルト先取式です。つまり、クライアントが接続を開始すると、すべてのアイドルプロセスがその接続を取得する機会を持ち、速い者勝ちとなります。誰が速いかは、オペレーティングシステムのカーネルのスケジューリングによって決まります。オペレーティングシステムは、最近使用されたプロセスがCPUの使用権を得る可能性が高く、その理由はCPUレジスタに前のプロセスのコンテキスト情報が残っている可能性があるため、コンテキストスイッチのオーバーヘッドを減少させることができるからです。したがって、ビジネスが十分に速い場合や負荷テスト中は、特定のプロセスに接続が集中して処理されることがより起こりやすく、この戦略は頻繁なプロセス切り替えを回避できるため、パフォーマンスが最適になり、特に問題ではありません。

ラウンドロビンメカニズム

Workermanは、$worker->reusePort = true; を設定することで接続の取得方法をラウンドロビンに変更できます。ラウンドロビン方式では、カーネルが接続をほぼ均等にすべてのプロセスに配分し、すべてのプロセスがリクエストを一緒に処理します。

誤解

多くの開発者は、すべてのプロセスがリクエスト処理に参加するほどパフォーマンスが向上すると考えていますが、必ずしもそうではありません。ビジネスが十分にシンプルな場合、リクエスト処理に参加するプロセス数がCPUコア数に近づくほど、サーバーのスループットは向上します。例えば、4コアのサーバーの場合、プロセス数を4に設定すると、helloworldの負荷テストにおけるQPSは一般的に最高になります。もしリクエスト処理に参加するプロセス数がCPUコア数を大幅に超えると、プロセスのコンテキストオーバーヘッドが大きくなり、パフォーマンスは逆に悪化します。一般的にデータベースを伴うビジネスの場合、プロセス数をCPUコア数の3倍から6倍に設定すると、パフォーマンスが向上する可能性があります。