nginx 中可通过 map 指令提取 user-agent 并映射为类型标识,再结合 limit_req_zone 实现按客户端类型(如 spider、mobile)差异化限流;支持单独 zone、ip+ua 组合键及 429 状态码友好提示。

在 Nginx 中,location 块本身不直接支持基于 User-Agent 的限流,但可通过配合 map 指令提取并分类 User-Agent 字符串,再将其作为 limit_req_zone 的键或速率变量,实现在特定 location 内对不同客户端(如爬虫、移动端、桌面端)差异化限流。
用 map 提取 User-Agent 类型并映射限流策略
先在 http 块中定义映射关系,把常见 User-Agent 归类为标识符(如 spider、mobile、desktop),再用于构造限流键或动态速率:
- 示例:识别主流爬虫并统一限速
map $http_user_agent $ua_type {
~*[Mm]ozilla.*[Ss]pider "spider";
~*curl|httpie|wget "tool";
~*[Aa]ndroid|[Ii]phone "mobile";
default "desktop";
}
- 该映射不区分大小写,覆盖常见特征;未匹配的默认归为
desktop - 注意:
$http_user_agent是 Nginx 自动解析的请求头变量,无需额外配置
按 User-Agent 类型设置独立限流区域
将 $ua_type 作为限流键,实现“每类客户端各自计数”,避免爬虫挤占正常用户配额:
- 定义 zone(放在 http 块):
limit_req_zone $ua_type zone=by_ua:10m rate=5r/s;
- 在 location 中启用:
location /api/ {
limit_req zone=by_ua burst=10 nodelay;
proxy_pass http://backend_api;
}
- 效果:爬虫(
spider)被限制为 5r/s,而桌面浏览器(desktop)也共用同一速率上限,但彼此隔离计数 - 若需更细粒度(如只限爬虫),可单独定义 zone:
limit_req_zone $ua_type zone=spider_only:1m rate=1r/s;,并在 map 中精准匹配
结合 IP + User-Agent 实现双重维度限流
防止同一 User-Agent 被多个 IP 滥用(例如伪造 UA 的批量请求),可用组合键提升精度:
- 定义键为
$binary_remote_addr$ua_type:
limit_req_zone "$binary_remote_addr$ua_type" zone=ip_ua:20m rate=20r/s;
- 该键确保“每个 IP + 每类 UA”独立限流,比如一个手机 IP 访问和一个桌面 IP 访问互不影响
- 内存开销略高(因键变长),但比单纯 IP 更抗伪装;建议搭配
burst=5缓冲合理突发
返回友好提示与验证建议
限流触发时,默认返回 503,体验较差。建议在 location 内显式配置:
- 设状态码为 429:
limit_req_status 429; - 自定义错误页(返回 JSON):
error_page 429 = @rate_limited;
location @rate_limited {
default_type application/json;
return 429 '{"error":"too_many_requests","retry_after":60}';
}
- 验证是否生效:用 curl 模拟不同 UA 发起请求,观察响应头
X-RateLimit-Limit(需配合 OpenResty 或第三方模块)或直接检查响应状态码与 body - 注意:CDN 或反向代理后,原始 UA 可能被覆盖,需确认
$http_user_agent确实来自真实客户端(必要时检查X-Forwarded-For配合)











