图片 1

原标题:nginx 1.17.7 主线版发布 来源:开源中国nginx
会同时维护着两个分支,分别为 mainline 主线版和 stable 稳定版。不过在
nginx
中,“稳定”指的是功能和更新频率,它与软件质量无关。稳定分支在其生命周期中从不接收新功能,并且通常仅接收一个或两个更新,用于修复严重的错误。nginx
1.17.7(mainline version)发布了,此版本主要是修复
bug,变更内容如下:Bugfix:如果在配置中使用了带有空替换字符串的”rewrite”指令,则可能在启动或重新配置期间发生分段错误Bugfix:如果将”break”指令与”alias”指令或带有
URI 的”proxy_pass”指令一起使用,则可能在 worker
进程中发生分段错误Bugfix:如果请求 URI 被重写为包含空字符的
URI,则”Location”的响应 header
行可能包含垃圾Bugfix:使用”error_page”指令返回重定向时,带有正文的请求会被错误处理;该错误在
0.7.12 中出现过Bugfix:使用 HTTP/2 时出现 socket 泄漏的情况Bugfix:在
SSL 连接中处理流水线请求时可能会发生超时; 该错误在 1.17.5
中出现过Bugfix: in the ngx_http_dav_module.下载地址 | 更新说明

编译自:
nginx-web-server

添加虚拟服务器

Nginx配置文件中至少包含一条定义虚拟服务器的server指令。当Nginx处理一个请求时,第一个被选中的虚拟服务器将用于处理该请求。

虚拟服务器通过http指令中的server指令来定义,示例如下:

http {
    server {
        # 服务器配置
    }
}

http中可以包含多条server指令来定义多个虚拟服务器。

通常server指令中会包含一条listen指令,用于指定该虚拟服务器将要监听的IP地址和端口。示例如下:

server {
    listen 127.0.0.1:8080;
    # 其他配置
}

如果不填写端口,则采用标准端口。如果不填写ip地址,则监听所有地址。如果缺少整条listen指令,则标准端口是80/tcp,默认端口是8000/tcp,由超级用户的权限决定。

如果有多个server配置了相同的ip地址和端口,Nginx会匹配server_name指令与请求头部的host字段。server_name指令的参数可以是精确的文本、通配符或正则表达式。通配符可以在字符串的头部、尾部或两端包含**可以匹配任意字符。Nginx采用Perl格式的正则表达式,以~开头。以下是一个精确匹配的例子:

server {
    listen      80;
    server_name example.org www.example.org;
    ...
}

如果有多个server_name匹配host字段,Nginx根据以下规则选择第一个相匹配的server处理请求:

  1. 精确匹配
  2. *开始的最长通配符,如*.example.org
  3. *结尾的最长通配符,如mail.*
  4. 第一个匹配的正则表达式(根据在配置文件中出现的先后顺序)

如果找不到任何与host字段相匹配的server_name,Nginx会根据请求端口将其发送给默认的server。默认server就是配置文件中第一个出现的server,也可以通过default_server指定某个server为默认server,如下所示:

server {
    listen      80 default_server;
    ...
}

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

  • Bugfix:如果在配置中使用了带有空替换字符串的”rewrite”指令,则可能在启动或重新配置期间发生分段错误

  • Bugfix:如果将”break”指令与”alias”指令或带有 URI
    的”proxy_pass”指令一起使用,则可能在 worker 进程中发生分段错误

  • Bugfix:如果请求 URI 被重写为包含空字符的 URI,则”Location”的响应
    header 行可能包含垃圾

  • Bugfix:使用”error_page”指令返回重定向时,带有正文的请求会被错误处理;该错误在
    0.7.12 中出现过

  • Bugfix:使用 HTTP/2 时出现 socket 泄漏的情况

  • Bugfix:在 SSL 连接中处理流水线请求时可能会发生超时; 该错误在
    1.17.5 中出现过

  • Bugfix: in the ngx_http_dav_module.

目录

配置Location指令

Nginx根据URL将请求发送给不同的代理,或处理不同的文件请求。由server指令中的location指令配置规则。

比如,可以为虚拟服务器配置三个location指令,将一些请求发送给代理服务器#1,将另外一些请求发送给代理服务器#2,再由本地文件系统处理剩余请求。

