nginx匹配请求先按listen筛选端口和ip,再按server_name逐级匹配host头:精确域名>前导通配符>后缀通配符>正则;无匹配时由default_server或首个server块兜底。

Nginx 处理多个 server 块共存时的请求匹配,不是看配置文件里谁写在前面,而是分两步严格筛选:先按 listen 匹配端口和 IP,再按 server_name 匹配 Host 头。
第一步:按 listen 指令锁定候选 server 块
Nginx 先检查请求的目标 IP 和端口,只保留所有 listen 值与之完全一致的 server 块。比如:
- 请求发往
192.168.1.100:443,就只会考虑listen 192.168.1.100:443 ssl或listen *:443 ssl(即0.0.0.0:443)这类配置; -
listen 127.0.0.1:80和listen 80是不同候选池,前者只响应本地回环请求,后者响应所有 IP 的 80 端口请求; - 如果只有一个
server块监听该端口(无论有没有server_name),它就会直接命中——此时server_name完全不参与判断。
第二步:在候选块中按 server_name 逐级匹配 Host 头
当多个 server 块监听同一端口时,Nginx 才会读取 HTTP 请求中的 Host 字段,并按固定优先级比对 server_name:
- 完全相等的域名优先,如
Host: example.com→server_name example.com; - 没有精确匹配时,找最长前导通配符,如
*.example.com比*.*.example.com更长、更优 - 再没有就看最长后缀通配符(需 Nginx ≥ 1.11.10),如
example.*可匹配example.org - 最后才执行正则匹配(以
~或~*开头),一旦命中立即停止,不继续往后查
兜底行为:没匹配上怎么办
- 显式标记了
default_server的那个块会被选中,例如listen 80 default_server; - 如果没设,默认取该端口下第一个加载的
server块(通常是配置文件里第一个出现的,但受include加载顺序影响) - 注意:HTTP 和 HTTPS 必须分开监听,
listen 80和listen 443 ssl属于两个完全隔离的匹配池,不会互相干扰
常见踩坑点
- 把 IP 或端口写进
server_name(如server_name 192.168.1.1:8080;)——无效,server_name只认纯域名 - 多个
server块漏写root,导致全部回退到全局root,内容混在一起 - 同一端口下两个
server都没设default_server,又没写对server_name,结果请求总落到第一个块,看似“不生效” - HTTPS 站点复用同一组证书路径,或没为每个
server单独配ssl_certificate和ssl_certificate_key
不复杂但容易忽略











