轮询算法本身无法区分移动端和pc端,需通过map指令预解析user-agent生成$is_mobile变量,并结合mobile_backend与pc_backend两个独立upstream实现分流,再在location中用if条件转发并设置设备标识头。

直接用轮询算法本身无法区分移动端和 PC 端——轮询只管“按顺序发请求”,不看设备类型。真正实现分流,靠的是在轮询之上叠加一层**基于 User-Agent 的条件判断**,再结合两个独立的 upstream 分别承接移动和 PC 流量。
用 map 预解析 User-Agent 判断设备类型
避免每次请求都做正则匹配,用 map 指令提前把 UA 转成布尔变量:
- 必须显式包含 ipad,否则 iPad 请求会走 PC 分支(iOS UA 中不含 mobile)
- default 0 要明确写,防止未匹配时变量为空导致 proxy_pass 失效
- 正则加 ~* 表示不区分大小写匹配
配置示例:
map $http_user_agent $is_mobile {
~*mobile 1;
~*android 1;
~*iphone 1;
~*ipad 1;
~*ios 1;
default 0;
}
定义两个物理隔离的 upstream
移动端和 PC 端后端服务通常架构不同、缓存策略不同,不能共用同一组节点:
- 分别定义 mobile_backend 和 pc_backend
- 每个 upstream 内可用轮询、weight 或 ip_hash,按需配置健康检查(如 max_fails=2 fail_timeout=30s)
- server 地址支持 IP:Port、域名或 Kubernetes Service 名
示例:
upstream mobile_backend {
server 10.0.1.10:8080 max_fails=2 fail_timeout=30s;
server 10.0.1.11:8080 max_fails=2 fail_timeout=30s;
}
upstream pc_backend {
server 10.0.2.20:8080 max_fails=2 fail_timeout=30s;
server 10.0.2.21:8080 max_fails=2 fail_timeout=30s;
}
在 location 中条件转发,fallback 必须明确
用 if 判断 $is_mobile 变量,但注意 Nginx 的 if 在 location 中有作用域限制,且不能嵌套 proxy_pass —— 正确写法是:
- if 块内只写 proxy_pass http://mobile_backend;
- if 外紧跟 proxy_pass http://pc_backend; 作为默认分支
- 不要用 else,Nginx 不支持 if-else 语法
配置片段:
location / {
if ($is_mobile) {
proxy_pass http://mobile_backend;
break;
}
proxy_pass http://pc_backend;
}
补充建议:加 header 标识便于后端识别
让后端知道请求来源,方便日志、限流或灰度控制:
- 在 if 分支中加 proxy_set_header X-Device-Type mobile;
- 在 fallback 分支前加 proxy_set_header X-Device-Type pc;
- 也可统一用 proxy_set_header X-Forwarded-For $remote_addr; 保留原始 IP











