[譯]如何配置Nginx

Goldbeener發表於2019-04-21

image

原文地址: How to Configure NGINX

Nginx是一個輕量的、高效能、專為高併發設計的web伺服器。

Nginx一個鮮明的特點就是,能夠高效的處理諸如HTML之類的媒體檔案。Nginx採用非同步事件驅動模型,以提供高負載下的可預測效能。

動態內容經過Nginx透傳給CGI、FastCGI或者其他的諸如Apache的web伺服器,然後這些內容又返回給Nginx以分發給客戶端。本文將使你熟悉基本的Nginx引數配置和規定。

指令(Directives)&塊(Blocks)&上下文(Contexts)

所有的Nginx配置檔案都位於/etc/nginx目錄下,基本的也是最主要的配置檔案是/etc/nginx/nginx.conf

Nginx的配置項也被稱之為指令。指令集合就是常說的或者上下文, 兩者是相同的。

以字元#開頭的行是註釋行,不會被Nginx所解析。指令行必須以分號;結尾,否則Nginx無法正確的載入配置檔案,並丟擲錯誤。

以下擷取自安裝nginx時自帶的配置檔案/etc/nginx/nginx.conf。該檔案開頭有四個指令: user,worker_processes,error_log, pid。它們沒有包含在任何指令塊內,因此我們稱之為存在於主指令塊內。eventshttp指令塊是額外的指令配置塊,它們也存在於主指令塊內。

你可以參考nginx官方配置檔案來了解這些指令的含義,以及主指令塊內的其他配置引數。

    user   nginx;
    worker_processes   1;
    
    error_log    /var/log/nginx/error.log warn;
    pid          /var/run/nginx.pid
    
    
    events {
        ...
    }
    
    http {
        ...
    }
    
複製程式碼

http配置塊

