Nginx用map实现千级域名重定向,通过哈希表O(1)匹配$host,避免if正则扫描;在server中用return 301 $redirect_target$request_uri跳转,支持协议透传与热更新。

在 Nginx 中用 map 配合 rewrite 实现千级域名重定向,核心在于避免大量 if 或重复 server 块,把域名映射关系从配置中解耦,用哈希查找替代线性匹配,让重定向既高效又易维护。
用 map 构建域名映射表(非正则、O(1) 查找)
map 指令在 Nginx 初始化阶段构建哈希表,对 $host 做精确匹配,查询复杂度接近常数级。千个域名下仍保持毫秒级响应,远优于 if ($host ~* ...) 的正则逐条扫描。
写法示例(放在 http 块内):
map $host $redirect_target {
default "";
old1.example.com https://new1.example.com;
old2.example.com https://new2.example.org;
legacy-site.net https://modern.site;
# …… 可继续追加上千行,无性能衰减
}
- 值为空字符串表示不重定向,可配合后续逻辑跳过
- 支持通配符
*(如*.oldsite.com),但仅限前缀匹配,不支持正则 - 所有 key 必须是合法域名(不含协议、路径),Nginx 会自动小写归一化
在 server 块中触发重定向(轻量、无 if)
不要用 if ($redirect_target) { rewrite ... } —— if 在 location 中有副作用且效率低。正确做法是直接用 return 判断变量值:
server {
listen 80;
server_name ~^(.+)$; # 捕获所有域名
<pre class='brush:php;toolbar:false;'># 若 map 匹配到目标,则 301 跳转;否则正常处理或返回 404
if ($redirect_target) {
return 301 $redirect_target$request_uri;
}
# 兜底:未匹配域名走默认逻辑(如静态服务或反向代理)
root /var/www/default;}
注意:if 在此场景下是安全的,因为只用于判断一个已计算好的 map 变量,不涉及 URI 修改或嵌套条件。若追求极致严谨,也可用 try_files + 内部命名 location,但对千级简单跳转而言,上述写法更直观可靠。
支持 HTTP/HTTPS 混合跳转与路径透传
多数重定向需保留原始路径和查询参数。$request_uri 自动包含完整 path + query,无需手动拼接。若需强制升级 HTTPS 或统一协议,可在 map 中定义带协议的目标:
- 写成
https://new.com$request_uri是错误的 ——$request_uri已含/path?query,重复拼接会导致双斜杠 - 正确写法是 map 中只写域名部分,重定向时显式拼接:
return 301 https://$redirect_target$request_uri; - 若部分旧站只支持 HTTP,map 中直接写
http://...即可,协议由目标决定
热更新与维护技巧
map 表过大时,建议拆分为多个文件引用,提升可读性:
include /etc/nginx/maps/redirects-legacy.conf; include /etc/nginx/maps/redirects-acquired.conf;
- 每次修改后执行
nginx -t && nginx -s reload,map 会重新加载,无需重启进程 - 上线前用
curl -I http://old1.example.com验证跳转状态码和 Location 头 - 记录原始域名与目标映射关系到 CSV,用脚本生成 map 文件,避免手误
不复杂但容易忽略:map 的 key 是 host 名,不是完整 URL;重定向必须用 return 或 rewrite ... redirect,仅 rewrite 是内部重写,不会发 3xx 响应。


















