Nginx 的 limit_req 不支持直接识别设备类型,需通过 map 指令解析 $http_user_agent 生成 $device 变量,再以此为 key 配置 limit_req_zone 实现按终端差异化限流。

limit_req 指令本身不支持直接识别或区分终端设备类型(如手机、平板、桌面浏览器),它没有内置的 $device_type 或类似变量。Nginx 原生的 ngx_http_limit_req_module 只能基于请求中已有的变量(如 $binary_remote_addr、$request_uri、$host、$http_user_agent 等)构造限流 Key,而设备类型需从 User-Agent 字符串中提取并映射为可管理的标签。
但你可以间接实现“按终端设备类型差异化限流”,核心思路是:
✅ 先通过 map 指令解析 User-Agent,生成设备分类变量(如 $device);
✅ 再用该变量作为 limit_req_zone 的 Key,定义不同设备的独立限流策略;
✅ 最后在 location 中调用对应 zone 实现差异化控制。
H3 使用 map 提取设备类型变量
Nginx 不直接识别设备,但可通过正则匹配 User-Agent 判断常见终端:
http {
# 定义设备类型映射:desktop / mobile / tablet
map $http_user_agent $device {
default desktop;
~*[Tt]ablet tablet;
~*[Mm]obi mobile;
~*iPhone mobile;
~*iPad tablet;
~*Android.*Mobile mobile;
~*Android.*Tablet tablet;
~*Firefox.*Mobile mobile;
~*Chrome.*Mobile mobile;
}
# 基于 $device + IP 组合,避免同一IP下多设备互相干扰
limit_req_zone "$device|$binary_remote_addr" zone=device_ip:10m rate=5r/s;
limit_req_zone "$device" zone=device_only:10m rate=20r/s;
}? 说明:
$device|$binary_remote_addr是更稳妥的 Key,兼顾设备类型和用户唯一性;zone=device_ip适用于“每个移动设备 IP 每秒最多 5 请求”;zone=device_only适用于“全站所有移动端每秒共 20 请求”,适合轻量级全局约束。
H3 在 location 中按设备启用不同限流策略
server {
location /api/ {
# 移动端走严格限流(防爬+保服务)
if ($device = mobile) {
limit_req zone=device_ip burst=3 nodelay;
break;
}
# 平板稍宽松
if ($device = tablet) {
limit_req zone=device_ip burst=8;
break;
}
# 桌面端用较宽松的全局设备限流
limit_req zone=device_only burst=15;
}
}⚠️ 注意:if 在 location 中使用需谨慎(仅支持部分指令),更推荐用嵌套 location + map 配合 limit_req 直接调用:
location /api/ {
limit_req zone=device_ip burst=3 nodelay;
}
# 若需完全隔离策略,可按设备前缀分路径(需前端或反向代理配合)
# 如:/api/mobile/ → 自动触发 mobile 限流更健壮的做法是统一用一个 zone,但通过不同 Key 实现逻辑隔离:
limit_req_zone "$device|$binary_remote_addr" zone=by_device:10m rate=10r/s;
server {
location /api/ {
limit_req zone=by_device burst=5;
# 所有设备各自独立计数:mobile|192.168.1.100 和 desktop|192.168.1.100 互不影响
}
}H3 结合缓存做响应级差异化控制(非限流,但常被混淆)
需要明确:
❌ limit_req 控制的是请求准入速率(进来的数量),不是缓存行为;
✅ 缓存控制由 expires、add_header Cache-Control、proxy_cache 等指令负责;
✅ 若目标是“移动端返回更短缓存时间、桌面端缓存更久”,应单独配置:
location /static/ {
if ($device = mobile) {
expires 1m;
add_header Cache-Control "public, max-age=60";
break;
}
expires 1h;
add_header Cache-Control "public, max-age=3600";
}限流与缓存是正交机制,可共存但不可混用。
H3 实际部署建议
-
优先测试 User-Agent 解析准确性:用
curl -H "User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)..."验证$device值; -
避免过度依赖 UA:部分爬虫伪造 UA,关键接口建议叠加
limit_conn(限制连接数)或结合fail2ban; -
监控与日志:添加
$device到 access log,便于分析各终端流量分布:log_format main '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" $device';
不复杂但容易忽略。

















