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/128(按 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:按 CPU 缓存行对齐,通常从 64、128、256 逐级翻倍试;报错中的数值不一定是可直接使用的最小值。max_size:是哈希表大小的上限,不要求等于或超过条目数,也不要求是 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 是从数据库/脚本动态生成的,应先根据报错调整哈希参数。只有域名匹配语义确实允许时才考虑通配符;正则按顺序匹配,不能作为无差别替代。
调整参数后,除检查 reload 结果,也应检查新产生的错误日志。若已通过观测云 Nginx 集成集中采集,可按主机和变更时间查 could not build server_names_hash,确认错误是否仍在出现,再核对进程实际加载的配置。
常见问题(FAQ)
Q:两个参数都要设吗?
A:不用,报错会指明是哪个。一般只设报错提到的那个;两者有依赖关系时(bucket 变大导致总容量变化)错误提示会换文案,按提示再调即可。
Q:bucket_size 设为 1024 可以吗?
A:语法上可以,但浪费内存且没收益。正确做法是从 64/128 开始按报错提示逐级翻倍,够用即停。
Q:为什么改完 reload 还报同样的错?
A:确认写在了 http 块里而非某个 include 文件的 server 上下文;nginx -T 看磁盘配置里这行是否真的出现在 http 层级。