Nginx組態靜態內容伺服器


本節介紹如何使用NGINX來提供靜態內容服務,定義搜尋路徑以查詢請求的檔案的方法,以及如何設定索引檔案。

在這個部分,我們主要涉及以下幾個方面的內容:

  • 根目錄和索引檔案
  • 嘗試幾個選項
  • 優化NGINX服務內容的速度

1. 根目錄和索引檔案

root指令指定將用於搜尋檔案的根目錄。 要獲取請求檔案的路徑,NGINX將請求URI附加到root指令指定的路徑。 該指令可以放置在httpserverlocation上下文中的任何級別上。 在下面的範例中,為虛擬伺服器定義了root指令。 它適用於不包括root指令的所有location塊以顯式重新定義根:

server {
    root /www/data;

    location / {
    }

    location /images/ {
    }

    location ~ \.(mp3|mp4) {
        root /www/media;
    }
}

這裡,NGINX在檔案系統的/www/data/images/目錄中搜尋以/images/開頭的URI。 但是,如果URI以.mp3.mp4擴充套件名結尾,則NGINX會在/www/media/目錄中搜尋.mp3.mp4檔案,因為它在匹配的location塊中定義。

如果請求以斜槓結尾,則NGINX將其視為對目錄的請求,並嘗試在目錄中找到索引檔案。index指令定義索引檔案的名稱(預設值為index.html)。繼續範例,如果請求URI為/images/some/path/,則NGINX會傳遞檔案/www/data/images/some/path/index.html(如果存在)。 如果不存在檔案,NGINX預設返回HTTP程式碼404(未找到)。 要組態NGINX以返回自動生成的目錄列表,請將on引數新增到autoindex指令中:

location /images/ {
    autoindex on;
}

可以在索引指令中列出多個檔案名。 NGINX以指定的順序搜尋檔案,並返回它找到的第一個檔案。

location / {
    index index.$geo.html index.html index.html;
}

這裡使用的$geo變數是通過geo指令設定的自定義變數。 變數的值取決於用戶端的IP地址。
要返回索引檔案,NGINX檢查其是否存在,然後通過將索引檔案的名稱附加到基本URI來對通過URI獲取的內部重定向。內部重定向會導致對某個位置(location)的新搜尋,並且可能會在另一個位置(location)中結束,如以下範例所示:

location / {
    root /data;
    index index.html index.php;
}

location ~ \.php {
    fastcgi_pass localhost:8000;
    ...
}

在這裡,如果請求中的URI是/path/,並且/data/path/index.html不存在,但是/data/path/index.php存在,則將/path/index.php 內部重定向對映到第二個位置(location)。 因此,請求被代理。

2. 嘗試幾個選項

try_files指令可用於檢查指定的檔案或目錄是否存在並進行內部重定向,如果沒有指定的檔案或目錄,則返回特定的狀態程式碼。 例如,要檢查與請求URI相對應的檔案的存在,請使用try_files指令和$uri變數,如下所示:

server {
    root /www/data;

    location /images/ {
        try_files $uri /images/default.gif;
    }
}

該檔案以URI的形式指定,它使用在當前位置或虛擬伺服器的上下文中設定的 rootalias 偽指令進行處理。 在這種情況下,如果與原始URI相對應的檔案不存在,則NGINX將內部重定向到最後一個引數中指定的URI,也就是返回/www/data/images/default.gif

最後一個引數也可以是一個狀態程式碼(直接在前面的等號)或位置的名稱。 在以下範例中,如果try_files指令的任何引數都不會解析為現有檔案或目錄,則會返回404錯誤。

location / {
    try_files $uri $uri/ $uri.html =404;
}

在下一個範例中,如果原始URI和帶有附加尾部斜線的URI都不能解析為現有檔案或目錄,則將請求重定向到將其傳遞給代理伺服器的命名位置(location)。

location / {
    try_files $uri $uri/ @backend;
}

location @backend {
    proxy_pass http://backend.example.com;
}

3. 優化NGINX服務內容的速度

載入速度是服務任何內容的關鍵因素。 對您的NGINX組態進行小幅優化可能會提高生產力並幫助實現最佳效能。

啟用sendfile

預設情況下,NGINX會自動處理檔案傳輸,並在傳送檔案之前將其複製到緩衝區中。 啟用sendfile指令將消除將資料複製到緩衝區中的步驟,並允許將資料從一個檔案描述符直接複製到另一個檔案描述符。 或者,為了防止一個快速連線完全占用工作進程,您可以通過定義sendfile_max_chunk指令來限制在單個sendfile()呼叫中傳輸的資料量:

location /mp3 {
    sendfile           on;
    sendfile_max_chunk 1m;
    ...
}

啟用tcp_nopush

tcp_nopush選項與sendfile一起使用。 該選項將使NGINX能夠通過sendfile獲取資料塊之後,在一個資料包中傳送HTTP響應頭

location /mp3 {
    sendfile   on;
    tcp_nopush on;
    ...
}

啟用tcp_nodelay

tcp_nodelay選項可以覆蓋Nagle的演算法,最初是為了解決慢網路中的小資料包問題而設計的。 該演算法將大量小資料包整合到較大的資料包中,並以200 ms的延遲傳送資料包。
如今,當服務大型靜態檔案時,無論資料包大小如何,都可以立即傳送資料。 延遲也會影響線上應用程式(ssh,線上遊戲,網上交易)。 預設情況下,tcp_nodelay指令設定為on,表示Nagle的演算法被禁用。 該選項僅用於Keepalive連線:

location /mp3  {
    tcp_nodelay       on;
    keepalive_timeout 65;
    ...
}

優化積壓佇列

其中一個重要因素是NGINX可以處理傳入連線的速度。 一般規則是建立連線時,將其放入監聽通訊端的「偵聽」佇列中。 在正常負載下,有一個低佇列,或根本沒有佇列。 但是在高負載下,佇列可能會急劇增長,這可能會導致效能不均衡,連線丟失和延遲。

測量偵聽佇列

讓我們來檢視當前的偵聽佇列。 執行命令:

netstat -Lan

命令輸出可能如下所示:

Current listen queue sizes (qlen/incqlen/maxqlen)
Listen         Local Address         
0/0/128        *.12345            
10/0/128        *.80       
0/0/128        *.8080

命令輸出顯示埠80的監聽佇列中有10個不接受的連線,而連線限制為128個連線,這種情況是正常的。
但是,命令輸出可能如下所示:

Current listen queue sizes (qlen/incqlen/maxqlen)
Listen         Local Address         
0/0/128        *.12345            
192/0/128        *.80       
0/0/128        *.8080

命令輸出顯示超過128個連線限制的192個不可接受的連線。 當網站的流量很大時,這是很常見的。 為了達到最佳效能,您需要增加NGINX在作業系統和NGINX組態中排隊等待接收的最大連線數。

調整作業系統
net.core.somaxconn鍵的值從其預設值(128)增加到足夠高的值以能夠處理高突發流量:

對於FreeBSD,執行命令:

sudo sysctl kern.ipc.somaxconn=4096

對於FreeBSD,執行命令:

sudo sysctl -w net.core.somaxconn=4096

開啟檔案:/etc/sysctl.conf,將下面一行新增到檔案並儲存檔案:

net.core.somaxconn = 4096

調整NGINX

如果將somaxconn鍵設定為大於512的值,請更改NGINX listen指令的backlog引數以匹配:

server {
    listen 80 backlog 4096;
    # The rest of server configuration
}