02-无人售货柜整体部署架构:Nginx作为统一入口的三端流量设计
02-无人售货柜整体部署架构Nginx作为统一入口的三端流量设计作者黒漂技术佬系列专栏Nginx高可用部署与三端项目实战一、先看全局无人售货柜系统的三端到底指哪三端做无人售货柜项目最容易迷糊的就是到底有几个端在跟后端通信。我把这套架构里所有会发请求的东西归一下类其实就三类端是什么跑在哪主要通信方式小程序端微信小程序C 端用户扫码购物的入口用户手机里HTTPS 短连接设备端安卓工控一体机装在售货柜里柜子硬件里WebSocket 长连接 HTTPS管理端SaaS 运营管理后台给商家用浏览器里HTTPS 静态资源这三端业务诉求完全不同小程序要的是快——扫码开门 200ms 内必须返回设备端要的是稳——长连接不能断关门事件、商品识别结果要实时回传管理端要的是全——后台页面、图表、设备列表一堆静态资源如果让这三端各自直连后端微服务会乱成一锅粥HTTPS 证书到处配、跨域问题满天飞、设备长连接和短连接互相抢资源、限流和灰度没法统一治理。所以我们必须在所有后端服务前面加一层Nginx 作为统一流量入口把三端流量收口、分流、收束治理。二、Nginx 在整套架构里的角色定位Nginx 在这里同时扮演四个角色下面分别说清楚1. 统一 HTTPS 入口SSL 卸载小程序和设备都强制走 HTTPS。后端微服务SpringBoot自己配证书太重而且每个服务都配一份运维成本爆炸。Nginx 集中管理 SSL 证书对外提供 HTTPS对内转发给后端时走明文 HTTP——这叫SSL 卸载SSL Termination让后端专心干业务加解密的事 Nginx 包了。2. 反向代理流量分发到后端微服务后端是微服务架构订单服务、设备服务、支付服务、商品服务各跑各的实例。Nginx 根据请求路径前缀把流量分发到对应服务集群/api/order/**→ 订单服务集群/api/device/**→ 设备服务集群/api/pay/**→ 支付服务集群3. 静态资源服务器管理端前端管理端是个 Vue/React 单页应用构建产物是一堆 JS/CSS/图片。直接把这些静态文件丢给 Nginx 托管比让后端服务转发快一个量级。4. WebSocket 网关设备长连接设备端需要跟后端保持长连接关门事件、商品识别结果要实时推上来。WebSocket 流量也需要 Nginx 转发而且要做特殊配置升级协议头 长超时这点跟普通 HTTP 转发不一样下面单独讲。三、整体部署拓扑图把上面这套画出来就是这副样子┌─────────────────────────────────────────────┐ │ 外网用户 / 设备 │ └─────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────┐ │ 云厂商 SLB / 公网入口 │ │ (高防DDoS 域名解析 TLS 证书前置) │ └─────────────────────────────────────────────┘ │ ▼ ┌───────────────────────────────────────────────────────────────────────┐ │ Nginx 集群主备/双活 │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Nginx 节点 A │ │ Nginx 节点 B │ │ │ │ (SSL卸载路由) │ │ (SSL卸载路由) │ │ │ └─────────────────┘ └─────────────────┘ │ │ Keepalived VIP 漂移 (高可用) │ └───────────────────────────────────────────────────────────────────────┘ │ │ │ │ ▼ ▼ ▼ ▼ /api/order/** /api/device/** /api/pay/** 管理后台静态资源 │ │ │ │ ▼ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ 订单服务集群 │ │ 设备服务集群 │ │ 支付服务集群 │ │ 前端静态文件 │ │ SpringBoot │ │ SpringBoot │ │ SpringBoot │ │ (Vue构建产物) │ │ WebSocket │ │ │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ ▼ ▼ ▼ ┌──────────────────────────────────────────────────┐ │ MySQL / Redis / RocketMQ / MinIO │ └──────────────────────────────────────────────────┘注意几个关键设计点SLB 在 Nginx 前云厂商 SLB 先扛一层 DDoS、做 4 层转发Nginx 不直接暴露公网 IP被打了找云厂商Nginx 双节点 Keepalived两台 Nginx 用 Keepalived 共享一个 VIP主挂了 VIP 漂到备秒级切换三端流量在 Nginx 一层分流不同前缀路由到不同后端服务集群四、三端请求路由设计详解这是本篇核心按端逐一说明 Nginx 上怎么配。1. 小程序端HTTPS 短连接 API小程序场景特征请求频繁、单次响应要快、强 HTTPS。Nginx 配置思路# 小程序 API 走 /mini 前缀 server { listen 443 ssl; server_name api.cabinet.example.com; ssl_certificate /etc/nginx/ssl/cabinet.pem; ssl_certificate_key /etc/nginx/ssl/cabinet.key; ssl_protocols TLSv1.2 TLSv1.3; location /mini/order/ { proxy_pass http://order_cluster/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /mini/device/ { proxy_pass http://device_cluster/; # 同上一套 header 透传 } }要点SSL 卸载后转发走 HTTP后端不用关心证书X-Forwarded-For 透传真实客户端 IP不然后端拿到的全是 Nginx 内网 IP做风控限流就抓瞎了X-Forwarded-Proto 透传协议后端要知道外面是 HTTPS构造重定向链接才不会跳到 HTTP2. 设备端WebSocket 长连接 HTTPS 上报设备端是难点。柜子里那台安卓工控机启动后要跟后端建立 WebSocket 长连接所有事件全靠这条长连接推上去。这条连接一断柜子就成失联设备了影响线上运营。Nginx 配 WebSocket 转发跟普通 HTTP 不一样三个点必须配# 设备 WebSocket 长连接 location /device/ws/ { proxy_pass http://device_ws_cluster/; # 关键1升级协议头把 HTTP 升级成 WebSocket proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; # 关键2长连接超时拉长默认60s会把长连接踢掉 proxy_read_timeout 3600s; proxy_send_timeout 3600s; # 关键3保持后端长连接复用 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }为什么这三点必须配协议升级WebSocket 握手时客户端发Upgrade: websocket头Nginx 默认用 HTTP/1.0 转发会把这种 hop-by-hop 头干掉必须显式升 1.1 透传 Upgrade/Connection超时拉长长连接可能一小时不通信proxy_read_timeout默认 60s 没数据就断对设备是灾难连接复用到后端也保持长连接减少握手开销3. 管理端静态资源 后台 API管理端是浏览器访问既要前端静态资源又要调后台 API。# 管理后台 server { listen 443 ssl; server_name admin.cabinet.example.com; # 静态资源直接由 Nginx 托管 location / { root /data/www/admin-dist; try_files $uri $uri/ /index.html; # SPA 路由回退到 index.html expires 30d; add_header Cache-Control public, no-transform; } # 后台 API location /admin/api/ { proxy_pass http://admin_cluster/; # ... 常规 header 透传 } }try_files那行很关键Vue/React 的前端路由是前端自己处理的刷新页面时浏览器会问后端要/device/list这种路径后端根本没有这个文件必须回退到index.html让前端路由接管。少了这行管理后台一刷新就 404经典的 SPA 部署坑。五、三端流量隔离与限流策略三端混在一起时必须做隔离避免某一端流量把别的端拖死。Nginx 上常用两种手段1. 按 server_name 隔离域名小程序走api.cabinet.example.com管理后台走admin.cabinet.example.com设备端走device.cabinet.example.com。三个 server 块各管各的互不干扰。2. 按 location 配置独立限流用limit_req_zone给不同端不同速率# 小程序接口限制每秒1000请求 limit_req_zone $binary_remote_addr zonemini_api:10m rate1000r/s; # 设备上报限制每台设备每秒10次 limit_req_zone $device_id zonedevice_report:10m rate10r/s;这样设计后某台柜子恶意刷请求最多把设备端的限流桶打满影响不到小程序用户扫码开门——端与端之间天然隔离。六、小结这一篇我们把无人售货柜系统的三端架构梳理了一遍小程序、设备端、管理端各自的特点和诉求Nginx 在中间扮演 SSL 卸载、反向代理、静态托管、WebSocket 网关四个角色以及三端在 Nginx 上的路由设计要点特别是 WebSocket 的三个关键配置和 SPA 的 try_files 回退。最后讲了流量隔离和限流的思路。下一篇我们落地到环境把 Nginx 的安装、Docker 部署、开机自启和运维命令一步步实战。