理解Nginx的server匹配规则

栏目: 服务器 · Nginx · 发布时间: 6年前

内容简介:Nginx在逻辑上将提供不同内容的配置划分为块,这些块以层次结构的形式存在(http->server->location)。客户端发出请求时,Nginx收到之后,会有一个确定应该使用哪些配置块来处理请求的过程。本文主要介绍 server 块背后的处理过程。server块是Nginx配置的子集,它定义用于处理已定义类型请求的虚拟服务器(虚拟机)。管理员通常会配置多个server块,并根据请求的域名,端口和IP地址决定哪个块应该处理哪个连接。由于Nginx允许管理员定义多个server块作为单独的虚拟Web服务

Nginx的块配置

Nginx在逻辑上将提供不同内容的配置划分为块,这些块以层次结构的形式存在(http->server->location)。客户端发出请求时,Nginx收到之后,会有一个确定应该使用哪些配置块来处理请求的过程。本文主要介绍 server 块背后的处理过程。

server块是Nginx配置的子集,它定义用于处理已定义类型请求的虚拟服务器(虚拟机)。管理员通常会配置多个server块,并根据请求的域名,端口和IP地址决定哪个块应该处理哪个连接。

Nginx如何决定哪个server块来处理请求

由于Nginx允许管理员定义多个server块作为单独的虚拟Web服务器实例,因此需要一个算法来确定将使用哪些server块来匹配请求。

Nginx在此过程中关注的主要server块指令是 listen 指令和 server_name 指令。

解析“listen”指令以找到可能的匹配

首先,Nginx查看请求的IP地址和端口,并与每个服务器的 listen 指令相匹配,构建可能解析请求的服务器块列表。

listen 指令通常定义 server 块将响应的IP地址和端口。默认情况下,任何不包含 listen 指令的 server 块默认 listen 在 0.0.0.0:80 (或者 0.0.0.0:8080 如果Nginx由普通的非root用户运行),这样的配置块响应80端口上任何接口的请求,但是这个默认值在server选择过程中没有太大的权重。

listen 指令可以设置为:

  • IP地址/端口组合。
  • 只有IP地址,它将监听默认端口80。
  • 只有端口,它将监听该端口上的每个接口。
  • Unix套接字的路径。

最后的选项通常在不同的服务器之间传递请求时起到作用。

在尝试确定向哪个服务器块发送请求时,Nginx将首先尝试 listen 使用以下规则根据指令的特异性来决定:

  • Nginx用默认的缺省值来替换所有不完整的lesten指令(完整:IP+port的组合)的缺省值,因此每一个server块的 listen 指令都可以看作是IP地址和端口的组合。 这种转换的例子有:
    • 没有 listen 指令的块使用该值 0.0.0.0:80
    • 设置为 111.111.111.111 没有端口的IP地址的块变为 111.111.111.111:80
    • 设置为 8888 没有IP地址的端口的块变为 0.0.0.0:8888
  • 接下来Nginx会尝试去收集一个server块的列表,这个列表是基于具体的IP和端口最佳匹配。也就是说如果匹配的server块有具体的IP地址,它就不会匹配用0.0.0.0作为默认的IP地址的server块。无论什么情况,在Nginx选择server块的过程中,端口必须准确匹配。
  • 如果只有一个最具体的匹配,那么该server块将用于提供请求。如果有多个server 块具有相同层次的具体匹配,那么Nginx需继续评估 server_name 指令 。

需要特别注意的是,只有 listen 指令在同一层次上有多个匹配的 server 块时,Nginx才会继续评估 server_name 指令。举个例子,如果域名example.com被解析到IP为192.168.1.10,端口为80的主机上,当客户端请求example.com时,在本例中,第一个server模块总是会提供服务,尽管 server_name 指令在第二个server模块中。

1
2
3
4
server{
listen 192.168.1.10;
....
}
1
2
3
4
5
server{
listen 80;
server_name example.com;
....
}

多个server模块在具体的匹配中处于同一级别的情况下,Nginx下一步才会检查 server_name 指令。

解析server_name指令选择一个匹配

接下来,为了进一步评估具有相同特定 listen 指令的请求,Nginx会检查请求的“host”标头,此值包含客户端实际尝试访问的域或IP地址。

