从 Nginx 反向代理到阿里云 ESA:一次降本增效的架构升级实践
一、背景:一个非标网络环境的无奈
我的项目是一个微信小程序后端服务,部署在内网服务器上。服务器通过电信家宽上网,虽然有一个电信公网 IP,但运营商毫不意外地封禁了 80 和 443 端口——也就是说,这台机器没法直接对外提供 HTTP/HTTPS 服务。而微信小程序强制要求所有接口走 https://,这就很尴尬了——服务在本地跑得好好的,外网就是访问不了。
最初的方案:阿里云 ECS 做 Nginx 反向代理
当时的思路很直接:在内网服务前面加一层跳板。
用户(微信小程序)
│ https://api.xxx.com:443
▼
阿里云 ECS(有 80/443,做 HTTPS 终结)
│ http://电信公网IP:8080(家宽同样没 80/443,只能走非标端口)
▼
内网服务器(Spring Boot :8080)
在阿里云另开一台 ECS,装 Nginx,配置 SSL 证书,把所有请求反向代理到内网服务器的电信公网 IP 的 8080 端口(路由器做了端口转发到内网机器)。注意,ECS 回源时面对的也是那台被运营商封了 80/443 的家宽机器,所以只能走 8080 这种非标端口。
这个方案跑了一年多,能用,但有几个明显的痛点:
- 成本高:一台 ECS 一年下来几百上千块,就为了跑个 Nginx 转发,太浪费了。
- 多一层维护:Nginx 配置、证书续期、系统安全补丁、磁盘监控……这些都是运维成本。
- 单点故障:ECS 挂了整个服务就不可用,除非再加钱做高可用。
- 延迟增加:多一跳就是多几十毫秒,对用户体验多少有影响。
重新思考:能不能把这一层"云化"?
本质上我要做的事情很简单:
- 对外暴露
https://api.xxx.com:443(需要 443 端口和 SSL 证书) - 把请求转发到
http://电信公网IP:8080(家宽没有 80/443,只能走非标端口)
也就是说,ECS 和 ESA 回源时面对的是同一个问题——目标机器都没有 80/443。那何必为了一层 HTTPS 终结专门养一台云服务器?这不就是 CDN/边缘加速的典型场景吗?于是我开始调研阿里云的边缘安全加速产品 ESA(Edge Security Acceleration)。
二、什么是阿里云 ESA?
ESA(Edge Security Acceleration)是阿里云推出的边缘安全加速一体化产品,你可以把它理解成 CDN + DDoS 防护 + WAF + 边缘计算 的集合体。
对我来说最香的一点是:ESA 天然支持自定义回源端口。这意味着:
用户访问 https://api.xxx.com:443
→ ESA 边缘节点(HTTPS 终结 + 证书管理)
→ http://电信公网IP:8080(走公网到路由器 → 端口转发 → 内网 Nginx)
→ 127.0.0.1:后端端口(内网转发到 Spring Boot)
完美绕过了运营商对 80/443 的封禁——ESA 边缘节点也是通过公网打到我那台家宽机器的 :8080,跟 ECS 回源路径完全一样。区别只是我不需要自己维护那台云服务器了。
更关键的是,ESA 有免费版套餐,对于小流量项目来说完全够用——这意味着一分钱不花就能替代掉 ECS 的角色。
三、整体架构对比
旧架构(ECS Nginx 反代)
新架构(阿里云 ESA)
📌 关键点:两个方案回源时打的是同一个电信公网 IP,都只能用
:8080非标端口——家宽 80/443 被运营商封了,跟前面用 ECS 还是 ESA 无关。区别仅在于 HTTPS 终结这一层是自建 ECS 还是用 ESA 边缘节点。
一眼看出区别:少了一台服务器。ESA 把证书管理、HTTPS 终结、DDoS 防护、全球加速全部在边缘节点完成,我只管好自己内网那台机器的 8080 端口就行。
四、完整迁移步骤
下面是我从零开始配置 ESA 的完整过程,记录备忘,也希望能帮到同场景的朋友。
约定信息(请替换为你自己的):
- 加速域名:
api.xxx.com- 内网公网 IP:
X.X.X.X- 内网服务端口:
8080(HTTP,内网不配置 SSL)- 接入方式:CNAME 接入(强烈推荐,别选 NS)
- 套餐:免费版
步骤 1:添加站点 & 域名验证
- 登录阿里云控制台 → 搜索【边缘安全加速 ESA】→【站点管理】→【新增站点】
- 站点域名:填写
api.xxx.com - 接入方式:选择 CNAME 接入
- 加速区域:中国大陆(域名需已备案)
- 套餐:免费版
- 域名所有权验证:推荐 TXT 记录验证,去你的域名 DNS 后台添加 TXT 解析后点验证
⚠️ 千万别选 NS 接入!NS 会接管全部域名的 DNS 解析,万一配错影响整个域名,风险极高。
步骤 2:添加 DNS 记录(配置源站)
验证通过后进入站点详情页 → 左侧【DNS】→【记录】→【添加记录】:
| 参数 | 值 |
|---|---|
| 主机记录 | api |
| 记录类型 | A 记录 |
| 代理状态 | 开启代理加速(必须开!否则无防护无加速) |
| 记录值/源站 | X.X.X.X(你的内网公网 IP) |
| TTL | 默认自动 |
步骤 3:【最关键】配置回源规则——自定义回源端口 8080
这是整个配置的核心,ESA 默认回源端口是 80,不配这一步直接超时。
左侧【规则】→【回源规则】→【新增规则】:
-
规则名称:
api回源内网8080 -
匹配条件: http.host eq "api.xxx.com"
-
执行动作:
- 回源 HOST:
$host - 回源协议:HTTP(内网只开 http,不用 https)
- HTTP 回源端口:8080
- HTTPS 回源端口:留空
- 回源 HOST:
保存,优先级保持默认。
📌 数据流:用户 →
https://api.xxx.com:443(ESA 边缘,HTTPS 终结)→http://X.X.X.X:8080(电信公网 IP,路由器端口转发至内网 Nginx)→127.0.0.1:后端端口(Spring Boot)
步骤 4:配置 HTTPS 证书
左侧【SSL/TLS】→【边缘证书】:
- 证书来源:阿里云免费 DV 证书
- 选择域名
api.xxx.com,一键申请 - 证书下发后开启【强制 HTTPS 跳转】(301)
免费的 DV 证书一年有效期,到期前 ESA 应该会自动续期,比之前手动在 Nginx 上用 acme.sh 续期省心多了。
步骤 5:缓存规则——API 必须绕过缓存!
这是最容易踩的坑。API 接口和图片上传请求绝对不能缓存,否则会出现旧数据返回、提交异常等问题。
左侧【规则】→【缓存规则】→【新增规则】:
- 规则名称:
动态API禁止缓存 - 匹配条件:
http.host eq "api.xxx.com" - 执行动作:绕过缓存(Bypass Cache)
所有 API 请求实时回源,不经过 CDN 缓存。
💡 如果后续添加了静态资源(如
/assets/路径的图片、JS),可以单独创建缓存规则来加速;当前全是 API 的话全局绕过最简单省心。
步骤 6:【安全核心】回源签名鉴权
这个非常重要!内网服务的 8080 端口是对公网开放的,不做防护的话,任何人扫描到 IP:8080 就能绕过 ESA 直接访问你的后端。
ESA 提供了回源签名鉴权机制:
左侧【访问控制】→【回源鉴权】:
- 鉴权方式:回源签名鉴权
- 点击生成密钥,保存好鉴权密钥
- 开启开关
配套:内网 Nginx 增加签名校验
你内网那台机器上还是需要一个轻量的 Nginx(或者直接在 Spring Boot 里加 Filter),用来校验 ESA 回源请求的签名。参考配置:
server {
listen 8080;
server_name api.xxx.com;
# ESA 回源鉴权密钥,替换成你控制台生成的密钥
set $esa_secret "你的ESA回源鉴权密钥";
location / {
# 校验 ESA 签名 — 没有签名参数的直接返回 403
if ($arg_esa_sign = "") {
return 403;
}
# 透传真实客户端 IP(日志、风控需要)
proxy_set_header X-Real-IP $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:你的后端端口;
}
}
🔐 原理:所有 ESA 回源请求自动带上
esa_sign参数,经过 HMAC 签名;直接访问IP:8080不带签名,直接返回 403。双重防护,安全性拉满。
步骤 7:切 DNS——正式迁移流量
回到你的域名 DNS 后台:
- 找到
api.xxx.com原有的 A 记录,删除 - 新建一条 CNAME 记录:
- 主机记录:
api - 记录类型:CNAME
- 记录值:ESA 控制台给出的 CNAME 地址(类似
xxx.esa.aliyun.com) - TTL:10 分钟
- 主机记录:
等待 5~30 分钟 DNS 生效。
步骤 8:防火墙收尾
- 确保内网防火墙放行 8080 端口入站
- 不要把 8080 对全公网开放,配合步骤 6 的 Nginx 签名鉴权做防护
- 不建议手动维护阿里云回源 IP 白名单(ESA 边缘节点 IP 是动态的),用签名鉴权就够了
五、上线验证清单
切流量前一定逐条验证:
| # | 验证项 | 预期结果 |
|---|---|---|
| 1 | 修改本机 host(X.X.X.X api.xxx.com)直连测试 | 内网服务正常响应 |
| 2 | 删掉 host,浏览器访问 https://api.xxx.com | 正常打开,证书有效 |
| 3 | 小程序测试登录、上传图片等核心接口 | 功能正常 |
| 4 | 直接访问 http://内网公网IP:8080 | 返回 403(签名鉴权生效) |
这 4 条全部通过,说明迁移成功。此时就可以把原来那台 ECS Nginx 反代机器关机观察一周,确认稳定后直接释放。
六、成本对比:实打实省了多少
| 项目 | 旧方案(ECS Nginx) | 新方案(ESA) |
|---|---|---|
| 计算资源 | ECS 1核1G ~¥800/年 | ESA 免费版 ¥0 |
| SSL 证书 | 免费(Let's Encrypt / acme.sh) | 免费 DV 证书,自动续期 |
| 带宽 | ECS 按带宽计费 | ESA 免费版含一定流量 |
| DDoS 防护 | 无(ECS 被打直接挂) | 内置,免费版就有基础防护 |
| 运维成本 | Nginx 配置、证书续期、安全补丁 | 近乎为零 |
| 年费总计 | ~¥800-1000 | ¥0 |
一年省下小一千块,对于个人项目或小团队来说不少了。流量大了之后升级 ESA 套餐的费用也远低于同等规格的 ECS。
七、我踩过的坑(请务必注意)
-
❌ 回源端口忘记填 8080 ESA 默认回源端口是 80。不配回源规则 → 请求到了内网 80 端口 → 连接超时。这一步卡了我半小时。
-
❌ 缓存没设置绕过 上线后小程序偶尔拉到旧数据,排查半天才发现是 ESA 默认缓存了 API 响应。所有 API 必须设置 Bypass Cache。
-
❌ 没开启回源签名鉴权 一开始图省事没配签名鉴权,后来用
curl http://IP:8080一试直接通了——这意味着任何人都能绕过 ESA 直连后端。赶紧补上。 -
❌ DNS 接入方式差点选 NS NS 接入会接管整个域名的解析,一旦出错整个域名都受影响。CNAME 接入只影响你指定的那个子域名,风险可控。
-
❌ 内网 Nginx 配了 SSL,但 ESA 用 HTTP 回源 内网服务和 ESA 之间走内网 HTTP 就够了,SSL 终结在 ESA 边缘。内网配了 SSL 反而导致回源握手失败。
八、总结
这次架构升级的核心思路就是:把能用云服务替代的基础设施"外包"出去。
原来需要自己买服务器、装 Nginx、配 SSL、做安全加固的事情,现在一个 ESA 免费套餐全搞定了,而且做得更好——自带全球加速节点、DDoS 防护、自动证书管理。回源链路本身没变,打的是同一台电信家宽机器的 :8080,变的只是前面那层 HTTPS 终结是谁来做——从自建 ECS 换成了 ESA 边缘节点。我只用关注自己的业务代码,这一层转发的事交给专业的边缘加速产品。
如果你的场景和我的类似(家宽/内网服务器 + 运营商封端口 + 需要 HTTPS),强烈建议试试 ESA 这个方案,免费、省心、还更安全。
本文基于实际项目迁移经验整理,项目为微信小程序虾苗计数系统,后端 Spring Boot,部署于内网服务器,通过阿里云 ESA 对外提供服务。