
我們有一台在 Ubuntu 20 LTS 上執行 WordPress 網站的伺服器,並在 Ubuntu 20 LTS 上安裝了 serverpilot 安裝的 nginx 堆疊。
非常大的上傳似乎陷入了nginx 代理和PHP 之間的切換,我已經完成了我所知道的如何排除故障,而不僅僅是戳它看看會發生什麼(這很少是一個很好的時間利用或前進的方式)。據我所知,我已經增加了必要的超時並提高了所有磁碟限制,但我顯然仍然缺少一些東西。
對於我們的用例,我們需要允許上傳高達 50GB 的文件,我們在運行標準 LAMP 堆疊的臨時環境中可以正常運作。我們對~2GB以下的檔案沒有任何問題,但根據我無法追蹤的一些標準,超過2GB的檔案可能會失敗,也可能不會失敗。在早些時候對問題進行故障排除時,檔案複製停止的時間似乎是任意的(成功達到 10GB),但使用當前配置(見下文),當 PHP 檔案tmp
達到 2GB 時,檔案複製始終會停止。
當我們上傳非常大的檔案時,我們可以看到傳入的臨時檔案消耗磁碟空間,直到整個檔案存在/mnt/tmp/[nginx_tmp_path]
(是的,有足夠的可用磁碟空間)。之後,我們可以看到檔案被複製到 phptmp
路徑,但幾秒鐘後,phptmp
檔案大小停止成長,複製過程掛起。最終,達到了 600 秒超時之一,並且記錄了錯誤(見下文)。在此螢幕截圖中,我們有一個已完成(從瀏覽器/最終用戶角度來看)的 14.8GB 上傳,該上傳掛在大約 2GB 的 tmp 檔案傳輸上。
在 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的虛擬主機設定:
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,第二個範例停在 3264364 KB。行為差異的原因對我來說沒有意義,但值得報告。
更新2:我已經能夠明確地確定這是tmp
nginx 和 php 之間文件切換的問題,但我似乎無法確定導致進程掛起的具體原因。
tmp
我們可以透過將這些行新增至 nginx 設定來跳過 nginx 代理程式並僅使用 PHP :
proxy_buffering off;
proxy_request_buffering off;
透過此配置,檔案直接進入/mnt/tmp/php<RND_STR>
,上傳完成後,我們的應用程式會正確地取出檔案tmp
並完成其任務。
但是,這會將上傳速度減慢到可用頻寬的大約 1/3,因此這不是一個好的解決方案。然而,它確實證明這不是應用程式問題。
所以這就是正在發生的事情:
- 用戶上傳一個大檔案(50GB 是我們的用例最大值)
- 檔案
tmp
完整到達nginx位置 - 嘗試將檔案從 nginx 複製
tmp
到 PHPtmp
- 複製過程將在幾秒鐘內在不可預測的地方停止,但在 3GB 到 10GB 之間。 [3b] 此時,我們可以看到兩個tmp
文件,並且 PHPtmp
文件包含的位元組數應該會不斷增長,直到等於 nginxtmp
文件的大小,但事實並非如此。這兩個檔案將完全保持原樣,直到達到 600 秒逾時之一(見上文),然後日誌檔案中會出現錯誤,並且這兩個tmp
檔案都會消失。 [3c] 如果檔案小於 3GB,則每次都可以工作。如果檔案超過 3GB,有時可以工作,但其他時候則不行 - 檔案越小,工作的可能性就越大。 - 繞過 nginx 的
tmp
工作完全符合預期,只是上傳速度很慢。
當檔案非常大時,在 nginx 和 PHP 之間的檔案切換過程中肯定會出現一些問題tmp
,我很想弄清楚它是什麼。