Nginx会将请求的URL匹配所有的location指令,请执行匹配location中的指令。每个location指令中通常还会包含多条更为精细匹配的location指令。

location指令包含两类参数:前缀字符串正则表达式。请求要匹配前缀字符串的话,必须以前缀字符串开始。

以下例子中location参数匹配以/some/path/开始的请求URI,如/some/path/document.html(不匹配/my-site/some/path,因为/some/path不在起始位置)。

location /some/path/ {
    ...
}

~用于匹配区分大小写的正则表达式,~*用于匹配不区分大小写的正则表达式。下面例子匹配任意包含.html.htm的URI。

location ~ \.html? {
    ...
}

Nginx先匹配前缀字符串,然后再匹配正则表达式。正则表达式拥有较高优先级,除非使用^~修饰符。在所有前缀字符串中,Nginx会挑选最精确的那个,也就是最长最匹配的那个。详细匹配过程如下:

  1. 匹配所有前缀字符串;
  2. 如果有一个=定义的精确匹配前缀字符串,停止继续匹配;
  3. 如果^~在最长匹配的前缀字符串之前,将忽略正则表达式;
  4. 存储最长的匹配前缀字符串;
  5. 匹配正则表达式;
  6. 找到第一个相匹配的正则表达,停止匹配过程,并执行该location指令;
  7. 如果没有正则表达式匹配,则使用第4部存储的最长前缀字符串;

=修饰符的典型应用是匹配
/请求。针对频繁访问/的情况,将location参数设置为= /可以加速处理过程,因为整个匹配过程在第一条之后就结束了。

location = / {
    ...
}

location指令内可以配置如何处理请求:处理静态文档或将请求转发给代理服务器。在下面的例子中,匹配第一个location的请求可以访问/data目录的文件,匹配第二个location的请求将被转发到www.example.com服务器。

server {
    location  {
        root /data;
    }

    location / {
        proxy_pass http://www.example.com;
    }
}

其中root指令指定了静态文件的文件系统路径,将与请求URI一起构成静态文件的完全路径。在上述例子中,请求xample.png将返回服务器上位于/dataxample.png的文件。

proxy_pass指令将请求转发到代理服务器,并将代理服务器的响应返回给客户端。在上述例子中,所有不是以“开头的URI请求都将被转发到代理服务器。

抽象来说,将 Nginx 配置为 Web 服务器就是定义处理哪些 URLS
和如何处理这些URLS 对应的请求。具体来说,就是定义一些虚拟服务器(Virtual
Servers),控制具有特定 IP 和域名的请求。

下载地址 | 更新说明

  • 建立虚拟服务器
  • 配置 location
  • 使用变量
  • 返回指定的状态码
  • URI 重写
  • 对 HTTP Response 进行重写
  • 处理错误

使用变量

通过在配置文件中使用变量,可以让Nginx以不同的方式处理请求。变量的值在运行时计算获得,并可作为参数传递给指令。变量必须以$开头。变量基于Nginx的状态定义信息,如正被处理请求的属性。

Nginx包含许多预设的变量,如core HTTP变量集,也可以使用setmapgeo指令来自定义变量。大多数变量都在运行时计算值,这些值一般都包含某个请求的相关信息。如$remote_addr包含了IP地址,而uri则包含了当前访问的URI

更具体的来说, Nginx 通过定义一系列 locations 来控制对 URIS
的选择。每一个 location
定义了对映射到自己的请求的处理场景:返回一个文件或者代理请求,或者根据不同的错误代码返回不同的错误页面。另外,根据
URI 的不同,请求也可以被重定向到其它 server 或者 location 。

这里有一个视频,有兴趣可以看看:nginx
安装与调优,其中讲述了以下主题:

返回指定状态码

有些网站在处理错误或重定向时,会要求立即返回一个状态码。最简单的方式就是使用return指令,如下所示:

location /wrong/url {
    return 404;
}

return指令的第一个参数是一个状态码。第二个是可选参数,可以是重定向的URL(当状态码是301、302、303和307时),也可以是返回的文本信息。示例如下:

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

locationserver中都可以包含return指令。

