Nginx监听不同端口时default_server问题

  • Nginx中的default_server
  • 场景复现
  • 实验过程
  • 官方文档
  • 结论


在学习配置Nginx时对default_server产生一点疑问,因此通过实验和查阅官方文档的方式对该问题进行初步的解决,本文用于记录该问题和研究过程,希望能对有同样疑问的同学有帮助,同时欢迎各位同学指点交流。

Nginx中的default_server

Nginx配置文件nginx.conf中的server块中的listen可以后可以设置default_server

  • nginxdefault_server 指令可以定义默认的 server 去处理一些没有匹配到 server_name 的请求
  • 如果没有显式定义,则会选取第一个定义的 server 作为 default_server

但是在视频学习过程中偶然发现以上规则似乎失效了, 其场景是一个server监听80端口(称为server1), 一个server监听8080端口(称为server2), 其中server1在前且没有配置default_server, 在匹配失败之后依然是server2处理了请求

场景复现

为了复现场景, 配置了以下四个server

# server1匹配 www.server1.com:80
server {
    listen 80;
    server_name www.server1.com;
    default_type text/plain;
    return 200 "=========this is server1 that listen on port 80==========";
}

# server2匹配 www.server2.com:8080
server {
    listen 8080;
    server_name www.server2.com;
    default_type text/plain;
    return 200 "=========this is server2 that listen on port 8080==========";
}

# 80端口的的默认server
server {
		listen 80 default_server;
    server_name _;
    default_type text/plain;
    return 200 "=========this is default server that listen on port 80==========";
}
# 给8080端口配置一个额外的server,但不显式的指定为默认server
server {
		listen 8080;
  	server_name _;
  	default_type text/plain;
  	return 200 "=========this is another server that listen on port 8080==========";
}

实验过程

在实验之前需要在\etc\hosts文件中配置一下域名解析, 加入一行127.0.0.1 www.server1.com www.server2.com www.server3.com即可。Windows系统在C:\Windows\System32\drivers\etc路径下

  1. 访问www.server1.com

nginx 监听2个服务端口并转发 nginx监听不同端口_运维

请求被server1正常匹配

  1. 访问www.server2.com

nginx 监听2个服务端口并转发 nginx监听不同端口_服务器_02


请求被80端口的默认server处理

  1. 访问www.server3.com

nginx 监听2个服务端口并转发 nginx监听不同端口_80端口_03


请求被80端口的默认server处理

  1. 访问www.server1.com:8080

nginx 监听2个服务端口并转发 nginx监听不同端口_nginx 监听2个服务端口并转发_04


请求被server2处理,此时8080端口没有显式指定default_server,选择第一个监听8080端口的server,即server2处理请求

  1. 访问www.server2.com:8080

nginx 监听2个服务端口并转发 nginx监听不同端口_80端口_05


请求被server2正常匹配

  1. 访问www.server3.com:8080

nginx 监听2个服务端口并转发 nginx监听不同端口_运维_06


请求被server2处理,同www.server1.com:8080的情况

官方文档

⚠️ 注意:由于文档版本问题,这里使用default参数,0.8.21版本之后使用default_server代替

listen

If the directive has the default parameter, then the enclosing server {…} block will be the default server for the address:port pair.

若listen指令有default参数,那么该server块则是该address:port对的默认server。

If there are no directives with thedefaultparameter, then the default server will be the first server block in which theaddress:portpair appears.

若没有带有default参数的listen指令那么默认server为监听address:port的第一个server

server_name

  • header of the incoming HTTP request against the server { … } blocks in the Nginx configuration files and selects the first one that matches. This is how virtual servers are defined. Server names are processed in the following order:
  1. full, static names
  2. names with a wildcard at the start of the name — *.example.com
  3. names with a wildcard at the end of the name — www.example.*
  4. names with regular expressions
    这之前都是关于server_name匹配的规则

If there is no match, a [#server server { … }] block in the configuration file will be used based on the following order:

若以上规则无法匹配到server,则使用下面的规则选择server:

  1. the server block with a matchinglistendirective marked asdefault匹配listen指令且被default显示标记的server块
  2. the first server block with a matchinglistendirective (or implicitlisten 80;)
    匹配listen指令的第一个server块
    ⚠️注意:这里有点不理解括号里啥意思,意思应该是listen等效于listen 80

结论

  1. 经过后续实验证明实际上, default_server可以配置多个, 但是需要配置为不同端口, 同端口配置多个default_server无法通过nginx -t检查。
  2. 结合简单实验和官方文档,对于该问题可以简单理解为匹配server时是根据请求的IP地址:端口号匹配的, 可以理解为多个server会根据监听的IP:端口号分为若干组, 若server匹配失败则由该组的default_server进行请求处理(没有显式指定default_server则为监听该IP端口对的第一个server)