Nginx 基础
背景
Nginx 读作 engine x
,是一个高性能的 HTTP 和反向代理服务器,还能用作邮件代理服务器或是通用的 TCP/UDP 代理服务器。有过后端程序部署经历的同学应该会有所了解,用 Nginx 能够很方便地完成反向代理、服务静态文件、实现负载均衡、接入 HTTPS 协议等任务。
根据官方文档里面写到的,除了提供静态文件服务、反向代理和负载均衡等功能之外,还提供以下包括单不限于若干个方面的支持:
- FastCGI, uwsgi 之类服务器和反向代理服务器的缓存支持;
- 以域名/IP 为基础的虚拟服务器、Keep-alive 和流水线链接的支持;
- 访问日志、错误日志的输出和格式化,带缓存的日志写机制;
- 3xx-5xx 错误码重定向,根据正则表达式重写 URI (Rewrite);
- 基于客户端地址的访问控制和函数调用;
- HTTP referer 的验证、支持除了 GET 外的几种 HTTP 方法: PUT/DELETE/COPY/MOVE/MKCOL;
- FLV/MP4 的流播放、响应限流、限制单点的并发连接数和请求数;
- 等等…(上面只列了我读得懂的)
Nginx 的功能实在太多了,在这里全部列出来不太可能。一直以来我对 Nginx 都停留在“配置是什么,work 就行”的态度。因为这周程序部署时遇到的一点问题,上网搜了好多帖子、博客寻求解决方法那种捉襟见肘、有病乱投医的样子让我觉得很狼狈。借此为契机,决定周末看一下 Nginx 的官方文档。nginx 旧版的官网文档组织混乱,建议移步 Nginx Plus (Nginx 的商业版)官网。Nginx 和 Nginx Plus 的对比放在这里。
基本功能概况
Name/IP-based Virtual servers
Nginx 接收到请求之后会首先决定让哪个 server 来接受这个请求。在 nginx 的配置文件中使用 server
这个指令可以定义“服务器”区域,当然最后到底是谁处理这个请求也是看 server 是如何定义的。下面是示例代码块:
1 | server { |
这个配置文件定义了 3 个服务器,都监听了 *:80 端口。Nginx 接收到请求之后会转发给 server_name
字段与请求头中的 Host
字段相同的 server 进行处理。如果没有完全对应的 Server 那么请求会被转发到默认服务器进行处理。default_server
是 listen
指令的可选参数,如果在端口号后加上 default_server
表示这个服务器是默认服务器。如果没有任何 server 有 default_server
,那配置文件中定义的第一个 server 就是默认的服务器。
对 listen
中的 IP 地址进行配置也是可行的。下面再看一个配置文件:
1 | server { |
这个配置文件下,Nginx 会先判断请求的 IP,再判断 server_name
字段。
Locations
路径配置规则
在 server
区域之中,可以定义若干个 location
区域。location
指令可以根据请求的 URI 将请求分发到不同的代理或者不同的静态文件目录中,后面提到的所有 location
配置都在 server
区域之中。
location prefix
匹配符合 prefix
前缀的 URI,如果一个请求的 URI 匹配了很多 location 的 prefix 那么请求会被分发到 prefix 定义最长的 location 块中。另外,location
指令还可以有标识符配置:
location = path
表示 URI 需要准确的等于 path 才会落到这个 location 区域进行处理;location ~ regex
表示 URI 匹配相应的正则表达式。如果是~*
的话,是忽略大小写的;location ^~ prefix
表示这个 prefix 匹配的话,不考虑相应的正则表达式;
匹配优先级
要找到最好的 location
块来匹配一个 URI,Nginx 会先匹配所有的 prefix,然后再匹配所有的正则表达式。但是 Nginx 会给正则表达式更高的优先级,除非有 ^~
标识符。准确的匹配流程如下:
- 将 URI 与所有的 prefix 进行比对;
- 如果
=
标识符的 location 命中了,直接使用该 location 进行处理,匹配过程终止; - 如果有
^~
标识符标识某个 prefix,则后续不用正则表达式检测这个 prefix 命中的 URI; - 保存最长的匹配的 prefix;
- 将 URI 与所有的正则表达式进行比对;
- 如果 URI 匹配到某个正则表达式,立即停止比对,用这个正则表达式对应的 location 进行处理;
- 如果没有正则表达式匹配,用第 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 的值。用户也可以使用 set 和 map 这两个指令在配置文件中自定义变量。
Nginx 内置的变量列表在这里可以查看:core HTTP
改写
return 使用 return code [url/"string"]
可以给请求返回相应的状态码,或者直接以 30x
的状态码跳转到后续的 url
,以 200
的状态码返回一个 string。
1 | location /wrong/url { |
rewrite 使用 rewrite regex target cmd
可以将 regex 匹配的路径改写到 target,cmd 这个参数有 break
和 last
这两个最常用的。它们俩的区别有两点:
last
会终止在当前 server 或者 location 区域当中的 rewrite 执行,但是重写到 target 之后落在新的 location 中的 rewrite(如果有的话)还是会继续执行;break
终止当前背景下的 rewrite 执行之外,新的 location 中的 rewrite 也不会执行。
rewrite 的例子可以看下面的配置:
1 | location /users/ { |
总结
这次走马观花看了一篇最基础的教程有了较多的新认识,服务静态文件、反向代理、压缩和解压缩、内容缓存等等内容在 Nginx Plus 的文档中都有比较系统的讲解,之后有需要或者有时间的时候再看看吧。