用Nginx map指令实现时间段流量切换的核心是“把时间判断交给系统,把状态识别交给Nginx”,通过cron每分钟检查维护时段并用文件标记(如/var/run/nginx-maint-on)存在性,再用map将文件存在性映射为$maint_mode变量,最后在server块中据此返回503维护页或代理至备用集群,轻量、可靠、易排查。

用 Nginx 的 map 指令做时间段流量切换,核心是“把时间判断交给系统,把状态识别交给 Nginx”。它不依赖 Lua 或外部服务,轻量、可靠、易于排查。
用 cron + 文件标记代替实时时间解析
Nginx 本身无法高效解析 $time_iso8601 做区间判断(需字符串截取+比较,配置臃肿且易出错)。更稳妥的做法是让系统每分钟检查当前时间是否落在维护窗口内,并通过一个文件存在与否来表达“是否启用维护逻辑”:
- 例如每天凌晨 02:00–04:00 维护,就用 crontab 每分钟执行一次脚本
- 脚本用
date +\%H\%M输出类似0235的字符串,直接字典序比对"0200"和"0400" - 命中时段则
touch /var/run/nginx-maint-on,否则rm -f它 - 文件放在
/var/run/(tmpfs,重启自动清空,安全)
用 map 映射文件存在性为开关变量
在 http{} 块中定义一个映射,把某个稳定变量(如 $document_root)和标记文件路径绑定:
map $document_root $maint_mode {
default off;
~*\/var\/run\/nginx-maint-on on;
}
⚠️ 注意:~* 是正则匹配,Nginx 会自动检测右侧路径是否为真实存在的文件。只要文件存在,$maint_mode 就为 on;不存在即为 off。这个变量后续可直接用于条件路由。
在 server 块中实现流量分流或维护页拦截
拿到 $maint_mode 后,就能灵活控制行为:
- 返回静态维护页:
if ($maint_mode = on) { return 503 @maintenance; },再定义location @maintenance { root /usr/share/nginx/html; try_files /maintenance.html =503; } - 将请求代理到备用集群:
set $backend $upstream_main;,然后if ($maint_mode = on) { set $backend $upstream_maint; },最后proxy_pass http://$backend; - 配合 upstream 的健康检查,可做到:维护时段自动切流 + 非维护时段自动回切,无需人工干预
与后端多集群协同的实用建议
若后端有主集群和维护专用集群(如灰度集群、降级集群),可进一步增强健壮性:
- 维护标记文件可扩展为多个,如
/var/run/nginx-maint-mode-01表示“仅切读流量”,-02表示“全量切流”,用不同 map 分别映射 - 结合
upstream的max_fails和fail_timeout,让 Nginx 自动规避临时异常节点,避免误切 - 在切换前后加简单日志:
log_by_lua_block { ngx.log(ngx.INFO, "maint_mode: ", ngx.var.maint_mode) }(如启用 Lua),便于审计