设置虚拟服务器

  • nginx 怎样使你的应用能更快响应、具有更好的伸缩性、更快、更安全?
  • 如何安装 nginx
  • 为 nginx 调整操作系统参数

重写请求中的URI

在处理请求过程中,可以通过rewrite指令重复修改请求的URI。rewrite指令包含2个必填参数和1个可选参数。第一个参数是请求URI必须匹配的正则表达式。第二个参数是要替换的目标URI。第三个为可选参数,可以是一个是否继续执行后续rewrite指令的标记,也可以发送一个重定向指令(状态码是301或302)。示例如下:

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

locationserver中都可以包含多个rewrite指令。Nginx从上到下依次磁性rewrite指令,每次进入server指令块时,rewrite指令都会被执行一次。

Nginx执行完一系列rewrite指令后,根据最新的URI来选择location指令。如果location中也包含rewrite指令,它们也将被依次执行,执行完毕后将重新选择location

下面是一个rewritereturn联合一起使用的例子。

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

这个例子用于区分两套不同的URI。类似于/download/some/media/file的URI将被改写为/download/some/mp3/file.mp3。由于最后的标识last,Nginx将忽略随后的两条指令,然后以新的URI继续处理请求。同样地,类似于/download/some/audio/file的URI将被改写为/download/some/mp3/file.ra。如果请求URI都不匹配上述两条rewrite指令,Nginx将返回403错误代码。

rewrite指令可以包含以下两种参数,用于中断处理过程:

  • last –
    停止执行当前serverlocation中的rewrite指令,并以新的URI查找新的location;
  • break –
    停止执行当前上下文环境内的rewrite指令,并不以新的URI查找新的location;

listen:
Nginx 配置文件至少包含一个 server 命令
,用来定义虚拟服务器。当请求到来时, Nginx
会首先选择一个虚拟服务器来处理该请求。

从高层次来说,配置 nginx 为一个 web 服务器,主要是定义:

重写HTTP返回信息

sub_filter指令支持重写或修改HTTP请求的响应内容,如替换某个字符串。该指令支持变量和链式替换。

下例中,将指向服务器的链接改为指向代理服务器的链接:

location / {
    sub_filter      /blog/ /blog-staging/;
    sub_filter_once off;
}

另一个例子是将http请求改为https请求,并将请求头部的本地主机地址改为主机名。sub_filter_once指令用于告诉Nginx是否连续执行location中的sub_filter指令。

location / {
    sub_filter     'href="http://127.0.0.1:8080/'%20%20%20%20'href="https://$host/';
    sub_filter     'img src="http://127.0.0.1:8080/'%20'img%20src="https://$host/';
    sub_filter_once on;
}

注意:被sub_filter指令修改后的内容将不会再被其他sub_filter指令修改。

虚拟服务器定义在 http 上下文中的 server 中:

  • 对哪些 URL 进行处理
  • 如何处理对于这些 URL 的 HTTP 请求

错误处理

error_page指令用于返回一个自定义错误页面和一个错误代码、修改响应中的错误代码或重定向到不同的URI。在下面的例子中,error_page指令返回404错误和一个错误页:

error_page 404 /404.html;

注意:该指令并不会马上返回(这是return指令做的事),仅仅指定出错时如何处理。错误代码可以能来自于代理服务器,也可能来自Nginx本身(如Nginx没有找到请求的文件)。

在下面的例子中,当Nginx未能找到请求的页面时,不会返回404,而会返回303和一个重定向到新页面指令。这通常用于处理客户端访问旧地址的情况。

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

以下例子中,当访问一个不存在的文件时,Nginx会将请求重定向到http://backend。由于error_page指令未指定重定向代码,该代码将由重定向后的http://backend返回。

server {
    ...
    location  {
        # Set the root directory to search for the file
        root /data/www;

        # Disable logging of errors related to file existence
        open_file_cache_errors off;

        # Make an internal redirect if the file is not found
        error_page 404 = /fetch$uri;
    }

    location /fetch/ {
        proxy_pass http://backend/;
    }
}

在上述例子中,当请求文件未找到时,error_page指令将发起一个内部重定向。$url变量持有当前请求的URI,并被传递给重定向。

