線上運營培訓seo每日一帖
Nginx學習:FastCGI模塊(三)緩沖區(qū)與響應頭
緩存相關(guān)的內(nèi)容占了 FastCGI 模塊將近一小半的內(nèi)容,當然,用過的人可能不多。而今天的內(nèi)容說實話,我平常也沒怎么用過。第一個是緩沖區(qū)相關(guān)的知識,其實和我們之前學習過的 client_body_buffer_size 有點類似,但它是針對后端動態(tài)程序的響應緩沖區(qū)來說的。另一個也是響應有關(guān)的,主要是響應頭相關(guān)的一些配置。
今天學習的內(nèi)容都是可以設(shè)置在 http、server、location 中的,有特殊情況的我會單獨說。
FastCGI緩沖區(qū)配置
就像開頭所說的,它和 client_body_buffer_size 的概念是類似的,只不過針對的是后端程序的響應緩沖。什么意思呢?其實就是將響應保存在內(nèi)存中,如果內(nèi)容太多,就會保存到一個臨時文件里。
fastcgi_buffering
啟用或禁用來自 FastCGI 服務器的響應緩沖。
fastcgi_buffering?on?|?off;
啟用緩沖后,Nginx 會盡快收到來自 FastCGI 服務器的響應,并將其保存到由 fastcgi_buffer_size 和 fastcgi_buffers 指令設(shè)置的緩沖區(qū)中。如果整個響應不適合內(nèi)存,可以將其中的一部分保存到磁盤上的臨時文件中。寫入臨時文件由 fastcgi_max_temp_file_size 和 fastcgi_temp_file_write_size 指令控制。
當緩沖被禁用時,響應會在收到時立即同步傳遞給客戶端。 Nginx 不會嘗試從 FastCGI 服務器讀取整個響應。 Nginx 一次可以從服務器接收的最大數(shù)據(jù)大小由 fastcgi_buffer_size 指令設(shè)置。
也可以通過在“X-Accel-Buffering”響應頭字段中傳遞“yes”或“no”來啟用或禁用緩沖??梢允褂?fastcgi_ignore_headers 指令禁用此功能。
它的默認值就是開啟的,用于控制整個 FastCGI 的緩沖區(qū)控制,上面已經(jīng)說明了關(guān)閉會發(fā)生什么情況。提到的配置指令我們馬上一一學習,最后再將所有配置指令合在一起進行一個簡單的測試。
fastcgi_buffer_size
設(shè)置用于讀取從 FastCGI 服務器接收到的響應的第一部分的緩沖區(qū)大小。
fastcgi_buffer_size?size;
這部分通常包含一個小的響應頭。默認情況下,緩沖區(qū)大小等于一個內(nèi)存頁,這是 4K 或 8K,具體取決于平臺。然而,它可以做得更小。它和 client_header_buffer_size 這類的配置指令是類似的,就相當于是 FastCGI 版本的。
fastcgi_buffers
為單個連接設(shè)置用于從 FastCGI 服務器讀取響應的緩沖區(qū)的數(shù)量和大小。
fastcgi_buffers?8?4k|8k;
默認情況下,緩沖區(qū)大小等于一內(nèi)存頁。這是 4K 或 8K,具體取決于平臺。這個配置項是創(chuàng)建幾個緩沖區(qū)用的,比如設(shè)置成 8 4k ,表示的就是 8*4=32k 的緩沖區(qū),而上面的 fastcgi_buffer_size 是第一個頭緩沖區(qū)的大小,不包含在這邊,因此,整個緩沖區(qū)的大小就是 8*4k+fastcgi_buffer_size 的結(jié)果。它和 client_header_buffer_size 類似,可以看成是主要的響應體的大小。
fastcgi_busy_buffers_size
當啟用來自 FastCGI 服務器的響應緩沖時,限制在響應尚未完全讀取時可能正忙于向客戶端發(fā)送響應的緩沖區(qū)的總大小。
fastcgi_busy_buffers_size?size;
默認值是 8 或 16 K,其余緩沖區(qū)可用于讀取響應,并在需要時將部分響應緩沖到臨時文件。默認情況下,大小受 fastcgi_buffer_size 和 fastcgi_buffers 指令設(shè)置的兩個緩沖區(qū)的大小限制。
fastcgi_max_temp_file_size
該指令設(shè)置臨時文件的最大大小。
fastcgi_max_temp_file_size?size;
默認值是 1024m ,零值表示禁用對臨時文件的響應的緩沖。如果啟用了來自 FastCGI 服務器的響應緩沖,并且整個響應不適合由 fastcgi_buffer_size 和 fastcgi_buffers 指令設(shè)置的緩沖區(qū),則可以將部分響應保存到臨時文件中。一次寫入臨時文件的數(shù)據(jù)大小由 fastcgi_temp_file_write_size 指令設(shè)置。此限制不適用于將緩存或存儲在磁盤上的響應。
fastcgi_temp_file_write_size
當啟用從 FastCGI 服務器到臨時文件的響應緩沖時,限制一次寫入臨時文件的數(shù)據(jù)大小。
fastcgi_temp_file_write_size?size;
默認情況下,大小受 fastcgi_buffer_size 和 fastcgi_buffers 指令設(shè)置的兩個緩沖區(qū)限制。臨時文件的最大大小由 fastcgi_max_temp_file_size 指令設(shè)置。
fastcgi_temp_path
定義一個目錄,用于存儲帶有從 FastCGI 服務器接收到的數(shù)據(jù)的臨時文件。
fastcgi_temp_path?path?[level1?[level2?[level3]]];
默認值是 Nginx 運行目錄下的 fasstcgi_temp 目錄,整體和之前學過的 client_body_temp_path 是類似的,在指定目錄下最多可以使用三級子目錄層次結(jié)構(gòu)。例如,在以下配置中:
fastcgi_temp_path?/spool/nginx/fastcgi_temp?1?2;
臨時文件可能存儲的目錄就是:
/spool/nginx/fastcgi_temp/7/45/00000123457
前面我們學習的 FastCGI 緩存相關(guān)的配置中,緩存臨時文件配置項 fastcgi_cache_path 有個參數(shù) use_temp_path 和這個配置項有關(guān)系,之前我們已經(jīng)學習過了。
綜合測試
新建一個配置,注意要用非正則針對指定目錄的配置,要不然會被我們最開始的那個?location ~ \.php
給搶走,因為它那邊指定了 php 結(jié)尾,優(yōu)先級比直接指定目錄要高,只需要加上?^~
?就好了,之前在 location 中已經(jīng)詳細講解過了。
location?^~?/fastcgi1/?{root?html;fastcgi_pass?unix:/var/sock/php-fpm/www.sock;fastcgi_index??index.php;fastcgi_param??SCRIPT_FILENAME??$document_root$fastcgi_script_name;include????????fastcgi_params;fastcgi_buffer_size?100;fastcgi_buffers?2?100;fastcgi_busy_buffers_size?100;fastcgi_temp_file_write_size?100;fastcgi_temp_path?/root/fastcgi_temp_test?1?2;
}
都設(shè)置得很小是吧,但是我們要準備的 PHP 文件需要返回的響應還是要設(shè)置的很大,否則很難看出效果。
//?1.php
<?php
$c?=?$_GET['c']????2000;
for?($i=$c;$i>0;$i--){print_r($_SERVER);
}
照理說,我們設(shè)置的都只是 100 字節(jié),但實際循環(huán) 2000 次返回的響應有 2M 了,這時才能看到指定的 fastcgi_temp_path 文件夾產(chǎn)生了變動,里面也會生成子目錄。這一塊確實不太理解,設(shè)置成 1600 次循環(huán),達不到 2M 的響應,就不會產(chǎn)生臨時文件。去掉 fastcgi_temp_file_write_size 的配置之后,2M 的響應也不會產(chǎn)生文件。
這一塊比較難測,而且出來的效果說實話和我們想像的也不太一樣。所以如果有大佬知道這是什么情況,歡迎評論留言哈。將來如果有學習或者接觸到類似的問題,也會再單獨寫文章說說。
另外,上面的數(shù)值大家可以亂調(diào)一下試試,這幾個配置之間有各種限制,比如:
nginx:?[emerg]?"fastcgi_temp_file_write_size"?must?be?equal?to?or?greater?than?the?maximum?of?the?value?of?"fastcgi_buffer_size"?and?one?of?the?"fastcgi_buffers"?in?/etc/nginx/nginx.conf:396nginx:?[emerg]?"fastcgi_busy_buffers_size"?must?be?less?than?the?size?of?all?"fastcgi_buffers"?minus?one?buffer?in?/etc/nginx/nginx.conf:396
這些看英文也都能猜到是啥意思了。即使通過檢查了,并且 reload 成功之后,請求時也可能會報這些錯。
2022/08/22?22:24:52?[crit]?1811#0:?*79?open()?"/root/fastcgi_temp_test/0000000001"?failed?(13:?Permission?denied)?while?reading?upstream,?client:?192.168.56.1,?server:?core.nginx.test,?request:?"GET?/fastcgi1/1.php?HTTP/1.1",?upstream:?"fastcgi://unix:/var/sock/php-fpm/www.sock:",?host:?"192.168.56.88"2022/08/22?22:20:33?[error]?1792#0:?*71?upstream?sent?too?big?header?while?reading?response?header?from?upstream,?client:?192.168.56.1,?server:?core.nginx.test,?request:?"GET?/fastcgi1/1.php?HTTP/1.1",?upstream:?"fastcgi://unix:/var/sock/php-fpm/www.sock:",?host:?"192.168.56.88"
第一個錯誤是指定的臨時文件夾,它的上級目錄的權(quán)限必須是 755 ,所有 Nginx 下面的文件夾目錄都有這個要求。第二個是 fastcgi_buffer_size 設(shè)置小了,我想極限測試,也就是設(shè)置成 1 ,結(jié)果就直接報錯了。這個和響應返回的頭的大小有關(guān),我這里測試是設(shè)置到 76 就可以了,不過為了統(tǒng)一,我就全部設(shè)置到 100 了。
響應頭處理
在 FastCGI 的處理中,HTTP 請求標頭字段作為參數(shù)傳遞給 FastCGI 服務器。在作為 FastCGI 服務器運行的應用程序和腳本中,這些參數(shù)通常作為環(huán)境變量提供。例如,“User-Agent”標頭字段作為 HTTP_USER_AGENT 參數(shù)傳遞。除了 HTTP 請求頭字段之外,還可以使用 fastcgi_param 指令傳遞任意參數(shù)。這些參數(shù)在 PHP 中都可以在?$_SERVER
?里面看到。
對于這些響應頭,Nginx 中也有一些字段進行處理,這里不僅是響應頭,請求頭部分的內(nèi)容也一起寫在這里了。
fastcgi_hide_header
默認情況下,nginx 不會從 FastCGI 服務器的響應中將頭字段“Status”和“X-Accel-...”傳遞給客戶端。
fastcgi_hide_header?field;
沒有默認值,也就是除了上面那些響應頭以外,其它響應頭都會進行傳遞,相反,如果需要允許傳遞字段,則可以使用 fastcgi_pass_header 指令。
我們在 PHP 文件中定義一個響應頭?header("oopp:111");
?,然后正常查看頁面,這個 oopp 會返回來,而添加了?fastcgi_hide_header oopp;
?之后,在瀏覽器上就看不到這個響應頭的信息了。
fastcgi_pass_header
允許將其他禁用的標頭字段從 FastCGI 服務器傳遞到客戶端。
fastcgi_pass_header?field;
可以指定在禁用列表中的響應頭返回,比如 “X-Accel-...” 這些的。具體有哪些可以看后面的 fastcgi_ignore_headers 配置。
比如我們之前測試過的 X-Accel-Expires 響應頭,在 PHP 中設(shè)置了,但是前端瀏覽器的響應頭中不會顯示,就可以用這個傳遞到前端瀏覽器上。
那么如果 fastcgi_hide_header 和 fastcgi_pass_header 同時設(shè)置一個響應頭字段呢?以先后順序為準,后設(shè)置的生效。
fastcgi_ignore_headers
忽略對來自 FastCGI 服務器的某些響應頭字段的處理。
fastcgi_ignore_headers?field?...;
以下字段可以忽略:“X-Accel-Redirect”、“X-Accel-Expires”、“X-Accel-Limit-Rate”(1.1.6)、“X-Accel-Buffering”(1.1.6) 、“X-Accel-Charset”(1.1.6)、“Expires”、“Cache-Control”、“Set-Cookie”(0.8.44)和“Vary”(1.7.7)。
如果未禁用,則處理這些標頭字段具有以下效果:
“X-Accel-Expires”、“Expires”、“Cache-Control”、“Set-Cookie”、“Vary”設(shè)置響應緩存的參數(shù)
“X-Accel-Redirect”執(zhí)行到指定 URI 的內(nèi)部重定向
“X-Accel-Limit-Rate”設(shè)置向客戶端傳輸響應的速率限制
“X-Accel-Buffering”啟用或禁用響應緩沖
“X-Accel-Charset”設(shè)置響應的所需字符集
默認值是空的,就是這些都會處理,假如設(shè)置一個 X-Accel-Expires ,那么我們之前在 PHP 中設(shè)置的 X-Accel-Expires 響應頭延長緩存時間的效果就不起作用了。
總結(jié)
緩沖區(qū)部分可能還是需要更深入的學習操作系統(tǒng)及網(wǎng)絡相關(guān)的知識才能夠解釋清楚,目前我的水平也就只能到這里了。測試代碼也是按自己的想法來進行測試的。另外一塊的響應頭部分比較簡單,大家可以自己測試一下哦。
參考文檔:
http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html