阅读之前,建议先阅读初识 Nginx。 之后,我们来了解一下 Nginx 配置。

抽象来说,将 Nginx 配置为 Web 服务器就是定义处理哪些 URLS和如何处理这些URLS。具体来说,就是定义一些虚拟服务器(Virtual Servers),控制具有特定 IP 和域名的请求。更具体的来说, Nginx 通过定义一系列 locations 来控制对 URIS 的选择。每一个 location 定义了对映射到自己的请求的处理场景:返回一个文件或者代理请求,或者根据不同的错误代码返回不同的错误页面。另外,根据 URI 的不同,请求也可以被重定向到其它 server 或者 location

设置虚拟服务器

listen:

Nginx 配置文件至少包含一个 server虚拟服务器定义在 http 上下文中的 server

http {
    server {
        # Server configuration
    }
}

注意: http 中可以定义多个 server

server 配置块使用 listen

server {
    listen 127.0.0.1:8080;  # IPv4地址,8080端口
    # listen [2001:3CA1:10F:1A:121B:0:0:10]:80;   # IPv6地址,80端口
    # listen [::]:80;  # 听本机的所有IPv4与IPv6地址,80端口
    # The rest of server configuration
}

上述配置,如果不写端口号,默认使用80端口,如果不写 IP ,则监听本机所有 IP。

server_name:

如果多个 server 的 listen IP 和端口号一模一样, Nginx 通过请求头中的 Host 

nginx 配置后台微服务 nginx配置成服务_Nginx

与 server_name定义的主机名进行比较,来选择合适的虚拟服务器处理请求:

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

server_name

  1. 完整的主机名,如:

api.lufficc.com

  1. 含有通配符(含有 

*

  1. ),如:

*.lufficc.com

  1.  或 

api.*

  1. 正则表达式,以 

~

通配符只能在开头或结尾,而且只能与一个 . 相邻。www.*.example.org 和 w*.example.org 均无效。 但是,可以使用正则表达式匹配这些名称,例如 ~^www\..+\.example\.org$ 和 ~^w.*\.example\.org$ 。 而且 * 可以匹配多个部分。 名称 * .example.org 不仅匹配 www.example.org,还匹配www.sub.example.org。
对于正则表达式:Nginx 使用的正则表达式与 Perl 编程语言(PCRE)使用的正则表达式兼容。 要使用正则表达式,且必须以 ~

命名的正则表达式可以捕获变量,然后使用:

server {
    server_name   ~^(www\.)?(?<domain>.+)$;

    location / {
        root   /sites/$domain;
    }
}

小括号 () 之间匹配的内容,也可以在后面通过 $1 来引用,$2 表示的是前面第二个 ()

server {
    server_name   ~^(www\.)?(.+)$;

    location / {
        root   /sites/$2;
    }
}

一个 server_name

server {
    listen      80;
    server_name api.lufficc.com  *.lufficc.com;
    ...
}

同样,如果多个名称匹配 Host

  1. 完整的主机名,如 

api.lufficc.com

  1. 最长的,且以 

*

  1.  开头的通配名,如:

*.lufficc.com

  1. 最长的,且以 

*

  1.  结尾的通配名,如:

api.*

  1. 第一个匹配的正则表达式。(按照配置文件中的顺序)

即优先级:api.lufficc.com > *.lufficc.com > api.*如果 Host 头部不匹配任何一个 server_name ,Nginx 将请求路由到默认虚拟服务器。默认虚拟服务器是指:nginx.conf文件中第一个 server 或者 显式用 default_server

server {
    listen      80 default_server;
    ...
}

配置 location

URI 与 location

当选择好 server 之后,Nginx 会根据 URIs 选择合适的 locationlocation

  1. 前缀字符串(路径名称)
  2. 正则表达式

对于前缀字符串参数, URIs 必须严格的以它开头。例如对于 /some/path/ 参数,可以匹配 /some/path/document.html ,但是不匹配 /my-site/some/path,因为 /my-site/some/path 不以 /some/path/

location /some/path/ {
    ...
}

对于正则表达式,以 ~ 开头表示大小写敏感,以 ~* 开头表示大小写不敏感。注意路径中的 . 要写成 \. 。例如一个匹配以 .html 或者 .htm 结尾的 URI 的 location

location ~ \.html? {
    ...
}

正则表达式的优先级大于前缀字符串。如果找到匹配的前缀字符串,仍继续搜索正则表达式,但如果前缀字符串以 ^~

具体的搜索匹配流程如下:

  1. 将 

URI=

  1.  修饰符表明 

URI

  1. 如果找到的最长前缀匹配字符串以 

^~

  1. 存储匹配的最长前缀字符串。
  2. 测试对比 

URI

  1. 找到第一个匹配的正则表达式后停止。
  2. 如果没有正则表达式匹配,使用 4 存储的前缀字符串对应的 

location