假设请求的some/file文件未找到,将被重定向到/fetchsome/file,同时搜索新的location。最终,请求将被第二个location处理,并被代理到http://backend

open_file_cache_errors指令可用于未找到请求文件时,禁止产生错误消息。在上述例子中可以忽略,因为错误已被正确处理。

http {
    server {
        # Server configuration
    }
}
注意: http 中可以定义多个 server

从较低层次来说,主要是定义一组 虚拟服务器 ,让这些 虚拟服务器
去处理对于 特定域名IP地址 的请求。

server 配置块使用 listen 命令监听本机 IP 和端口号(包括 Unix domain
socket and path),支持 IPv4、IPv6,IPv6地址需要用方括号括起来:

更多关于如何配置 nginx 的信息,可参考 Creating NGINX Plus Configuration
Files。

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
}

每个 虚拟服务器 都定义了 location 区块,location
区块定义了对于指定的一组 URI 是如何进行处理的。

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

在 location 中可作如下定义:

server_name:
如果多个 server 的 listen IP 和端口号一模一样, Nginx 通过请求头中的
Host 与 server_name
定义的主机名进行比较,来选择合适的虚拟服务器处理请求:

  • 转发请求到后端服务器(也就是将此 nginx
    服务器作为代理),或者返回一个文件;
  • 对 URI 进行重写,将请求重定向至其它的 location 或者其它虚拟服务器;
  • 返回指定的 error code,并且可以为每个 error code 配置一个指定的
    error page。
server {
    listen      80;
    server_name lufficc.com  www.lufficc.com;
    ...
}

建立虚拟服务器


在 nginx 配置文件中,必须包含至少一个 server 指令,server
指令定义了一个虚拟服务器。当一个请求到来时,nginx
首先要决定选择哪一个虚拟服务器处理该请求。

server 指令在 http context 中进行定义,例如:

http {
    server {
        # Server configuration
    }
}

http context 中,可添加多个 server 指令以定义多个虚拟服务器。

server 区块中,一般会包含一个
listen
指令。listen 指令是用于定义该虚拟服务器监听于哪个 IP地址
端口(或者定义一个 Unix socket 文件及路径)。IP地址可为 IPv4 或 IPv6
地址;IPv6 地址应放入方括号中。

以下是一个例子,该服务器监听于 127.0.0.1 和 8080 端口:

server {
    listen 127.0.0.1:8080;
    # The rest of server configuration
}

如果不指定端口地址,将使用标准的端口地址,即 80 端口。如果不指定 IP
地址,将监听于所有 IP 地址之上。如果 server 区块中没有包含 listen
指令,根据超级用户的权限,将使用 标准的 80/tcp 端口或者 默认的
8000/tcp 端口。

如果同时有多个 虚拟主机 匹配了请求的IP地址和端口,nginx 将测试请求的
Host 首部字段,将它与 server 区块中的
server_name
指令的配置进行对比。server_name
指令的值有三种:准确的主机名通配主机名正则表达式主机名。通配主机名在其起始、或末尾有一个
* 符号,或者起始和末尾都有一个 * 符号,*
可匹配任意长度的字符串;nginx 的正则表达式兼容 Perl
的正则语法,在正则表达式之前需有~前缀。

以下是关于 准确的主机名 的例子:

server {
    listen      80;
    server_name example.org www.example.org;
    ...
}

如果有多个 server_name 指定的主机名与请求首部的 Host
字段匹配,nginx 按如下的优先次序选择,当找到第一个能匹配的 server name
就终止查找:

  1. 准确的主机名
  2. 以 “*” 起始的最长的通配主机名,比如 *.example.org
  3. 以 “*” 结尾的最长的通配主机名,比如 mail.*
  4. 第一个匹配的正则表达式(按照配置文件中的顺序)

如果没有找到与 Host 字段匹配的 server name,nginx
将把请求路由到该端口地址的 默认的虚拟主机
如果没有特别指定,默认的虚拟主机 就是 nginx.conf
文件中的第一个定义的 虚拟主机。也可以使用 listen 指令的
default_server 参数显式地指定一个虚拟主机为 默认的虚拟主机

server {
    listen      80 default_server;
    ...
}

