nginx 通过 map 提取 user-agent 设备类型,结合 $binary_remote_addr$device_type 构建差异化限流 key,并为 mobile/tablet/desktop 分别定义独立 limit_req_zone,再用变量 zone 名动态应用限流策略。

limit_req 指令本身不参与负载均衡,也不能直接识别设备类型或做差异化流量整形——它只基于定义的 key(如 $binary_remote_addr)对请求进行速率限制。要实现“按设备类型差异化限流”,必须借助 Nginx 的变量机制与外部特征提取配合,核心思路是:**用 $http_user_agent 或其他可区分设备的变量构造限流 key,并为不同设备设置独立的 limit_req_zone**。
1. 通过 User-Agent 提取设备类型并生成分类变量
Nginx 本身不内置 UA 解析函数,但可通过正则匹配粗略识别设备类别。在 http 或 server 块中定义:
map $http_user_agent $device_type {
~*android|mobile|blackberry|webos|opera\smini|iemobile mobile;
~*ipad|tablet|kindle|silk|gt-p|sch-i tablet;
default desktop;
}
该 map 块将常见 UA 特征映射为 mobile / tablet / desktop 三类。注意:匹配顺序重要,tablet 规则需放在 mobile 之前(避免 iPad 被 mobile 规则提前捕获)。
2. 为每类设备定义独立的限流区域
每个 limit_req_zone 必须有唯一名称,且 key 应包含设备标识以隔离计数:
limit_req_zone $binary_remote_addr$device_type zone=mobile_limit:10m rate=5r/s; limit_req_zone $binary_remote_addr$device_type zone=tablet_limit:10m rate=8r/s; limit_req_zone $binary_remote_addr$device_type zone=desktop_limit:10m rate=15r/s;
这里 key 使用 $binary_remote_addr$device_type 组合,确保同一 IP 在不同设备类型下使用不同计数器。zone 名称需唯一,内存大小(如 10m)按并发连接数预估分配。
3. 在 location 中按设备类型应用对应限流策略
利用 if 判断 $device_type,再调用对应 limit_req。注意:limit_req 不能直接写在 if 内,需用 map 预生成限流指令名或用嵌套配置。更稳妥的做法是分 location 或用 error_page 配合:
- 推荐方式:用三个独立 location + rewrite 分流(适合设备类型明确且路径可分离的场景)
- 实用方式:用 map 构造限流 zone 名,再配合 limit_req 引用(Nginx 1.13.10+ 支持变量 zone 名):
map $device_type $limit_zone {
mobile mobile_limit;
tablet tablet_limit;
desktop desktop_limit;
}
...
location /api/ {
limit_req zone=$limit_zone burst=10 nodelay;
}
⚠️ 注意:变量 zone 名需开启 limit_req_zone with variable support(高版本默认支持),否则会报错 “invalid value”。
4. 补充建议与注意事项
- UA 可被伪造,该方案适用于非强安全场景(如体验优化、防爬初筛);高安全要求应结合前端埋点、Token 设备指纹或后端校验
- burst 值建议设为 rate 的 2–3 倍,缓解短时突发;nodelay 可避免排队延迟,但会丢弃超限请求
- 监控各 zone 使用情况:用 stub_status 模块或 nginx-module-vts 查看 active、exceeded 等指标
- 若需更精细识别(如 iOS vs Android),可扩展 map 规则,但需平衡维护成本与 UA 变化频率










