Nginx 的 server_name 不支持下划线,因 HTTP/1.1 协议禁止 Host 头含下划线;配置如 api_v2.example.com 虽通过 nginx -t,但运行时被静默忽略,需通过 error.log 警告、curl -H "Host:..." 测试及正则匹配等方式排查与替代。

Nginx 的 server_name 指令本身不支持下划线(_)作为合法字符,这是由 HTTP/1.1 协议规范决定的——Host 头和域名中只允许使用字母、数字、连字符(-)和点(.),下划线是明确禁止的。所以如果你在 server_name 中写了类似 api_v2.example.com 这样的配置,Nginx 根本不会报错,但也不会匹配成功,请求会落到默认 server 或其他匹配项上,导致“配置写了却没生效”的假象。
排查这类问题,核心是分三步:确认写法是否合法、验证实际匹配行为、检查 Nginx 日志线索。
看配置是否违反域名规范
Nginx 对 server_name 的解析严格遵循 DNS 域名规则:
- 允许:
a-z、A-Z、0-9、-、. -
禁止:
_、@、$、/、空格、中文等任何非标准字符 - 通配符只能出现在开头(
*.example.com)或结尾(example.*),且不能混用
如果出现 server_name api_v2.example.com;,这行配置语法上能通过 nginx -t,但运行时会被静默忽略——它不参与任何 Host 匹配逻辑。
查看 error.log 中的隐式提示
Nginx 不会为非法 server_name 主动报错,但会在启动或重载时,在 error.log(通常位于 /var/log/nginx/error.log)里输出警告:
nginx: [warn] invalid server name "api_v2.example.com" on line 23 of /etc/nginx/conf.d/app.conf
⚠️ 注意:这个警告只有在 server_name 出现在 http { ... } 块内、且该块被实际加载时才会触发。如果配置文件被注释、未被 include,或 nginx -t 时未覆盖到该文件,则可能看不到此提示。
建议执行:
nginx -t && nginx -s reload tail -n 20 /var/log/nginx/error.log
用 curl + Host 头手动验证匹配结果
绕过浏览器 DNS 和缓存干扰,直接构造请求测试:
# 假设你的配置是 server_name api_v2.example.com; curl -H "Host: api_v2.example.com" http://your-server-ip/ curl -H "Host: api-v2.example.com" http://your-server-ip/
对比响应头中的 Server、Content-Length,或返回的 HTML 内容路径(比如 root 设置不同),就能判断是否命中了预期的 server 块。
更直观的方式是在每个 server 块里加一句:
add_header X-Server-Name "$server_name";
然后看响应头里 X-Server-Name 是什么值——如果是空或别的名字,说明根本没匹配上。
替代方案:用正则捕获绕过命名限制
如果业务确实需要按带下划线的 Host 区分路由(比如灰度标识),不要硬塞进 server_name,改用正则匹配 + 变量提取:
server {
listen 80;
server_name ~^(?<service>[a-z0-9-]+)_[a-z0-9-]+\.(?<domain>.+)$;
location / {
# $service = "api", $domain = "example.com"
proxy_pass http://backend-$service;
}
}</domain></service>
注意:正则必须以 ~ 开头,. 要转义为 \.,含 { } 必须加双引号。
不复杂但容易忽略