http配置塊內包含著處理web通訊的指令,這些指令通常被成為通用指令,因為這些指令作用於所有nginx代理的站點服務。 可以查閱nginx官方配置檔案來了解http配置塊內的所有指令

    http {
        include     /etc/nginx/mime.type;
        default_type        application/octet-stream;
        
        log_format  main    '$remote_addr - $remote-user [$time_local] "$request" '
                            '$status $body_bytes_sent "$http_referer"'
                            '"$http_user_agent" "$http_x_forwarded_for"';
                            
                            
        access_log      /var/log/nginx/access.log   main;
        
        sendfile        on;
        #tcp_nopush     on;
        
        keepalive_timeout       65;
        
        #gzip   on;
        
        include     /etc/nginx/conf.d/*.conf;
        
    }
複製程式碼

Server配置塊

上面的http配置塊包含了一個include指令,它是用來告訴nginx站點的配置檔案的位置

  • 如果你是用官方的nginx包安裝的,那麼會是像上面的那樣include /etc/nginx/conf.d/*.conf。 用nginx代理的每個站點都應該在目錄/etc/nginx/conf.d下有自己的配置檔案, 並且使用形如 example.com.conf的統一的命名規範。 沒有被nginx代理的站點的配置檔案應該被命名為example.com.conf.disabled
  • 如果你從Debian或者Ubuntu源上安裝的nginx,這條指令會是這樣的/etc/nginx/sites-enabled/*; sites-enabled資料夾下包含著站點配置檔案的連結,這些檔案儲存在/etc/nginx/sites-available/檔案下。 可以通過移除連結的方式達到禁用站點代理的目的。
  • 根據你的安裝源,可以在/etc/nginx/conf.d/default.conf或者etc/nginx/sites-enabled/default 路徑下找到預設的nginx配置例子

無論是何種安裝源,每個站點的配置檔案都會包含一個server配置塊,例如:

    # /etc/nginx/conf.d/example.com.conf
    
    server {
        listen          80 default_server;
        listen          [::]:80 default_server;
        server_name     example.com www.example.com;
        root            /var/www/example.com;
        index           index.html;
        try_files $uri /index.html;
    }
複製程式碼

監聽埠

listen 指令告訴nginx應該監聽的http連結的主機名/IP/埠號。 default_server引數意味著,哪些80埠上的、不符合其他特定的監聽宣告的請求也會被該虛擬主機處理。第二個listen指令是基於IPv6的,行為與上一個IPv4一致.

命名的虛擬主機

server_name指令,允許一個IP地址代理多個域名,nginx代理伺服器會根據收到的請求頭來決定將請求轉發給哪個域名。

你應該為代理的每個域名建立一個單獨的配置檔案,下面是對應的一些例子:

  1. 處理來自example.comwww.example.com的請求
# /etc/nginx/conf.d/example.com.conf

server_name     example.com www.example.com;
複製程式碼
  1. server_name指令的值也可以是萬用字元**.example.com.example.com這兩個指令都是指示nginx處理來自二級域名example.com下的所有請求
server_name     *.example.com;
server_name     .example.com;
複製程式碼
  1. 處理所有以example開頭的域名下的請求
server_name     example.*;
複製程式碼

Nginx還允許server_name的值是自定義的、無效的域名,它只管根據HTTP請求頭中的域名來響應請求,不會去關注該域名是否是有效的。

這種特性在區域網中是非常有用的,或者是你已經知道所有的可能發起請求的客戶端。比如,前端常用的,在hosts檔案中配置的ip-域名對,nginx都可以監聽、處理。

Location路由配置塊

Location配置的是,Nginx如何響應請求的資源。該指令把請求抽象為特定的檔案或資料夾,就像server_name指令指示Nginx如何處理代理域名下的請求一樣, 比如http://example.com/blog/, 下面是一些例子:

location / { }
location /images/ { }
location /blog/ { } 
location /planet/ { }
location /planet/blog/ { } 
複製程式碼

上述是路由字串匹配,匹配的目標是,http請求中域名之後的所有路徑:

請求: Http://example.com/

響應: 假設已經配置了主機 server_name example.com, location /該指令將決定該請求的響應是什麼。

Nginx總是會用最精確的路由匹配來處理請求:

請求: 例如有這兩個請求http://example.com/planet/blog/ & http://example.com/planet/blog/about/

響應: 在上面的路由匹配中,最終會使用location /planet/blog/ { }路由下的配置處理,即使location /planet/ { }該路由也是匹配的,但是因為前者是更精確的,所以會使用前者而不是後者。

location ~ IndexPage\.php$ { }
location ~ ^/BlogPlanet(/|/index\.php)$ { }
複製程式碼

location指令後面緊跟著一個波浪號, 表示該路由匹配是正則匹配,並且是區分大小寫的。 因此IndexPage.php是能夠符合上述的第一個例子的,但是indexpage.php是不行的。在第二個例子中,正規表示式^/BlogPlanet(/|index\.php)$會匹配,諸如/BlogPlanet//BlogPlanet/index.php這樣的請求,但是不會匹配到/BlogPlanet, /blogplanet/或者 /blogplanet/index.php這樣的請求,因為大小寫不符合。

Nginx的正則匹配規則是遵循PCRE(Perl Compatible Regular Expression)的。

location ~* \.(pl|cgi|perl|prl)$ { }
location ~* \.(md|mdwn|txt|mkdn)$ { }
複製程式碼

如果你想使匹配規則對大小寫不敏感,那麼在~後面新增一個*. 上述的例子是指定nginx如何處理以副檔名結尾的請求。 在第一個例子中,所有以.pl, .PL, .cgi, .CGI, .perl, .Perl, .prl, 和.PrL結尾的檔案請求,都是滿足匹配規則的.

location ^~ /images/IndexPage/ { }
location ^~ /blog/BlogPlanet/ { }
複製程式碼

location指令後面跟著 ^~組合,意味著,如果匹配到特定的字串,就直接停止尋找更精確的路由匹配項,直接使用當前的路由配置。除此之外,與字串匹配規則一樣。如果一個請求符合該指令,那麼不論後面是否有更精確的匹配項,直接使用此處的配置規則。關於匹配的順序以及優先順序,後文會有更詳細的介紹。

location = / { }
複製程式碼

最後,如果你在location後面新增了一個等號=, 意味著這是一個精準的匹配,請求路徑必須嚴格等於路由項,才會停止匹配查詢。舉個例子:最後的例子會匹配到http://example.com/, 而不會匹配http://example.com/index.html, 使用精準匹配可以輕微的提升響應速度,在某個請求需要頻繁的被呼叫的場景下是非常有用的。

該指令的處理順序如下:

  1. 精準匹配路由是最先被處理的,如果發現符合條件的,Nginx會停止匹配搜尋,直接處理請求
  2. 字串匹配是第二優先處理的,如果遇到^~匹配項,nginx會停止匹配,直接處理。否則,會持續匹配搜尋直到找到最合適的匹配項
  3. 正則匹配項(~~*)是第三優先處理的,如果遇到符合條件的,停止搜尋,處理請求
  4. 如果前三步都沒有匹配到,那麼將會使用最通配的字串匹配

確保代理域名下的每個檔案、資料夾至少能夠匹配一個location指令

注意:
不建議也不支援巢狀的location配置塊

路由的根路徑和入口檔案

location也是一個塊指令,裡面可以配置相關的指令

一旦Nginx匹配到了一個請求的最佳匹配路由,該請求的響應就會被相關location內的指令處理。例如:

location / {
    root html;
    index index.html index.htm;
}
複製程式碼

本例中,檔案的根路徑會被定位在html/目錄下,在預設的nginx配置檔案中,例子中的完整檔案路徑是/etc/nginx/html/

請求: http://example.com/blog/includes/style.css

響應: nginx會嘗試在/etc/nginx/html/blog/includes/style.css路徑下尋找目標檔案

注意:
如果需要的話,root的值也可以使用絕對路徑

index指令是告訴nginx,如果沒有在目標路徑找到目標檔案,那麼使用index指令的值代表的檔案作為返回值。 例如:

請求: http://example.com

響應: nginx沒有找到合適的匹配項,就會返回/etc/nginx/html/index.html檔案

如果index指令的值有多個,nginx會按順序尋找檔案,直到發現第一個存在的,以此作為響應。如果在相關的資料夾下index.html不存在,會尋找index.htm, 如果依然不存在,就會返回404.

下面是一個稍微複雜的例子,展示了一個代理example.com域名的服務上的一系列location配置

location / {
    root   /srv/www/example.com/public_html;
    index  index.html index.htm;
}

location ~ \.pl$ {
    gzip off;
    include /etc/nginx/fastcgi_params;
    fastcgi_pass unix:/var/run/fcgiwrap.socket;
    fastcgi_index index.pl;
    fastcgi_param SCRIPT_FILENAME /srv/www/example.com/public_html$fastcgi_script_name;
}
複製程式碼

在這個例子中,所有獲取以.pl為副檔名的資源的請求,都會被第二個location塊處理, 在該指令塊裡定義了一個fastcgi回撥來處理所有的請求。其他的請求則是由第一個指令塊處理。 資源的請求被分發在檔案系統中的/srv/www/example.com/public_html/路徑下,如果請求的目標檔案不存在,nginx會尋找index.htmlindex.htm代替,如果這兩個檔案也不存在,就會返回404.

我們來分析一下下面的幾個例子:

請求: http://example.com

響應: 該請求會被第一個location匹配

  1. /srv/www/example.com/public_html/index.html 路徑下的檔案,有的話直接返回,沒有走第二步
  2. /srv/www/example.com/public_html/index.htm路徑下的檔案,有的話返回,沒有的話走第三步
  3. 返回404錯誤

請求: http://example.com/blog/
響應: 該請求會被第一個location匹配,請求路徑裡面有指出資源路徑,因此拼接root路徑

  1. /srv/www/example.com/public_html/blog/index.html 路徑下的檔案,有的話直接返回,沒有走第二步
  2. /srv/www/example.com/public_html/blog/index.htm路徑下的檔案,有的話返回,沒有的話走第三步
  3. 返回404錯誤

請求: http://example.com/tasks.pl
響應: 請求的資源是以.pl結尾的,會被第二個location匹配,資源名稱是tasks.pl,拼接上root路徑 nginx會尋找/srv/www/example.com/public_html/tasks.pl 路徑下的檔案,然後用指定的FASTCGI回撥處理該檔案,然後把結果作為響應返回

請求: http://example.com/username/roster.pl
響應: 請求的資源是以.pl結尾的,會被第二個location匹配,資源名稱是roster.pl,路徑是username, 拼接上root路徑 nginx會尋找/srv/www/example.com/public_html/username/roster.pl 路徑下的檔案,然後用指定的FASTCGI回撥處理該檔案,然後把結果作為響應返回

總結(譯者)

  • nginx location 指令是取請求uri,與location指令後面緊跟的字串正規表示式做比較,選擇匹配度最高的location塊,用其中定義的指令處理請求。
  • root指令調整了資源的定址路徑,nginx會按照root + uri的路徑來尋找請求資源
  • 如果uri沒有明確指定資源名(具體的檔名),那麼nginx會讀取index指令的值作為預設返回值, 如果沒有的話返回404

好文推薦

快狗叫車前端團隊博文前端想要了解的Nginx

相關文章