10-四层/七层代理实战:适配安卓工控设备长连接、心跳上报场景
一、四层代理 vs 七层代理:OSI模型视角
网络分层这块,七层模型(OSI)大家应该都背过:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。Nginx 代理主要涉及第四层(传输层)和第七层(应用层)。
四层代理(L4):工作在传输层,只看 TCP/UDP 端口和IP地址,不关心应用层协议内容。Nginx 中由stream模块实现。
七层代理(L7):工作在应用层,能解析 HTTP/HTTPS/WebSocket 等协议头,可以根据 URL、Header、Cookie 做路由决策。Nginx 中由http模块实现。
用一个通俗的比喻来区分:
- 四层代理 = 快递分拣中心,只看包裹上的地址标签(IP+端口),不拆包裹
- 七层代理 = 海关检查,要把包裹打开看里面的东西(HTTP请求头、URL),再决定怎么处理
| 对比项 | 四层代理(stream) | 七层代理(http) |
|---|---|---|
| 工作层级 | 传输层(TCP/UDP) | 应用层(HTTP/HTTPS) |
| 性能 | 更高,不解析协议内容 | 稍低,需要解析HTTP头 |
| 路由能力 | 仅IP+端口 | URL/Header/Cookie维度 |
| 适用协议 | 任意TCP/UDP协议 | HTTP/HTTPS/WebSocket |
| 典型场景 | 数据库代理、MQTT、自定义TCP协议 | Web服务、API网关、静态资源 |
二、安卓工控设备的长连接需求
我们的无人售货柜使用瑞芯微RK3568主板,跑的是定制版安卓系统。每台售货柜需要和后端保持长连接,用于:
- 心跳上报:设备每30秒上报一次状态(温度、库存、门禁状态)
- 实时指令下发:后台远程开门、补货指令、价格变更
- 交易数据同步:用户开门取货后的结算数据上传
通信协议有三种选择:
- MQTT:物联网标准协议,轻量级,适合低带宽场景
- WebSocket:基于HTTP升级,适合Web端实时通信
- 自定义TCP协议:性能最高,但需要自己处理粘包/拆包
售货柜场景用的是 MQTT + 自定义TCP协议混合方案:MQTT 做心跳和指令推送,自定义TCP协议做大文件传输(固件升级包)。
三、stream 模块:四层代理配置实战
首先确认 Nginx 编译时包含了 stream 模块:
nginx-V2>&1|grepstream如果没有,需要在编译时加上--with-stream参数。
MQTT 负载均衡配置
# nginx.conf 主配置文件 # stream 模块必须写在 http 块外面,和 http 平级 stream { # MQTT 后端服务器集群 upstream mqtt_backend { server 192.168.1.201:1883 max_fails=3 fail_timeout=30s; server 192.168.1.202:1883 max_fails=3 fail_timeout=30s; server 192.168.1.203:1883 max_fails=3 fail_timeout=30s; # least_conn; # MQTT长连接适合用最少连接策略 } # MQTT TCP 代理 server { listen 1883; proxy_pass mqtt_backend; proxy_connect_timeout 5s; proxy_timeout 300s; # MQTT长连接保活超时,5分钟无数据断开 } # MQTT over TLS(加密通道) server { listen 8883 ssl; ssl_certificate /etc/nginx/ssl/mqtt.pem; ssl_certificate_key /etc/nginx/ssl/mqtt.key; proxy_pass mqtt_backend; proxy_connect_timeout 5s; proxy_timeout 300s; } }关键参数说明:
proxy_timeout 300s:这个参数很重要。MQTT 是长连接,设备连上后要一直保持,如果超时设置太短,设备会被频繁断开重连,浪费资源。设成5分钟,配合 MQTT 自身的 KeepAlive 心跳机制,足够保持连接稳定。least_conn:MQTT 长连接场景下,轮询策略会导致连接数不均匀——先启动的节点连的设备多,后启动的节点连的少。用least_conn确保连接数均衡分配。
自定义TCP协议代理
固件升级用的自定义TCP协议,传输大文件,需要更大的超时时间:
stream { upstream firmware_upload_backend { server 192.168.1.201:9000; server 192.168.1.202:9000; } server { listen 9000; proxy_pass firmware_upload_backend; proxy_connect_timeout 10s; proxy_timeout 3600s; # 固件包可能几百MB,给1小时超时 # 代理缓冲区调大,提升传输性能 proxy_buffer_size 64k; } }四、七层 WebSocket 代理配置
WebSocket 虽然是基于HTTP升级的,但在 Nginx 的http模块中配置。后台管理系统的实时大屏需要 WebSocket 推送设备状态,配置如下:
http { upstream websocket_backend { server 192.168.1.201:8082; server 192.168.1.202:8082; ip_hash; # WebSocket长连接用ip_hash保持会话 } server { listen 443 ssl; server_name ws.vending.com; ssl_certificate /etc/nginx/ssl/vending.pem; ssl_certificate_key /etc/nginx/ssl/vending.key; location /ws/device-status { proxy_pass http://websocket_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # WebSocket长连接超时配置 proxy_read_timeout 3600s; proxy_send_timeout 3600s; } } }WebSocket 代理的三个关键配置:
proxy_http_version 1.1:WebSocket 协议要求 HTTP/1.1,默认 Nginx 用 HTTP/1.0 代理后端,必须手动切换。Upgrade+Connection头:这是 HTTP 协议升级到 WebSocket 的握手关键,告诉后端"我要把连接升级成 WebSocket"。proxy_read_timeout 3600s:WebSocket 连接建立后,如果没有数据传输,Nginx 默认60秒就断开。后台大屏可能几分钟才有一次数据更新,必须加大超时。
五、设备心跳上报完整转发方案
整理一下售货柜设备从上线到心跳的完整链路:
售货柜设备(安卓工控机) │ ├── MQTT:1883 ──────────► Nginx(stream四层代理) ──► EMQX集群 │ (心跳上报 + 指令下发) │ ├── TCP:9000 ──────────► Nginx(stream四层代理) ──► 固件升级服务 │ (大文件传输) │ └── HTTPS:443 /ws/ ────► Nginx(http七层代理) ──► WebSocket服务 (后台实时大屏)对应的 Nginx 完整配置结构:
# /etc/nginx/nginx.conf # 四层代理:设备端通信 stream { include /etc/nginx/stream.d/*.conf; } # 七层代理:Web端API + WebSocket http { include /etc/nginx/conf.d/*.conf; }stream.d/mqtt.conf:
upstream mqtt_cluster { least_conn; server 192.168.1.201:1883 max_fails=3 fail_timeout=30s; server 192.168.1.202:1883 max_fails=3 fail_timeout=30s; server 192.168.1.203:1883 max_fails=3 fail_timeout=30s; } server { listen 1883; proxy_pass mqtt_cluster; proxy_connect_timeout 5s; proxy_timeout 300s; }六、四层健康检查
stream 模块的健康检查和 http 模块类似,但有个额外的问题:四层代理不解析协议内容,只能做TCP连接层面的探测。
upstream mqtt_cluster { server 192.168.1.201:1883 max_fails=3 fail_timeout=30s; server 192.168.1.202:1883 max_fails=3 fail_timeout=30s; server 192.168.1.203:1883 max_fails=3 fail_timeout=30s; }被动健康检查的逻辑:Nginx 尝试建立 TCP 连接,如果连接失败就算一次fail,3次失败后标记节点为不可用,30秒后重试。
但这有个缺陷——TCP端口能连上不代表 MQTT 服务正常(可能 EMQX 进程假死但端口还在监听)。如果需要主动健康检查,需要编译安装nginx_upstream_check_module:
upstream mqtt_cluster { server 192.168.1.201:1883; server 192.168.1.202:1883; check interval=3000 rise=2 fall=3 timeout=2000 type=tcp; }interval=3000:每3秒检查一次rise=2:连续成功2次才标记为健康fall=3:连续失败3次才标记为故障type=tcp:检查类型,TCP连接级别
七、四层还是七层?选择指南
最后给个决策参考:
- MQTT、自定义TCP协议→ 四层代理(stream),七层根本解析不了
- WebSocket→ 七层代理(http),需要处理HTTP升级握手
- 普通HTTP API→ 七层代理,需要URL路由能力
- 追求极致性能的HTTP→ 可以用四层代理,但会丧失所有七层功能
售货柜项目里,设备端走四层(MQTT/TCP),管理端走七层(HTTP/WebSocket),各取所长。