nginx 不原生支持基于操作系统的负载均衡,但可通过 map 指令解析 user-agent 实现 os 分类路由;例如在 http 块中匹配 windows、macos 等 ua 特征并映射为变量,再结合 upstream 动态分发。

Nginx 本身不直接支持基于客户端操作系统(如 Windows、macOS、Android、iOS)的负载均衡调度,因为 HTTP 请求头中没有标准化、可靠且不可伪造的字段能唯一标识操作系统类型。但可通过 User-Agent 字符串间接识别,并结合 map 指令 + upstream 动态选择 实现定向分发——这不是原生“OS感知”算法,而是基于 UA 特征的规则路由。
识别并分类客户端操作系统
Nginx 的 map 指令可在 http 块中预先定义变量,从 $http_user_agent 提取 OS 类型:
- 匹配常见 UA 特征:Windows 含
Windows或;macOS 含 <code>Mac OS X或;iOS 含 <code> 或 <code>;Android 含 <code>Android - 注意大小写和空格,建议统一转小写后匹配(用
$sent_http_user_agent不适用,应使用$http_user_agent并配合map的正则忽略大小写) - 未匹配时设为默认组(如
other),避免变量为空导致配置错误
为不同 OS 定义独立 upstream 组
不能复用同一个 upstream 块做条件分发,必须为每类 OS 显式声明独立的服务器组:
- 例如:
upstream win_backend { server 192.168.1.10:8080; }、upstream ios_backend { server 192.168.1.20:8080; } - 每个 upstream 可配置不同策略:iOS 组启用
ip_hash保证会话粘性;Windows 组用least_conn应对长连接;Android 组加weight=2分担高并发流量 - 确保各组后端服务实际支持对应平台的特性(如 iOS 组部署适配 Safari 的静态资源压缩策略,Android 组启用 Brotli)
在 server 块中按 OS 变量选择 proxy_pass
利用 map 生成的变量(如 $os_group),在 location 内通过嵌套 if 或更推荐的 try_files + error_page 方式间接跳转——但最简洁可靠的是直接在 proxy_pass 中引用变量:
- 写法示例:
proxy_pass http://$os_group;,前提是$os_group的值恰好等于 upstream 名称(如值为win_backend) - 必须确保该变量在
proxy_pass执行前已解析完成,因此map必须定义在http级,且变量名不与内置变量冲突 - 测试时用
curl -H "User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X)..." http://your-domain/验证是否命中 iOS 后端
注意事项与局限性
该方案是应用层特征路由,非网络层或内核级识别,存在固有约束:
- User-Agent 可被任意修改或屏蔽,无法用于安全敏感场景(如权限控制)
- 部分浏览器(如 Chrome on iOS)UA 中仍含
iPhone,但实际运行在 iOS;而某些 Android 浏览器可能伪装成桌面版 - Nginx 不支持运行时动态加载 upstream 列表,所有组需在配置重载前静态定义
- 若需更高精度识别,应在后端应用层解析 UA 并打标,Nginx 仅作简单分流;或前置 WAF/CDN(如 Cloudflare)提供
CF-Device-Type或CF-OS头供 Nginx 使用











