
私たちは、Ubuntu 20 LTS 上に serverpilot でインストールされた nginx スタックを使用して WordPress サイトを実行しているサーバーを持っています。
非常に大きなアップロードは、nginx プロキシと PHP 間のハンドオフで停止しているようです。何が起こるかを調べるためにただ触る以外に、私が知っているトラブルシューティング方法はもう限界です (これは時間の無駄であり、前進する方法でもありません)。私が知る限り、必要なタイムアウトを増やし、すべてのディスク制限を上げましたが、明らかにまだ何かが欠けています。
私たちのユースケースでは、最大 50 GB のアップロードを許可する必要がありますが、標準の LAMP スタックを実行するステージング環境では問題なく動作しています。約 2 GB 未満のファイルでは問題はありませんが、それを超えると、追跡できなかったいくつかの基準に基づいて失敗する可能性があります。以前、この問題のトラブルシューティングを行っていたときに、ファイルのコピーが停止した時間は任意であるように見えましたが (10 GB までは成功)、現在の構成 (以下を参照) では、PHPtmp
ファイルが 2 GB に達すると常に停止します。
非常に大きなファイルをアップロードする場合、ファイル全体が存在するまで、受信一時ファイルがディスク領域を消費するのを見ることができます/mnt/tmp/[nginx_tmp_path]
(はい、十分なディスク領域があります)。その後、ファイルが PHPtmp
パスにコピーされているのがわかりますが、数秒後に PHPtmp
ファイルのサイズが大きくなり、コピー プロセスが停止します。最終的に、600 秒のタイムアウトの 1 つに達し、エラーが記録されます (以下を参照)。このスクリーンショットでは、(ブラウザー/エンド ユーザーの観点から) 14.8 GB のアップロードが完了し、一時ファイルの転送が約 2 GB で停止しています。
600 秒の期間の終了時に、Apache エラー ログに次の内容が記録されます。
(70008)Partial results are valid but processing is incomplete: [client <MY_IP>] AH01075: Error dispatching request to : (reading input brigade), referer: https://<THE_URL>/wp-admin/media-new.php
nginx のエラー ログには次のように表示されました。
2512066#0: *9 upstream timed out (110: Connection timed out) while sending request to upstream, client: <MY_IP>, server: <INTERNAL_IP>, request: "POST /wp-admin/async-upload.php HTTP/2.0", upstream: "http://127.0.0.1:81/wp-admin/async-upload.php", host: "<THE_URL>", referrer: "https://<THE_URL>/wp-admin/media-new.php"
重要な点として、これらのメッセージは、アップロードが最初にサーバーに完全に到着してから 10 分後、つまりファイル コピーが一時停止/ハングしたように見えてから 9 分以上経過するまでログ ファイルに表示されないことに注意してください。何かが原因でファイル コピーが停止し、最終的にタイムアウトに達したと確信しています。タイムアウト自体に問題があるとは思いません。ファイル コピーが停止してからタイムアウト エラーがログ ファイルに表示されるまでの間、サーバー上でアクティビティの増加や異常は発生せず、すべてのサービスが期待どおりに機能し、応答します。
現在の構成では、PHPtmp
ファイルは常に 2097152 KB まで大きくなります (によるとdu -a
)。そのため、現時点ではまだ明らかにしていない組み込みのファイル サイズ制限に達していると考えられます。
関連する nginx サーバー設定オプションは次のとおりですserver
:
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_max_temp_file_size 51200m;
fastcgi_connect_timeout 600;
fastcgi_read_timeout 600;
fastcgi_send_timeout 600;
fastcgi_request_buffering off;
keepalive_timeout 600;
send_timeout 600;
client_max_body_size 0;
client_body_temp_path /mnt/tmp;
client_body_in_file_only clean;
Apache の VirtualHost 設定:
RequestReadTimeout header=0 body=0
Timeout 3600
ProxyTimeout 3600
最後に、PHP 設定:
memory_limit = -1
max_execution_time = 0
max_input_time = -1
post_max_size = 50G
upload_max_filesize = 50G
default_socket_timeout = -1
私が見ている症状の原因が何なのか、まったくわかりません。何かアドバイスがあれば、ぜひ教えてください。
追記:症状からすると関係ない気がしますが、もし関係あるなら…サイトはWP Rocket経由で動いていますが、CloudFlareのような外部プロキシサービスはありません。
アップデート: nginx 設定に次の行を追加しました:
proxy_http_version 1.1;
proxy_set_header Connection "";
これにより症状は少し変わりましたが、問題は解決しませんでした。この変更により、動作は以前説明したとおりに戻り、ファイル転送は予期しない場所で停止します。以下の最初の例は 3823176 KB で停止し、2 番目の例は 3264364 KB で停止しました。動作の違いの理由は私にはわかりませんが、報告する価値はあります。
アップデート2: これは nginx と php 間のファイルの受け渡しの問題であると明確に特定できましたtmp
が、プロセスがハングする原因となっている具体的な原因を特定できないようです。
tmp
nginx 設定に次の行を追加することで、nginx プロキシをスキップし、PHP のみを使用できます。
proxy_buffering off;
proxy_request_buffering off;
この構成では、ファイルは直接アップロードされ/mnt/tmp/php<RND_STR>
、アップロードが完了すると、アプリケーションはファイルを適切に取り出してtmp
タスクを完了します。
ただし、これによりアップロード速度が利用可能な帯域幅の約 1/3 に低下するため、これは適切な解決策ではありません。ただし、これはアプリケーションの問題ではないことが証明されています。
つまり、次のようなことが起こっているのです:
- ユーザーが大きなファイルをアップロードします(使用ケースの最大値は 50 GB です)
- ファイルは
tmp
そのままnginxの場所に届きます tmp
ファイルを nginxから PHP にコピーしようとするtmp
と、コピー プロセスは数秒以内に停止しますが、停止する場所は予測できません (3 GB から 10 GB の間)。[3b] この時点では、両方のtmp
ファイルが表示され、PHPtmp
ファイルには、nginx ファイルのサイズと等しくなるまで増加するはずのバイト数が含まれていますtmp
が、実際にはそうではありません。両方のファイルは、600 秒のタイムアウトのいずれかに達するまで (上記を参照)、そのままの状態になりますtmp
。その後、ログ ファイルにエラーが表示され、両方のファイルが消えます。[3c] ファイルが 3 GB 未満の場合、常に機能します。ファイルが 3 GB を超える場合、機能することもあれば機能しないこともあります。ファイルが小さいほど、機能する可能性が高くなります。- nginx をバイパスする
tmp
と、アップロードが遅くなる点を除いて、完全に期待どおりに動作します。
ファイルが異常に大きい場合、nginx と PHP 間のファイル受け渡し中に何かが確実にハングアップしておりtmp
、それが何であるかを解明したいと思います。