nginx如何執行請求的

http://nginx.org/en/docs/http/request_processing.html#simple_php_site_configuration


基於名字的虛擬服務

nginx首先決定哪個服務應該去執行請求。我們從一個簡單的服務開始,這裏的三個虛擬服務器都監聽在*:80端口上:

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;
    ...
}

此配置中,nginx僅檢查請求頭中的“Host”字段來決定請求路由到哪個服務中。如果host的值不匹配任何服務名,或者請求中根本不包含host地段,nginx將把請求路由到此端口默認的服務上去。上面的配置中,默認服務是第一個--這是nginx的標準的默認行爲。也可以明確指定哪個服務作爲默認的,使用參數default_server,放到listen指令後面:

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

The default_server parameter has been available since version 0.8.21. In earlier versions thedefault parameter should be used instead.

Note that the default server is a property of the listen port and not of the server name. More about this later.

注意:默認服務是監聽的端口的屬性而不是服務名的屬性

如何不執行沒有定義服務名的請求

How to prevent processing requests with undefined server names

If requests without the “Host” header field should not be allowed, a server that just drops the requests can be defined:

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

Here, the server name is set to an empty string that will match requests without the “Host” header field, and a special nginx’s non-standard code 444 is returned that closes the connection.

Since version 0.8.48, this is the default setting for the server name, so the server_name ""can be omitted. In earlier versions, the machine’s hostname was used as a default server name.

基於服務名和IP地址的混合虛擬服務

Mixed name-based and IP-based virtual servers

我們看一個更復雜的配置,這裏有一些虛擬服務監聽不同的地址:

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 blocks中的listen指定進行比較。再然後將請求中的host頭字段同ip地址和端口已經匹配的這些server blocks中的server name進行比較。如果server name沒有找到,請求將會被默認的虛擬服務器執行。比如,在192.168.1.1:80端口上接收到了www.example.com的請求,這個請求就會被默認的92.168.1.1:80端口執行。就是上面的第一個服務,因爲92.168.1.1:80端口沒有定義www.example.com。


In this configuration, nginx first tests the IP address and port of the request against thelisten directives of the server blocks. It then tests the “Host” header field of the request against the server_name entries of the server blocks that matched the IP address and port. If the server name is not found, the request will be processed by the default server. For example, a request for www.example.com received on the 192.168.1.1:80 port will be handled by the default server of the 192.168.1.1:80 port, i.e., by the first server, since there is no www.example.comdefined for this port.

As already stated, a default server is a property of the listen port, and different default servers may be defined for different ports:

正如已經說明的,默認服務是監聽端口的屬性,對於不同的端口有可能會定義不同的默認服務:

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;
    ...
}

簡單的PHP站點配置

A simple PHP site configuration

Now let’s look at how nginx chooses a location to process a request for a typical, simple PHP site:

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是不考慮location的列表順序的,nginx首先對location進行逐個查找,找到最準確的前綴location。在上面的配置中,只有前綴“/”location是匹配所有的請求你的,這個location將被用作最後考慮。nginx按照配置文件中列出的順序檢查是正則表達式的location。一旦匹配到了一個正則表達式就停止搜索,然後nginx就會使用此location。如果沒有正則表達式匹配到此請求,nginx就會使用先前發現的最準確的prefix location。

nginx first searches for the most specific prefix location given by literal strings regardless of the listed order. In the configuration above the only prefix location is “/” and since it matches any request it will be used as a last resort. Then nginx checks locations given by regular expression in the order listed in the configuration file. The first matching expression stops the search and nginx will use this location. If no regular expression matches a request, then nginx uses the most specific prefix location found earlier.

Note that locations of all types test only a URI part of request line without arguments. This is done because arguments in the query string may be given in several ways, for example:

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

Besides, anyone may request anything in the query string:

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

現在我們來看看根據上面的配置,請求是如何執行的:

Now let’s look at how requests would be processed in the configuration above:

/logo.gif”請求首先匹配前綴location/”,然後又匹配到了正則表達式\.(gif|jpg|png)$”,因此,這個請求被後者處理。根據指令root /data/www”,請求映射到文件/data/www/logo.gif,然後文件被髮送到客戶端。

  • A request “/logo.gif” is matched by the prefix location “/” first and then by the regular expression “\.(gif|jpg|png)$”, therefore, it is handled by the latter location. Using the directive “root /data/www” the request is mapped to the file /data/www/logo.gif, and the file is sent to the client.
  • /index.php”請求也是先匹配location “/”,然後又匹配到\.(php)$”。因此也是被後者映射處理,所以請求被傳送到監聽ocalhost:9000的FastCGI服務。fastcgi_param指令設置FastCGI參數SCRIPT_FILENAME到/data/www/index.php,然後FastCGI服務執行這個文件。變量$document_root的值等於root指令的值,變量$fastcgi_script_name的值等於請求的URI,比如這裏的"index.php"
  • A request “/index.php” is also matched by the prefix location “/” first and then by the regular expression “\.(php)$”. Therefore, it is handled by the latter location and the request is passed to a FastCGI server listening on localhost:9000. The fastcgi_paramdirective sets the FastCGI parameter SCRIPT_FILENAME to “/data/www/index.php”, and the FastCGI server executes the file. The variable $document_root is equal to the value of the rootdirective and the variable $fastcgi_script_name is equal to the request URI, i.e. “/index.php”.
  • 請求/about.html”僅僅匹配location “/”,因此被此location處理。
  • A request “/about.html” is matched by the prefix location “/” only, therefore, it is handled in this location. Using the directive “root /data/www” the request is mapped to the file /data/www/about.html, and the file is sent to the client.
  • Handling a request “/” is more complex. It is matched by the prefix location “/” only, therefore, it is handled by this location. Then the index directive tests for the existence of index files according to its parameters and the “root /data/www” directive. If the file/data/www/index.html does not exist, and the file /data/www/index.php exists, then the directive does an internal redirect to “/index.php”, and nginx searches the locations again as if the request had been sent by a client. As we saw before, the redirected request will eventually be handled by the FastCGI server.

發佈了59 篇原創文章 · 獲贊 24 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章