基于域名的虚拟主机

Nginx 首先决定该请求由哪一个server来处理请求。让我们以一个简单的配置文件样本来说明,这个样本中的3个虚拟主机都监听80端口:


    1. server {
    2.     listen       80;
    3.     server_name  nginx.org  www.nginx.org;
    4.     …
    5. }
    6. 
    7. server {
    8.     listen       80;
    9.     server_name  nginx.net  www.nginx.net;
    10.     …
    11. }
    12. 
    13. server {
    14.     listen       80;
    15.     server_name  nginx.com  www.nginx.com;
    16.     …
    17. }


    在这个配置文件中,Nginx只检验其请求的头部中的“Host”部分,以决定应该选择用哪一个server去响应。如果“Host”不匹配任何 server,或者请求中不包含“Host”部分,那么Nginx会用默认的server来响应请求。在上面这个配置文件中,默认的server是第一个 — 这是Nginx默认的标准行为方式。如果你不希望第一个server作为默认server,你可以明确地设置一个“default_server”参数在 你所希望的那个server上:


      1. server {
      2.     listen       80  default_server;
      3.     server_name  nginx.net  www.nginx.net;
      4.     …
      5. }


      “default_server” 从0.8.21版开始可用。在早期的版本中,应该使用“default”。
      注意,默认server匹配端口,不匹配域名。 以后会有更多的扩展。


      如何避免处理未被匹配的域名

      如果你不想处理那些未被匹配的“Host”行,你可以定义一个默认 server 用来丢弃那些请求:


        1. server {
        2.     listen       80  default_server;
        3.     server_name  _;
        4.     return       444;
        5. }


        我们选择了一个不存在的域名 “_” 作为 server 名称并且返回Nginx的特殊代码‘444’用来关闭连接。注意你应该给这个server设置一个名称,否则Nginx会使用主机名称。

        基于域名和基于IP的虚拟主机的混用

        让我们看一个更加复杂的配置文件样本,这个样本中,那些虚拟 server 监听着不同的地址:

        1. server {
        2.     listen       192.168.1.1:80;
        3.     server_name  nginx.org  www.nginx.org;
        4.     …
        5. }
        6. 
        7. server {
        8.     listen       192.168.1.1:80;
        9.     server_name  nginx.net  www.nginx.net;
        10.     …
        11. }
        12. 
        13. server {
        14.     listen       192.168.1.2:80;
        15.     server_name  nginx.com  www.nginx.com;
        16.     …
        17. }


        在这个配置文件中,Nginx首先根据“server” 区块的“listen”指令检验请求中的 IP 地址和端口。 然后根据 “server” 区块的“server_name”条目检验“Host”行所匹配的IP和端口。 如果server名称没有找到,那么该请求会由默认server 处理。 例如, 在192.168.1.1:80上收到的一个对 www.nginx.com 的请求会由192.168.1.1:80 端口的默认 server 来处理, 也就是第一个 server —既然这个端口上不存在www.nginx.com 的定义。

        如前所述, 一个默认 server 对应一个端口,不同的默认server对应不同的端口:


        1. server {
        2.     listen        192.168.1.1:80;
        3.     server_name   nginx.org  www.nginx.org;
        4.     …
        5. }
        6. 
        7. server {
        8.     listen        192.168.1.1:80  default_server;
        9.     server_name   nginx.net  www.nginx.net;
        10.     …
        11. }
        12. 
        13. server {
        14.     listen        192.168.1.2:80  default_server;
        15.     server_name   nginx.com  www.nginx.com;
        16.     …
        17. }


        一个简单的PHP网站的配置

        现在,让我们用一个典型的、简单的PHP样本来看看Ningx如何选择处理请求时使用的location(位置):

        1. server {
        2.     listen        80;
        3.     server_name   nginx.org  www.nginx.org;
        4.     root          /data/www;
        5. 
        6.     location / {
        7.         index     index.html  index.php;
        8.     }
        9. 
        10.     location ~* /.(gif|jpg|png)$ {
        11.         expires   30d;
        12.     }
        13. 
        14.     location ~ /.php$ {
        15.         fastcgi_pass   localhost:9000;
        16.         fastcgi_param  SCRIPT_FILENAME
        17.                        $document_root$fastcgi_script_name;
        18.         include        fastcgi_params;
        19.     }
        20. }

        首先,Nginx 搜索字符location(对应正则表达式location来解释)所给出的最有效的location(作为保留位置)。 在上面的配置文件中,唯一的字符location是“/”。因为它匹配任何请求,所以他会被作为保留选项。 Nginx检查配置文件中列出的命令中的正则表达式用以匹配location。第一个匹配的表达式会使搜索停止,然后Nginx会使用这个 location。如果没有匹配的正则表达式,那么Nginx会把前面找到的location作为最后有效的location(保留位置)。

        注意所有类型的location只检验一个请求中的URI部分,而不包括查询字符串(?user=…). 这么做是因为查询字符串的参数可以以多种方式出现,比如:


          1. /index.php?user=johnpage=1
          2. /index.php?page=1user=john


          除此之外,请求方式不限:


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


          现在,让我们看看上面的请求将被如何处理:

          一个“/logo.gif”请求会先和字符location“/”匹配,然后再和正则表达式“/.(gif|jpg|png)$”匹配, 因此,它是被字符location处理的。指令“root /data/www”会使该请求指向一个文件 “/data/www/logo.gif”,之后这个文件就会发送到客户端。

          一个 “/index.php”请求同样先被字符location “/” 匹配,然后才被正则表达式“/.(php)$”匹配。 所以, 它是被字符location所处理的,并且这请求是通过一个监听在localhost:9000的FastCGI server被处理的. “fastcgi_param” 指令设置FastCGI的参数SCRIPT_FILENAME设置为“/data/www/index.php”, FastCGI server 执行这个文件. $document_root 变量的值等于 “root” 指令,$fastcgi_script_name 变量等于 URI 请求的值, 也就是 “/index.php”.

          一个 “/about.html”请求只被字符location“/”匹配, 所以,它被这个location处理。 使用“root /data/www” 指令的时候,该请求会被转到 “/data/www/about.html”, 并且文件会被发送到客户端。

          处理一个 “/”请求更加复杂。 它只被字符location“/”匹配, 因此它被这个location处理。然后 “index” 指令按照它的参数和“root /data/www” 检验 index 文件是否存在。如果“/data/www/index.php” 存在, 那么指令会做内部专向到“/index.php”,然后Nginx 按照客戶端是否发送新请求来再次搜索location。 按照我们前面所看到的,转向请求最终会被FastCGI server处理。

          written by Igor Sysoev
          edited by Brian Mercer
          Translated by 成歌