Nginx允许多个server块监听同一端口,关键靠default_server标识和请求匹配顺序;必须且仅有一个listen 80 default_server,其余同端口server块不可重复设default_server,IPv4与IPv6监听独立,无server_name时依赖default_server兜底匹配请求。

Nginx 允许多个 server 块监听同一个端口,即使都不写 server_name(或都写 _、空字符串),也能正常运行——但必须有明确的区分逻辑,否则会出错或行为不可控。
关键在于:Nginx 不靠 server_name 的有无来决定是否启用某个 server,而是靠 default_server 标识 + 请求匹配顺序。
✅ 同端口下多个无域名 server 能运行的前提
- 至少有一个
server块明确声明listen 80 default_server; - 其余同端口的
server块不能也加default_server - 所有
server块的listen指令必须在 IP+端口+协议维度上不冲突(例如listen 80;和listen [::]:80;是分开的)
注意:IPv4 和 IPv6 默认是独立监听,所以
listen 80;和listen [::]:80;可共存;但两个listen 80 default_server;就会报错:“duplicate default_server”。
? 实际运行逻辑(请求进来时怎么选)
先按 listen 匹配
Nginx 收到 TCP 连接后,根据目标 IP 和端口找到对应listen的所有server块(比如所有listen 80的块)。再看 Host 头是否匹配
server_name
如果请求带了Host: xxx,Nginx 查找server_name精确/通配/正则匹配的块;
如果所有server_name都不匹配(包括_、""、没写),且没有default_server,则用第一个定义的server块(非推荐行为,不可靠)。-
default_server是兜底保障- 它不依赖
server_name,哪怕你写server_name "";或干脆不写,只要加了default_server,它就生效; - 它确保:无论 Host 头是什么、有没有、甚至 HTTP/1.0 无 Host 请求,都会被这个 server 处理。
- 它不依赖
✅ 正确配置示例(同一端口,无域名,靠 default_server 区分)
server {
listen 80 default_server;
root /var/www/default;
location / { try_files $uri $uri/ =404; }
}
server {
listen 80;
root /var/www/backup;
server_name _; # 或删掉这行,效果一样
location / { return 200 "Backup site"; }
}- 访问
http://192.168.1.100/→ 触发default_server,返回默认站 - 访问
http://192.168.1.100/health?仍走 default_server,除非你在第二个 server 中用location显式拦截路径 - ⚠️ 但注意:仅靠端口 + 无 server_name,无法让不同请求自动分流到不同 server ——
default_server是唯一确定性入口,其余 server 若没被 Host 匹配,基本不会被触发。
❌ 常见误区
- 认为
server_name _;就等于“匹配任意域名” → 错,它只是个占位符,仍需 Host 头匹配才能命中 - 把多个
server都设成listen 80;却不设default_server→ Nginx 会用第一个定义的 server 作兜底,但行为不稳定,尤其 reload 后顺序可能变 - 忘记 IPv6 → 若监听了
listen [::]:80;,也得单独配一个default_server,否则 IPv6 请求可能 fallback 到错误 server
? 实用建议
- 如果真不需要域名,只靠端口区分服务 → 改用不同端口更清晰可靠(如
listen 8001;、listen 8002;) - 如果必须共用端口又无域名 → 用
default_server明确指定主入口,其余 server 通过location或if ($host)等方式辅助判断(不推荐复杂逻辑) - 测试时用
curl -H "Host: fake.com" http://ip/模拟不同 Host,验证匹配是否符合预期
不复杂但容易忽略细节。


















