nginx 是如何處理訪問請求的

nginx 是如何處理訪問請求的
=========================

編譯自:
http://nginx.org/en/docs/http/request_processing.htmlphp


目錄:
    name-based 虛擬主機
    對於未定義 server name 的訪問請求,如何防止其被處理
    混合使用 name-based 虛擬主機和 IP-based 虛擬主機
    一個簡單的 PHP 站點配置示例
html

 

name-based 虛擬主機
-----------------------

當一個訪問請求到達 nginx,nginx 會考慮選擇某一個 server 處理訪問請求。
咱們以一個包含三個 server 區塊的配置來說解: nginx

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

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

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


這三個虛擬主機均監聽於 *:80 端口。根據上面的配置,nginx 僅經過檢查請求首部中的
「HOST」 字段來決定讓哪一個虛擬主機處理訪問請求。若是該字段的值沒有匹配任何虛擬主機,
或者請求首部中沒有 「HOST」 字段,nginx 會將該請求路由到 *:80 端口的默認 server。
在上面的配置中,默認 server 是第一個 server —— 這是 nginx 的標準默認行爲。
咱們也能夠顯式指定一個默認 server,使用 listen 指令的 default_server 參數來指定,
例如:
  正則表達式

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


    
    Note:
    default_server 參數從 0.8.21 以後開始使用,以前是 default 參數。
    
要注意,默認 server 是監聽端口的一個屬性,不是 server name 的屬性。稍後將進一步描述這個問題。bash

 

對於未定義 server name 的訪問請求,如何防止其被處理
--------------------------------------------

若是但願禁止未定義 「Host」 請求首部的訪問請求,可設置一個 server 用於丟棄這樣的請求:服務器

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


咱們在這裏將 server name 設置爲一個空字符串,它能匹配未攜帶 「Host」 請求首部的訪問請求,而且返回一個特殊的狀態碼 444 以關閉鏈接,444 不是標準的 nginx 狀態碼。測試

    Note:
    從 0.8.48 版開始,這個設置變成了 nginx 的默認設置,因此 server_name "" 可被刪去。
    在更早的版本中,物理主機的主機名被設置爲 default server name。
    spa


混合使用 name-based 虛擬主機和 IP-based 虛擬主機
------------------------------------------

如今咱們看一個更復雜的配置案例,這裏有多個虛擬主機監聽於不一樣的地址:    .net

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

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

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


根據這份配置,nginx 首先檢查訪問請求的 IP 地址和端口號,將它與 server 區塊的 listen 指令
的參數進行對比,過濾掉不匹配的 server。而後 nginx 檢查訪問請求的 「Host」 請求首部,將它與剩下的 server 區塊中的 server_name 進行對比,看可否匹配。若是沒有匹配的 server,該請求將交給 default server 處理。code

例如,nginx 在 192.168.1.1:80 端口接收到對於 www.example.com 的訪問請求,由於在 192.168.1.1:80 端口沒有匹配的 server name,這個請求最後將被交給 192.168.1.1:80 端口的 default server 處理,也就是第一個server。

正如前面提到過,default server 是監聽端口的屬性,因此對於不一樣的監聽端口,能夠分別爲其定義不一樣的 default server。    

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

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

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

192.168.1.1:80 端口的默認 server 是第二個 server;
192.168.1.2:80 端口的默認 server 是第三個 server。

 

一個簡單的 PHP 站點配置示例
-------------------------------

最後咱們來看一個 PHP 站點的例子,看看 nginx 是如何選擇 location 處理請求的: 

server {
	    listen      80;
	    server_name example.org www.example.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 首先根據訪問請求的 URI 查找匹配的定義了 prefix 前綴的 location,並記住其中匹配的最長的前綴。在上面的例子中,定義了前綴的 location 只有一個,並且前綴爲 「/」,它是最短的前綴,能匹配全部請求。由於 「/」 前綴最短,因此這個 location 老是被做爲最後的備選。而後 nginx 開始檢查指定了正則表達式的 location,依照配置文件中的順序依次檢查是否與訪問請求的 URI 匹配,當找到第一個匹配的正則表達式,nginx 再也不繼續檢查後面的 location,nginx 將使用找到的第一個匹配正則表達式所對應的 location。若是沒有匹配的 正則表達式,nginx 將使用以前記住的擁有最長匹配前綴的 location。

要注意的是,全部類型的 location 僅測試請求的 URI 部分,不帶參數。由於在查詢字符串中的參數,可能以
幾種方式提供:

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

除此以外,在查詢字符串中,任何人能夠請求任何事情:

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


    

如今咱們仔細研究一下根據上面的配置,nginx 將會如何處理訪問請求:

  • 訪問請求爲 「/logo.gif」。 對於 「/logo.gif」 的請求首先被 prefix location 「/」 所匹配,而後被正則表達式「\.(gif|jpg|png)$」 所匹配,所以,這個請求將被交給後者處理。使用 「root /data/www」 指令,該請求被映射爲 /data/www/logo.gif,這個文件被髮送給客戶端。

 

  • 訪問請求爲 「/index.php」。 對於 「/index.php」 的請求一樣首先被 prefix location 「/」 所匹配,而後被正則表達式 「\.(php)$」所匹配。所以這個請求將被交給後者處理。該請求被轉發給一個 FastCGI 服務器,該服務器監聽於:localhost:9000。fastcgi_param 指令用於設置 FastCGI 參數 SCRIPT_FILENAME,這裏設置爲:「/data/www/index.php」,以後 FastCGI 服務器會執行該文件。$document_root 變量的值等同於 root 指令的參數值,$fastcgi_script_name 變量的值等於請求 URI,即 「/index.php」。

 

  • 訪問請求爲 「/about.html」。對於 「/about.html」 的請求只能被 prefix location 「/」 所匹配。所以該 location 會處理這個請求。使用 「root /data/www」 指令,這個請求被映射到 /data/www/about.html 文件,該文件將被髮送給客戶端。

 

  • 訪問請求爲 「/」。對於 「/」 的訪問請求的處理更爲複雜。它只能被 prefix location 「/」 所匹配,所以該 location 會處理這個請求。而後 index 指令根據本身的參數以及 「root /data/www」 指令,開始測試是否存在 index 文件。若是 /data/www/index.html 文件不存在,而 /data/www/index.php 文件存在,index 指令會將請求經過內部重定向,重定向至 「/index.php」,而後 nginx 如同接收到客戶端發來對「/index.php」 的請求開始進行處理。這個處理過程剛纔已經講解過,被重定向的請求最後會被轉發給 FastCGI 服務器進行處理。
相關文章
相關標籤/搜索