server_name 的参数可以为:

配置 location


nginx 可基于请求的
URI,将访问流量转发给不同的后端服务器,或者将不同的文件提供给客户端。这个功能由
location
指令定义,location 指令在 server 区块中定义。

举个例子,你可以定义三个 location
区块,将一些请求转发给一个后端服务器,将另一些请求转发给另一个不同的后端服务器,余下的请求从本地的文件系统中提供客户端所请求的文件。

当一个请求交给了某个虚拟主机之后,nginx 将请求的 URI
与该虚拟主机内所有的 location 指令的定义进行对比,然后将请求映射到匹配的
location 之中。

在每个 location 区块中,一般可以放置更多的 location
指令(有少数例外),用于进一步对请求进行分组处理。

Note: 在本文中,location 这个词只表示一个单独的 location
上下文。

location 指令可定义两种参数:

  • 前缀字符串(路径名)
  • 正则表达式

如果一个请求的 URI 以某个 前缀字符串 为起始,则与该 location 匹配。

下面举一个 前缀字符串 的例子,在下面的例子中,该 location 的参数为
/some/path/ ,它能匹配类似于 URI 为 /some/path/document.html
的请求:

location /some/path/ {
    ...
}

正则表达式必须带有前缀 ~~*(忽略大小写)。在下面的例子中,该
location 可匹配包含 .html 或者 .htm 的请求:

location ~ \.html? {
    ...
}

为了找到某个 URI 的最佳匹配,nginx 首先比较 URI 和 前缀字符串,然后比较
URI 和 正则表达式。

正则表达式拥有更高的优先级,除非正则表达式使用了 ^~ 修饰符。

在所有匹配的 前缀字符串 中,nginx
选择其中最长及最完整的前缀字符串所对应的 location。

下面是准确的查找 loction 的过程:

  1. 将 URI 与所有的 前缀字符串 进行比较
  2. 修饰符 = 表示 URI 与 前缀字符串
    必须精确匹配。如果能够精确匹配,则结束查找
  3. 如果在匹配的最长的 前缀字符串 前添加了 ^~
    修饰符,则不会再检查正则表达式
  4. 保存匹配的最长的 前缀字符串
  5. 测试 URI 和 正则表达式的匹配情况
  6. 一旦找到匹配的正则表达式,则终止查找,并使用对应的 location
  7. 如果没有匹配的正则表达式,使用保存匹配的最长的 前缀字符串

如果对于 / 的请求很频繁,可为 location / 添加 =
修饰符,这样可以加速处理过程,因为一次匹配查找即可结束:

location = / {
    ...
}

在 location
区块中,可匹配将请求转发给后端服务器。在下面的例子中,对于匹配第二个
location 的请求,将被转发给
www.example.com

server {
    location  {
        root /data;
    }

    location / {
        proxy_pass http://www.example.com;
    }
}

root
指令指定了提供静态文件的本地路径。如果请求的 URI 匹配第一个 location,将
URI 追加到 /data
之后即可得到文件的访问路径:/data/URI。比如请求的 URI 为
xample.png,nginx 将 /dataxample.png
文件返回给客户端。

proxy_pass
指令用于将请求转发给后端服务器,参数值即为后端服务器的访问路径
URL。从后端服务器取回响应之后,nginx
再转发给客户端。在上面的例子中,所有不以 ** 起始的
URI,对应的请求将被转发给后端服务器。

完整的主机名,如:api.lufficc.com 。
含有通配符(含有 ),如:.lufficc.com 或 api.* 。
正则表达式,以 ~ 开头。
通配符只能在开头或结尾,而且只能与一个 . 相邻。www..example.org 和
w
.example.org
均无效。 但是,可以使用正则表达式匹配这些名称,例如
~^www..+.example.org$

~^w.*.example.org$
。 而且 * 可以匹配多个部分。 名称 *
.example.org 不仅匹配
www.example.org,还匹配www.sub.example.org。
对于正则表达式:Nginx 使用的正则表达式与 Perl
编程语言(PCRE)使用的正则表达式兼容。 要使用正则表达式,且必须以 ~
开头。
命名的正则表达式可以捕获变量,然后使用:

相关文章