Nginx 报错 "could not build server_names_hash" 怎么办?
Nginx could not build server_names_hash 的解法:调大 server_names_hash_bucket_size(域名过长时)与 server_names_hash_max_size(域名过多时),放置位置与取值规则、FAQ。
这个 [emerg] 错误表示 server_name 哈希表放不下你的域名配置——在 http 块里调大对应参数即可:域名太长调 server_names_hash_bucket_size,域名太多调 server_names_hash_max_size。
http {
server_names_hash_bucket_size 128; # 默认 32/64(按 CPU 缓存行)
server_names_hash_max_size 1024; # 默认 512
...
}
两个参数的分工
Nginx 用哈希表按 Host 头快速匹配 server 块,报错信息会指明是哪个参数不够:
| 报错文案 | 要调的参数 | 典型原因 |
|---|---|---|
increase server_names_hash_bucket_size |
server_names_hash_bucket_size |
单个域名太长(如超长通配或多级子域) |
increase server_names_hash_max_size |
server_names_hash_max_size |
server_name 条目总数太多 |
取值规则:
bucket_size:必须是 2 的幂(64、128、256),逐级翻倍试;报错会提示需要的最小值。max_size:不小于 server_name 条目总数,取 2 的幂更稳妥。
完整示例
# /etc/nginx/nginx.conf
http {
server_names_hash_bucket_size 128;
server_names_hash_max_size 2048;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
⚠️ 必须放在 http {} 块内,写在 server/location 里无效。改完:
nginx -t && systemctl reload nginx
什么时候会踩到这个坑
- SaaS 平台给每个客户分配子域,
server_name列表几百上千条; - 自动化系统(泛域名证书 + 动态站点)批量生成 server 块;
- 域名特别长:
very-long-subdomain.for-a-customer.example-hosting-provider.com。
如果你的 server_name 是从数据库/脚本动态生成的,这个错误通常意味着该考虑用通配符 *.example.com 或正则 server_name 收敛条目,而不是无限调大哈希表。
观测云对照
[emerg] 级错误意味着 Nginx 起不来或 reload 失败——站点可能正处在"旧配置苟延残喘、新配置从未生效"的状态。把 Nginx error.log 接入观测云,对 [emerg]、[alert] 级别日志设即时告警,配置变更引发的起不来事件第一时间通知到人;结合变更管理,出问题能立刻定位到是哪次改动。
常见问题(FAQ)
Q:两个参数都要设吗?
A:不用,报错会指明是哪个。一般只设报错提到的那个;两者有依赖关系时(bucket 变大导致总容量变化)错误提示会换文案,按提示再调即可。
Q:bucket_size 设为 1024 可以吗?
A:语法上可以,但浪费内存且没收益。正确做法是从 64/128 开始按报错提示逐级翻倍,够用即停。
Q:为什么改完 reload 还报同样的错?
A:确认写在了 http 块里而非某个 include 文件的 server 上下文;nginx -T 看最终生效配置里这行是否真的出现在 http 层级。