Nginx在候选的每一个server模块中,查看其 server_name 指令,尝试去找到最佳的匹配。Nginx通过下面的公式来进行评估:

  • Nginx首先找到 server_name 与请求的Host头信息精准匹配的server模块,如果找到了这个server模块,它将会被用于服务客户端的请求。若有多个特定的匹配项被找到,第一个会被用于提供服务。
  • 如果没有找到精准的匹配项,Nginx接下来将尝试去找 server_name 与前置通配符(在配置中名称的开头用*表示)匹配的server模块。只要找到一个,这个server模块将被用于为客户端提供服务。如果找到了多个匹配,最长匹配结果的server模块将会被用于提供服务。
  • 如果使用前置通配符没有找到匹配时,Nginx接下来将尝试去找 server_name 与后置通配符(在配置中名称的结尾用*表示)匹配的server模块。只要找到一个,这个server模块将被用于为客户端提供服务。如果找到了多个匹配,最长匹配结果的server模块将会被用于提供服务。
  • 如果使用后置通配符没有找到匹配时,Nginx接下来将会评估用正则表达式(在名称前用~表示)定义 server_name 的server模块。带有与Host头匹配的正则表达式的第一个 server_name 将被用于提供服务。
  • 如果没有找到用正则表达式定义 server_name 的相匹配的server模块时,Nginx接下来会使用默认IP和端口的server模块。

每一个IP地址/端口组合都有一个默认的server模块,当用上面的方法不能确定一个操作的过程时将使用默认的server模块。对于IP地址/端口的组合来说,这将是配置中的第一个模块或者是包含 default_server 选项作为 listen 指令的一部分的server模块(这将复写first-found算法)。每一个IP地址/端口组合只能有一个 default_server 声明。

实例

如果已定义的 server_name 与Host头的值精准匹配时,这个server模块将被选择来处理请求。

在这个例子中,如果请求的Host头的值被设置为 host1.example.com,第二个server模块将被选中:

1
2
3
4
5
server{
listen 80;
server_name *.example.com;
...
}
1
2
3
4
5
server{
listen 80;
server_name host1.example.com;
...
}

如果精准的匹配没有被找到时,Nginx将会检查是否有一个具有适合前置通配符的 server_name 。以通配符开始的最长的 server_name 的server模块将会被选择来完成响应。

在这个例子中,如果请求的Host头是 www.example.org,第二个server模块将被选中:

1
2
3
4
5
server{
listen 80;
server_name www.example.*;
...
}
1
2
3
4
5
server{
listen 80;
server_name *.example.org;
...
}
1
2
3
4
server{
listen 80;
server_name *.org;
}

server_name 以通配符开始的模块没有找到,Nginx将查看在表达式后面有通配符的匹配项是否存在。此时,以通配符结尾的最长的匹配项将被用于服务客户端的请求。

在这个例子中,如果请求的Host头被设置为 www.example.com,第三个模块将被选中:

1
2
3
4
5
server{
listen 80;
server_name host1.example.com;
...
}
1
2
3
4
server{
listen 80;
server_name example.com;
}
1
2
3
4
server{
listen 80;
server_name www.example.*;
}

如果通配符匹配项没有找到,Nginx将会去匹配用了正则表达式的 server_name 。第一个匹配上的server模块将会被选中来响应请求。

在这个例子中,如果请求的Host头设置为 www.example.com,那么第二个server模块将被选中来完成响应。

1
2
3
4
5
server{
listen 80;
server_name example.com;
...
}
1
2
3
4
5
server{
listen 80;
server_name ~^(www|host1).*\.example\.com$;
...
}
1
2
3
4
5
server{
listen 80;
server_name ~^(subdomain|set|www|host1).*\.example\.com$;
...
}

如果上述步骤都不能满足请求,则该请求将被传递到默认的server模块以获取匹配的IP地址和端口。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Just My Type

Just My Type

Simon Garfield / Profile Books / 2010-10-21 / GBP 14.99

What's your type? Suddenly everyone's obsessed with fonts. Whether you're enraged by Ikea's Verdanagate, want to know what the Beach Boys have in common with easy Jet or why it's okay to like Comic Sa......一起来看看 《Just My Type》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器