= 修饰符拥有最高的优先级。如网站首页访问频繁,我们可以专门定义一个 location 来减少搜索匹配次数(因为搜索到 = 修饰的匹配的 location

location = / {
    ...
}
静态文件和代理

location 也定义了如何处理匹配的请求:返回静态文件 或者 交给代理服务器处理。下面的例子中,第一个 location 返回 /data 目录中的静态文件,第二个 location 则将请求传递给 https://lufficc.com 域名的服务器处理:

server {
    location /images/ {
        root /data;
    }

    location / {
        proxy_pass https://lufficc.com;
    }
}

root 指令定义了静态文件的根目录,并且和 URI 拼接形成最终的本地文件路径。如请求 /images/example.png,则拼接后返回本地服务器文件 /data/images/example.pngproxy_pass 指令将请求传递到 URL 指向的代理服务器。让后将来自代理服务器的响应转发给客户端。 在上面的示例中,所有不以 /images / 开头的 URI比如我把 proxy_pass 设置为 https://www.baidu.com/,那么访问 http://search.lufficc.com/ 将得到百度首页一样的响应(页面)(感兴趣的童鞋可以自己试一试搜索功能,和百度没差别呢):

server{
      listen 80;
      server_name search.lufficc.com;
      location / {
              proxy_pass https://www.baidu.com;
      }
}

使用变量(Variables)

你可以使用变量来使 Nginx 在不同的请求下采用不同的处理方式。变量是在运行时计算的,用作指令的参数。 变量由 $开头的符号表示。 变量基于 Nginx 的状态定义信息,例如当前处理的请求的属性。有很多预定义变量,例如核心的 HTTP 变量,你也可以使用 setmap 和 geo 指令定义自定义变量。 大多数变量在运行时计算,并包含与特定请求相关的信息。 例如,$remote_addr 包含客户端 IP 地址,$uri

一些常用的变量如下:

变量名称

作用

$uri

请求中的当前URI(不带请求参数),它可以通过内部重定向,或者使用index指令进行修改,$uri不包含主机名,如 /foo/bar.html

$arg_name

请求中的的参数名,即“?”后面的arg_name=arg_value形式的arg_name

$hostname

主机名

$args

请求中的参数值

$query_string

同 $args

$request

代表客户端的请求地址

$request_uri

这个变量等于包含一些客户端请求参数的原始URI,它无法修改,不包含主机名,如:/cnphp/test.php?arg=freemouse

...

...

一个简单的应用就是从 http 重定向到 https

server{
       ...
       return      301 https://lufficc.com$request_uri;
       ...
}

返回特定状态码

如果你的网站上的一些资源永久移除了,最快最简洁的方法就是使用 return

location /wrong/url {
    return 404;
}

return

location /permanently/moved/url {
    return 301 http://www.example.com/moved/here;
}

return 指令可以包含在 location 和 server

server{
      location / {
              return 404;
      }
}

或者:

server{
      ...
      return 404;
      location / {
          ...            
      }
}

错误处理

error_page 命令可以配置特定错误码的错误页面,或者重定向到其他的页面。下面的示例将在 404 错误发生时返回 /404.html

error_page 404 /404.html;

error_page 命令定义了如何处理错误,因此不会直接返回,而 return在下面的示例中,当 Nginx 找不到页面时,它将使用代码301替换代码404,并将客户端重定向到 http://example.com/new/path.html 。 此配置很有用,比如当客户端仍尝试用旧的 URI

location /old/path.html {
    error_page 404 =301 http:/example.com/new/path.html;
}

重写 URIs

rewrite 指令可以多次修改请求的 URIrewrite 的第一个参数是 URI需要匹配的正则表达式,第二个参数是将要替换的 URI。第三个参数可选,指示是否继续可以重写或者返回重定向代码(301或302)。例如:

location /users/ {
    rewrite ^/users/(.*)$ /show?user=$1 break;
}

您可以在 server 和 location 上下文中包括多个 rewrite 指令。 Nginx 按照它们发生的顺序一个一个地执行指令。 当选择 server 时,server 中的 rewrite在 Nginx 处理一组 rewrite 指令之后,它根据新的 URI 选择 location 。 如果所选 location 仍旧包含 rewrite 指令,它们将依次执行。 如果 URI 匹配所有,则在处理完所有定义的 rewrite 指令后,搜索新的 location以下示例将 rewrite 指令与 return

server {
    ...
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  last;
    return  403;
    ...
}

诸如 /download/some/media/file 的 URI 被改为 /download/some/mp3/file.mp3 。 由于 last 标志,后续指令(第二个 rewrite 指令和 return 指令)被跳过,但 Nginx 继续以更改后的 URI 处理请求。 类似地,诸如 /download/some/audio/file 的 URI 被替换为 /download/some/mp3/file.ra。 如果 URI 不匹配 rewritelast 与 break的区别是:last

  •  : 在当前 

server

  •  或 

location

  •  上下文中停止执行 

rewrite

  •  指令,但是 Nginx 继续搜索与重写的URI匹配的 

location

  • ,并应用新 

location

  •  中的任何 

rewritebreak

  •  :停止当前上下文中 

rewrite

  •  指令的处理,并取消搜索与新 URI 匹配的 

location

  • 。 不会执行新 

location

  • 中的 

rewrite

附录

常用正则

.?+*

  • : 重复0次或更多次

\d^${n}{n,}[c][a-z]

  • : 匹配a-z小写字母的任意一个
全局变量

$args

  •  : #这个变量等于请求行中的参数,同

$query_string$content_length$content_type$document_root$host$http_user_agent$http_cookie$limit_rate$request_method$remote_addr$remote_port$remote_user$request_filename$scheme$server_protocol$server_addr$server_name$server_port$request_uri

  •  : 包含请求参数的原始URI,不包含主机名,如:

/foo/bar.php?arg=baz

$uri

  •  : 不带请求参数的当前URI,$uri不包含主机名,如

/foo/bar.html

$document_uri例如请求:http://localhost:88/test1/test2/test.php

$hostlocalhost

$server_port:88

$request_uri/test1/test2/test.php

$document_uri/test1/test2/test.php

$document_root/var/www/html

$request_filename/var/www/html/test1/test2/test.php

参考

  1. https://www.nginx.com/resources/admin-guide/nginx-web-server/
  2. http://seanlook.com/2015/05/17/nginx-location-rewrite/