高效能Web伺服器Nginx的配置與部署研究(3)Nginx的請求處理機制

鍾超發表於2012-02-26

高效能Web伺服器Nginx的配置與部署研究(3)Nginx的請求處理機制

本文為您解讀,Nginx是如何處理請求的,讓你從邏輯上有一個清晰的認識。

1. 處理什麼樣的請求

處理訪問到 Nginx 所在 IP 地址的請求,並且這些請求的 HTTP 頭資訊中的 Host 為所要處理的域名(如下以80埠為例),如下幾個 server 就對應響應的請求:

server {
    listen       80;
    server_name  nginx.org  www.nginx.org;
    ...
}

server {
    listen       80;
    server_name  nginx.net  www.nginx.net;
    ...
}

server {
    listen       80;
    server_name  nginx.com  www.nginx.com;
    ...
}

2. 預設 server

如果不主動設定預設server,那麼第一個server就會被當做預設server。若要主動設定,應該如下配置:

server {
    listen       80  default_server;
    server_name  nginx.net  www.nginx.net;
    ...
}

此項的版本注意事項:

  • 0.8.21 版本之前,使用default關鍵詞;
  • 從 0.8.21 版本開始,使用default_server關鍵詞。

另外注意,default_server是埠的一個屬性,不是server_name的一個屬性。

3. 如何處理未定義 host 為 server_name 的請求

比如,如果不想處理 HTTP 請求中沒有 HOST 欄位的頭資訊的情況,那麼可以如下:

server {
    listen       80;
    server_name  "";
    return       444;
}

此項的版本注意事項:

  • 0.8.48 之前的版本,如果沒有設定server_name的話,那麼會把server_name設定為本機的 hostname。
  • 0.8.48 開始的版本,如果沒有設定server_name的話,那麼會把server_name設定為"",所以如果要達到上述程式碼的效果,在此版本開始可以不設定server_name

4. Nginx 的虛擬主機監聽

請先看如下配置:

server {
    listen       192.168.1.1:80;
    server_name  nginx.org  www.nginx.org;
    ...
}

server {
    listen       192.168.1.1:80;
    server_name  nginx.net  www.nginx.net;
    ...
}

server {
    listen       192.168.1.2:80;
    server_name  nginx.com  www.nginx.com;
    ...
}

這個應該很好理解,如果listen的 IP 地址和埠號都吻合了,就看 HTTP 請求中的 HOST 頭資訊與某個server_name中的 name 是否吻合。如果server_name不吻合,就到該埠對應的default_server那裡處理請求,如果default_serverserver_name也沒有與 HOST 頭資訊吻合,那麼就放棄該請求。

特別再次強調,default_server是埠的屬性,而非server_name的屬性。所以可以有如下配置:

server {
    listen        192.168.1.1:80;
    server_name   nginx.org  www.nginx.org;
    ...
}

server {
    listen        192.168.1.1:80  default_server;
    server_name   nginx.net  www.nginx.net;
    ...
}

server {
    listen        192.168.1.2:80  default_server;
    server_name   nginx.com  www.nginx.com;
    ...
}

5. 一個簡單的 PHP 站點的 Nginx 配置

server {
    listen        80;
    server_name   nginx.org  www.nginx.org;
    root          /data/www;

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

    location ~* \.(gif|jpg|png)$ {
        expires   30d;
    }

    location ~ \.php$ {
        fastcgi_pass   localhost:9000;
        fastcgi_param  SCRIPT_FILENAME
                       $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

Nginx 在匹配location的時候,不是按照配置程式碼給出的順序進行匹配的,而是先按照匹配表示式中的文字字串(literal string)的明確程度,從最明確的開始匹配。這麼說可能有點含混不清,簡單說,沒有正則規則的匹配表示式,是最明確的。比如如果這個匹配表示式就是一個“/”或者“/abc”,那麼這就是最明確的。上例中的"/"就是這個最明確的蚊子字串(the most specific literal string),其實也是該例中唯一的。所以先從這個location開始,然後再按照location的列出順序,依次匹配,直到出現第一個匹配的location後停止。如果所有的location都不匹配,就用第一個找到的最明確的文字字串來匹配(the most specific literal string)。

6. 待查詢的 HTTP 請求

Nginx只處理無查詢的HTTP請求,因為查詢請求的查詢欄位的順序不確定,比如:

/index.php?user=john&page=1
/index.php?page=1&user=john

再比如:

/index.php?page=1&something+else&user=john

7. 幾個location的例子

例1:

/logo.gif

“/”先被找到,然後匹配"\.(gif|jpg|png)$",再根據 redirective 找到root/data/www,然後這個請求就被對映到"/data/www/logo.gif"了,最後檔案就被髮送給到了客戶端。

例2:

/index.php

"/"先被找到,然後匹配"\.(php)$",然後 request 就被傳遞給在 9000 埠上監聽的 FastCGI 伺服器,"fastcgi_param" directive 設定 FastCGI 的引數SCRIPT_FILENAME"/data/www/index.php",然後FastCGI伺服器就執行這個檔案。(注意其中document_root/data/wwwfastcgi_script_name/index.php。)

例3:

/about.html

"/"先被找到,且只有這一個匹配的。然後根據root/data/www,就找到了檔案/data/www/about.html,然後傳送給客戶端。

例4:

/

"/"是很複雜的,先找到"/"這個location,然後根據root/data/www,看/data/www/index.php是否存在,如果存在 directive 就在內部重定向到/index.php,然後 Nginx 根據這個再次搜尋location,重複上面第二個例子。

-

更多 Nginx 技術博文請訪問 CSDN 專欄 《Nginx 高效能Web伺服器》

轉載請註明來自“柳大的CSDN部落格”: blog.CSDN.net/Poechant

-

相關文章