Nginx 基础

背景

Nginx 读作 engine x,是一个高性能的 HTTP 和反向代理服务器,还能用作邮件代理服务器或是通用的 TCP/UDP 代理服务器。有过后端程序部署经历的同学应该会有所了解,用 Nginx 能够很方便地完成反向代理、服务静态文件、实现负载均衡、接入 HTTPS 协议等任务。

根据官方文档里面写到的,除了提供静态文件服务、反向代理和负载均衡等功能之外,还提供以下包括单不限于若干个方面的支持:

  1. FastCGI, uwsgi 之类服务器和反向代理服务器的缓存支持;
  2. 以域名/IP 为基础的虚拟服务器、Keep-alive 和流水线链接的支持;
  3. 访问日志、错误日志的输出和格式化,带缓存的日志写机制;
  4. 3xx-5xx 错误码重定向,根据正则表达式重写 URI (Rewrite);
  5. 基于客户端地址的访问控制和函数调用;
  6. HTTP referer 的验证、支持除了 GET 外的几种 HTTP 方法: PUT/DELETE/COPY/MOVE/MKCOL;
  7. FLV/MP4 的流播放、响应限流、限制单点的并发连接数和请求数;
  8. 等等…(上面只列了我读得懂的)

Nginx 的功能实在太多了,在这里全部列出来不太可能。一直以来我对 Nginx 都停留在“配置是什么,work 就行”的态度。因为这周程序部署时遇到的一点问题,上网搜了好多帖子、博客寻求解决方法那种捉襟见肘、有病乱投医的样子让我觉得很狼狈。借此为契机,决定周末看一下 Nginx 的官方文档。nginx 旧版的官网文档组织混乱,建议移步 Nginx Plus (Nginx 的商业版)官网。Nginx 和 Nginx Plus 的对比放在这里

基本功能概况

Name/IP-based Virtual servers

Nginx 接收到请求之后会首先决定让哪个 server 来接受这个请求。在 nginx 的配置文件中使用 server 这个指令可以定义“服务器”区域,当然最后到底是谁处理这个请求也是看 server 是如何定义的。下面是示例代码块:

demo.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
...
}

这个配置文件定义了 3 个服务器,都监听了 *:80 端口。Nginx 接收到请求之后会转发给 server_name 字段与请求头中的 Host 字段相同的 server 进行处理。如果没有完全对应的 Server 那么请求会被转发到默认服务器进行处理。default_serverlisten 指令的可选参数,如果在端口号后加上 default_server 表示这个服务器是默认服务器。如果没有任何 server 有 default_server,那配置文件中定义的第一个 server 就是默认的服务器

listen 中的 IP 地址进行配置也是可行的。下面再看一个配置文件:

demo2.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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_name 字段。

Locations

路径配置规则

server 区域之中,可以定义若干个 location 区域。location 指令可以根据请求的 URI 将请求分发到不同的代理或者不同的静态文件目录中,后面提到的所有 location 配置都在 server 区域之中。

location prefix 匹配符合 prefix 前缀的 URI,如果一个请求的 URI 匹配了很多 location 的 prefix 那么请求会被分发到 prefix 定义最长的 location 块中。另外,location 指令还可以有标识符配置:

  1. location = path 表示 URI 需要准确的等于 path 才会落到这个 location 区域进行处理;
  2. location ~ regex 表示 URI 匹配相应的正则表达式。如果是 ~* 的话,是忽略大小写的;
  3. location ^~ prefix 表示这个 prefix 匹配的话,不考虑相应的正则表达式;

匹配优先级

要找到最好的 location 块来匹配一个 URI,Nginx 会先匹配所有的 prefix,然后再匹配所有的正则表达式。但是 Nginx 会给正则表达式更高的优先级,除非有 ^~ 标识符。准确的匹配流程如下:

  1. 将 URI 与所有的 prefix 进行比对;
  2. 如果 = 标识符的 location 命中了,直接使用该 location 进行处理,匹配过程终止;
  3. 如果有 ^~ 标识符标识某个 prefix,则后续不用正则表达式检测这个 prefix 命中的 URI;
  4. 保存最长的匹配的 prefix;
  5. 将 URI 与所有的正则表达式进行比对;
  6. 如果 URI 匹配到某个正则表达式,立即停止比对,用这个正则表达式对应的 location 进行处理;
  7. 如果没有正则表达式匹配,用第 4 步保存的最长的 prefix 来处理。

那么根据这个流程,在配置 / 对应的处理方式时,使用 = 标识符能够提高 Nginx 的响应速度。

root, index, proxy_pass

root, index, proxy_pass 是几个在 location 区域内常用的指令,这里专门查一下它们的用法。

  • root path 用文件系统路径来表示,表示在这个 location 中从哪个目录找静态文件来服务;
  • index file ... 定义首页文件,按照给定顺序注意匹配,最后一个文件名可以是绝对路径;
  • proxy_pass url 将请求转发到某个代理服务器上。

变量和改写

变量

在 Nginx 的配置文件中可以使用以 $ 开头的变量,和 linux 的 shell 变量相似。Nginx 预定义了很多变量如 $remote_addr 表示客户端的 IP 地址,$uri 表示目前 URI 的值。用户也可以使用 setmap 这两个指令在配置文件中自定义变量。

Nginx 内置的变量列表在这里可以查看:core HTTP

改写

return 使用 return code [url/"string"] 可以给请求返回相应的状态码,或者直接以 30x 的状态码跳转到后续的 url,以 200 的状态码返回一个 string。

demoReturn.conf
1
2
3
4
5
6
7
8
9
location /wrong/url {
return 404;
}
location /permanently/moved/url {
return 301 http://www.example.com/moved/here;
}
location /text/url {
return 200 "hello world";
}

rewrite 使用 rewrite regex target cmd 可以将 regex 匹配的路径改写到 target,cmd 这个参数有 breaklast 这两个最常用的。它们俩的区别有两点:

  • last 会终止在当前 server 或者 location 区域当中的 rewrite 执行,但是重写到 target 之后落在新的 location 中的 rewrite(如果有的话)还是会继续执行;
  • break 终止当前背景下的 rewrite 执行之外,新的 location 中的 rewrite 也不会执行。

rewrite 的例子可以看下面的配置:

demoRewrite.conf
1
2
3
4
5
6
7
8
9
location /users/ {
rewrite ^/users/(.*)$ /show?user=$1 break;
}
server {
rewrite ^(/download/.*)/media/(\w+)\.?.*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(\w+)\.?.*$ $1/mp3/$2.ra last;
return 403;
# 可以组合使用
}

总结

这次走马观花看了一篇最基础的教程有了较多的新认识,服务静态文件、反向代理、压缩和解压缩、内容缓存等等内容在 Nginx Plus 的文档中都有比较系统的讲解,之后有需要或者有时间的时候再看看吧。

作者

PowerfooI

发布于

2021-08-15

更新于

2024-08-04

许可协议

评论