【Nginx】圖片顯示過慢,檔案下載不完全,竟然是Nginx的鍋!!

冰河團隊發表於2020-07-21

寫在前面

最近,一名讀者跟我說他通過瀏覽器訪問自己的伺服器時,圖片顯示的非常慢,以至於在瀏覽器中都無法完全載入出來,下載檔案時,更是惱火,檔案根本就無法完全下載下來。而且奇怪的是這位讀者所在的網路是沒啥問題的。於是,我便開始幫他排查各種問題。。。

問題定位

經過一系列的排查(中間過程我就省略了,直接寫重點了!),最終定位到是Nginx的問題。當我開啟這位讀者的網站後臺管理系統,發現圖片顯示非常慢,在Nginx前端代理上查出如下錯誤資訊。

[error] 28423#0: *5 connect() failed (111: Connection refused) while connecting to upstream

直接在後臺伺服器上用後臺伺服器的IP地址去訪問,發現速度相當快,於是懷疑是Nginx的配置問題。

注意:當下載大的附件,或是頁面中有大圖片時,就會下載中斷或是圖片無法顯示,也許你會說我用的Nginx預設的配置也從來沒有碰到過這種問題呀!我想說的是:那是因為你的網站沒有大檔案,至少沒有大到使用Nginx的預設配置載入不出來。

這裡,我給出一段Nginx的配置,如下所示。

location /file {
	 root /home/file;
	 index  index.html index.htm;
	 proxy_set_header X-Real-IP $remote_addr;
	 proxy_set_header   Host $host;
	 proxy_pass http://127.0.0.1:8080 ;
	 client_max_body_size     100m;
	 client_body_buffer_size  128k;
	 proxy_connect_timeout    600;
	 proxy_read_timeout       600;
	 proxy_send_timeout       600;
	 proxy_buffer_size        32k;
	 proxy_buffers          4 64k;
	 proxy_busy_buffers_size 64k;
	 proxy_temp_file_write_size 64k;
}

其中幾個重要的引數如下所示。

  • proxy_connect_timeout 600; #nginx跟後端伺服器連線超時時間(代理連線超時)
  • proxy_read_timeout 600; #連線成功後,後端伺服器響應時間(代理接收超時)
  • proxy_send_timeout 600; #後端伺服器資料回傳時間(代理髮送超時)
  • proxy_buffer_size 32k; #設定代理伺服器(nginx)儲存使用者頭資訊的緩衝區大小
  • proxy_buffers 4 32k; #proxy_buffers緩衝區,網頁平均在32k以下的話,這樣設定
  • proxy_busy_buffers_size 64k; #高負荷下緩衝大小(proxy_buffers*2)
  • proxy_temp_file_write_size 16k; #設定快取資料夾大小,大於這個值,將從upstream伺服器傳

看到這裡,發現問題了,這位讀者的Nginx有下面一行配置。

proxy_temp_file_write_size 16k;

而他伺服器上的圖片基本都在100K~5M之間。

問題就出在proxy_temp_file_write_size上,當伺服器上的檔案超過該引數設定的大小時,Nginx會先將檔案寫入臨時目錄(預設為Nginx安裝目下/proxy_temp目錄),預設Nginx是以nobody身份啟動的,用ls -al 命令檢視proxy_temp目錄 nobody是proxy_temp目錄的所有者,怪了那為什麼沒許可權呢?接下來檢視proxy_temp的父目錄既Nginx安裝目錄。發現nobody競然沒許可權,怪不得會出現上面的問題。

解決問題

定位到問題,接下來解決問題就比較簡單了。可以使用兩種方式解決這個問題,如下所示。

  • 設定任何人都可以寫 proxy_temp目錄,重啟 Nginx 即可解決。
  • 直接更改proxy_temp_file_write_size的值,將其修改為大於圖片和檔案的大小,重啟Nginx。

如果是以第一種方式解決問題的話,比如我的proxy_temp目錄是/usr/local/nginx/proxy_temp,用如下命令將/usr/local/nginx/proxy_temp目錄設定為任何人都可以寫,問題解決。

chmod -R 777 /usr/local/nginx/proxy_temp/ 

如果是使用第二種方式解決問題的話,就可以直接修改nginx.conf檔案,如下所示。

location /file {
	 root /home/file;
	 index  index.html index.htm;
	 proxy_set_header X-Real-IP $remote_addr;
	 proxy_set_header   Host $host;
	 proxy_pass http://127.0.0.1:8080 ;
	 client_max_body_size     100m;
	 client_body_buffer_size  256k;
	 proxy_connect_timeout    1200;
	 proxy_read_timeout       1200;
	 proxy_send_timeout       6000;
	 proxy_buffer_size        32k;
	 proxy_buffers            4 64k;
	 proxy_busy_buffers_size  128k;
	 proxy_temp_file_write_size 10m;
}

當然,我也幫這位讀者優化了一些其他的配置項。

好了,今天就聊到這兒吧!別忘了點個贊,給個在看和轉發,讓更多的人看到,一起學習,一起進步!!

寫在最後

如果你覺得冰河寫的還不錯,請微信搜尋並關注「 冰河技術 」微信公眾號,跟冰河學習高併發、分散式、微服務、大資料、網際網路和雲原生技術,「 冰河技術 」微信公眾號更新了大量技術專題,每一篇技術文章乾貨滿滿!不少讀者已經通過閱讀「 冰河技術 」微信公眾號文章,吊打面試官,成功跳槽到大廠;也有不少讀者實現了技術上的飛躍,成為公司的技術骨幹!如果你也想像他們一樣提升自己的能力,實現技術能力的飛躍,進大廠,升職加薪,那就關注「 冰河技術 」微信公眾號吧,每天更新超硬核技術乾貨,讓你對如何提升技術能力不再迷茫!

相關文章