借鑒大佬的nginx反向代理下載文件失敗處理
https://www.cnblogs.com/breezey/p/6740229.html
最近遇到了客戶在從我們的服務器下載文件失敗時的情況。然后把解決方案一並整理一下以備后續。需要說明的是,我們前端都是使用nginx來做反向代理,后面的邏輯處理采用php的方式。
1、緩存目錄不可寫
nginx在做反向代理,代理后端的nginx+php-fpm時,在客戶端下載文件時,總是下載到一定的大小,就下載不動,查看后端服務器,表現正常,在繞過前端反向代理,直接從后端下載,也正常。檢查反向代理服務器日志,拋出如下異常:
- 復制代碼
2017/01/16 11:54:38 [warn] 3748#0: *61038342 an upstream response is buffered to a temporary file /usr/local/tengine/proxy_temp/5/03/0000000035 while reading upstream, client: 192.168.42.190, server: preview-qa.fdccloud.com, request: "GET /zip/033ca15a28b33298b46bc1e7eb2ea0f24cde16f9/%E9%99%84%E4%BB%B6%E9%97%AE%E9%A2%98/04%E6%98%8E%E6%BA%90%E7%A7%BB%E5%8A%A8V3.0%E4%BA%A7%E5%93%81%E5%8F%91%E5%B8%83%E5%85%AC%E5%91%8A-%E7%A7%BB%E5%8A%A8%E8%AE%A1%E5%88%92.pptx HTTP/1.1", upstream: "http://127.0.0.1:2016/zip/033ca15a28b33298b46bc1e7eb2ea0f24cde16f9/%E9%99%84%E4%BB%B6%E9%97%AE%E9%A2%98/04%E6%98%8E%E6%BA%90%E7%A7%BB%E5%8A%A8V3.0%E4%BA%A7%E5%93%81%E5%8F%91%E5%B8%83%E5%85%AC%E5%91%8A-%E7%A7%BB%E5%8A%A8%E8%AE%A1%E5%88%92.pptx", host: "preview-qa.fdccloud.com"
是因為/usr/local/tengine/proxy_temp目錄沒有權限,修改文件權限為nginx進程用戶以后,即正常。
原因分析:
nginx代理nginx時,前端用戶請求下載文件, nginx代理會先從后端nginx拿到文件並緩存到本地,然后響應給客戶端,其中與proxy buffer相關的配置項如下:
proxy_buffer_size 512k;
proxy_buffers 4 512k;
proxy_busy_buffers_size 512k;
proxy_temp_file_write_size 512k;
由此可知, buffer緩沖區最大可以緩沖2.5M的數據,然后就開始刷寫磁盤,如果磁盤無法寫入,數據丟失。這也是為什么前端下載部分數據,即下載不動的原因。
2、下載大文件超時
客戶端在下載大文件時,下載到1G時就會顯示“下載失敗”,FireFox中如果繼續下載,則還會再下載1G,然后再失敗。反向代理的錯誤日志如下:
2016/11/25 11:23:47 [error] 67663#0: *11 upstream prematurely closed connection while reading upstream, client: ...
被代理服務器的錯誤日志:
2016/11/24 23:33:02 [error] 5833#101125: *8559 upstream timed out (60: Operation timed out) while reading response header from upstream, client: ....
2.1 原因分析:
1)、代理服務器報告:上游過早的關閉連接,好像問題出在被代理服務器;而被代理服務器則抱怨:上游服務器超時。那么一個很合理的推論是:代理服務器很長時間沒向被代理服務器請求數據,被代理服務器認為代理服務器已經掉線或完成任務,於是主動斷開連接,代理服務器發現需要數據,再連接時,已經連接不上了。
2)、正常的流程應該是:只要客戶端一直下載,“客戶機->代理服務器->被代理服務器”,這一連串的數據流不會中斷,也就不會出現超時。
3)、出現超時只能有一種情況:代理服務器緩存了大文件。
4)、代理服務器接到下載請求,向被代理服務器請求數據,由於兩個服務器之間網速快,所以代理服務器請求速度要遠大於向客戶端發送的速度,這就導致一下正常的代理方式:代理服務器要緩存數據。
5)、但是兩個服務器之間的速度實在是太快了,緩存1G數據也就是分分鍾的事情,而客戶端需要慢慢下載,可能需要十幾、甚至幾十分鍾。代理服務器和被代理服務器這段時間內沒有什么事可干,與是兩端靜默的時間一長,超過了timeout的時間(一般是60s),被代理服務器就認為代理服務器掉線。
2.2 解決方案:
1)將代理服務器緩存設置更大,可以直接緩存整個文件,跟上面的解決一樣
2)禁用代理服務器緩存:
proxy_pass http://192.168.0.1;
proxy_redirect default;
proxy_buffering off;
3)設置更長的超時時間
proxy_send_timeout 90; #后端服務器數據回傳時間(代理發送超時)
proxy_read_timeout 90; #連接成功后,后端服務器響應時間(代理接收超時)