Featured image of post 反向代理 6 巨头 + 内网穿透双雄:从 Nginx/Tengine 健康检查到全场景工具横评

反向代理 6 巨头 + 内网穿透双雄:从 Nginx/Tengine 健康检查到全场景工具横评

系统梳理 Nginx / Tengine / Caddy / Traefik / Envoy / BFE 6 款主流反向代理工具的核心特性、生态位与选型建议;基于实战讲透主动/被动健康检查、Stream 四层代理与主动/被动混用的踩坑要点;最后给出内网穿透场景下 frp 与 cpolar 的对比与选型矩阵。

写于 2026 年 4 月的回望

做博客 14 年,第一次把"反向代理 + 内网穿透"合并到一篇文章里——不是因为它们逻辑上多紧密,而是因为在写代码、跑业务、对外服务这条链路上,这两类工具几乎总是成对出现:你先要有个公网入口(反代 + 四层代理),再考虑内网服务怎么被访问(内网穿透)。入口打不通,内网穿透也无处发力

本文是 0.7 批次"架构实战"系列的一篇,合并源文档 9 篇(其中 3 篇有实战内容、6 篇仅有工具骨架),目标是给读者一份可立即拿去选型的横评 + 实战手册。

全文目录

  • 一、为什么需要反向代理?3 个真实场景
  • 二、6 款主流反代工具特性横评
  • 三、Nginx 与 Tengine:编译安装 + 健康检查实战(基于源文档深度展开)
  • 四、Stream 四层代理:主动检查 vs 被动检查的踩坑点
  • 五、内网穿透双雄:frp 与 cpolar 选型
  • 六、选型矩阵:按业务场景一图看懂
  • 七、常见 8 个坑点速查

一、为什么需要反向代理?3 个真实场景

反向代理(Reverse Proxy) 站在客户端与真实服务器之间,客户端只看到代理的地址,永远不知道后端有几台机器。在生产环境里,反向代理通常承担三类职责:

  1. 统一入口 + 域名路由:把 a.example.comb.example.com 解析到同一个入口,按 Host 头转发到不同后端
  2. TLS 终结 + HTTPS 加速:所有证书/加解密在反代层完成,后端只跑明文 HTTP,省 CPU 省证书
  3. 负载均衡 + 健康检查:检测后端故障、自动剔除/恢复

在微服务、Service Mesh、API 网关场景里,反代还承担动态路由、灰度发布、限流熔断等高级职责——这正是 Caddy、Traefik、Envoy、BFE 竞相入场的原因。

二、6 款主流反代工具特性横评

工具出品方 / 协议核心定位配置风格动态生效四层代理生态优势
NginxF5 / BSD-2HTTP 反代事实标准静态 conf + reload需 reloadstream 模块模块生态最丰富
Tengine阿里 / BSD-2Nginx 增强 + 通用 API 网关兼容 Nginx + 动态配置支持域名/证书/路由动态生效stream + UDP bypass双 11 验证 + Ingress 标注
Caddy个人作者 / Apache-2自动 HTTPS + 极简配置Caddyfile / JSONreload(零停机)需 reverse_proxy + layer4 插件自动 ACME、HTTP/3 默认开
TraefikTraefik Labs / MIT云原生动态反代动态发现(Docker/K8s)热加载(监听 provider)需 entrypoints TCPK8s Ingress 一等公民
EnvoyLyft/CNCF / Apache-2Service Mesh 数据面YAML/JSON xDSxDS 热推送原生 L4/L7Istio 默认 sidecar
BFE百度 / Apache-2大流量七层网关类 Nginx conf动态配置支持七层 + 部分四层百度搜索/地图规模验证

工具生态位速读

  • Nginx / Tengine:做"经典反代"——nginx.conf 写好、reload 完事,适合中小规模、配置不频繁变化的场景
  • Caddy:做"个人/小团队站点"——默认自动 HTTPS,省心,配置文件 5 行就能跑
  • Traefik:做"K8s/容器编排动态反代"——监听 Docker/K8s 标签自动生成路由
  • Envoy:做"Service Mesh 数据面"——xDS 协议动态下发配置,Istio 默认用它
  • BFE:做"超大流量七层网关"——百度搜索级别流量验证,国内大厂可选

三、Nginx 与 Tengine:编译安装 + 健康检查实战

本节是源文档里有完整实战内容的部分,逐行引用并补全注释。

3.1 编译选项对比

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Nginx 1.24 编译(Debian/Ubuntu 风格)
./configure \
  --prefix=/usr/local/nginx \
  --with-http_ssl_module \
  --with-http_stub_status_module \
  --with-pcre \
  --with-http_gzip_static_module \
  --with-stream \
  --with-stream_ssl_module \
  --add-module=../nginx_upstream_check_module

make && make install
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Tengine 3.1 编译(额外启用 HTTP/2、realip、upstream_check)
./configure \
  --prefix=/usr/local/nginx \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-stream \
  --with-stream_ssl_module \
  --with-http_realip_module \
  --with-http_gzip_static_module \
  --add-module=../nginx_upstream_check_module

Tengine 在 Nginx 1.24 基础上额外提供(源文档原文特性清单):

  • HTTP/3 支持(QUIC v1 与 draft-29)
  • 基于 header / cookie / query / 服务权重的高级路由动态无损生效
  • 配置分域名 TLS 多版本、timeout、强制 HTTPS、CORS、robots 动态生效
  • bypass 内核的用户态 UDP 转发(xUDP),性能远高于内核 UDP
  • 流式上传到后端 / FastCGI
  • 异步 OpenSSL,可对接 QAT 硬件加速
  • 更强大的负载均衡:一致性 hash、会话保持、主动健康检查、动态 upstream 域名解析
  • CSS/JS 合并空白字符去除内存监控CPU 亲缘性自动绑定

3.2 迁移原 Nginx 到 Tengine

源文档提供了一套保留证书与 conf 的安全迁移流程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. 备份
mkdir -p /backup
rsync -av /usr/local/nginx/conf/cert /backup/
rsync -av /usr/local/nginx/conf/nginx.conf /backup/

# 2. 停止原服务(如有 HAProxy/keepalived 协同)
systemctl stop keepalived
systemctl stop nginx
systemctl stop nginxwebui

# 3. 卸载旧版
rm -rf /usr/local/nginx

# 4. 安装 Tengine(编译步骤见 3.1)

# 5. 还原备份
rsync -av --force /backup/nginx.conf /usr/local/nginx/conf/
rsync -av /backup/cert /usr/local/nginx/conf/

# 6. 启动
systemctl start keepalived
systemctl start nginx
systemctl start nginxwebui

关键点:Tengine 完全兼容 Nginx 配置,所以可以直接复用 nginx.conf 与证书目录。--force 标志在还原时避免 rsync 因目标存在而拒绝覆盖。

四、Stream 四层代理:主动检查 vs 被动检查的踩坑点

源文档反复强调的一条铁律:

注意:这个模块(nginx_upstream_check_module)只能支持 HTTP,不支持 stream;且被动检查不能和主动检查同时使用。

4.1 主动健康检查(仅 HTTP)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
http {
    upstream backend_http {
        server {{BACKEND_1}}:8080;
        server {{BACKEND_2}}:8080;
        check type=http;
        check interval=5000 rise=2 fall=3 timeout=2000;
        check_http_send "GET /health HTTP/1.0\r\nHost: example.com\r\n\r\n";
        check_http_expect_alive http_2xx;
    }

    server {
        listen 80;
        location / {
            proxy_pass http://backend_http;
        }
    }
}

参数含义(源文档原文):

  • interval:调用间隔(毫秒)
  • rise:连续成功多少次后标记存活
  • fall:连续失败多少次后摘除
  • timeout:单次检查超时

4.2 被动健康检查(stream 块)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
stream {
    upstream backend_tcp {
        server {{MQTT_NODE_1}}:1883 fail_timeout=30s max_fails=3;
        server {{MQTT_NODE_2}}:1883 fail_timeout=30s max_fails=3;
        server {{MQTT_NODE_3}}:1883 fail_timeout=30s max_fails=3;
        server {{MQTT_NODE_4}}:1883 fail_timeout=30s max_fails=3;
        server {{MQTT_NODE_5}}:1883 fail_timeout=30s max_fails=3;
        server {{MQTT_NODE_6}}:1883 fail_timeout=30s max_fails=3;
        keepalive 32;
    }

    server {
        listen 1883;
        proxy_pass backend_tcp;
    }
}

被动检查的语义:客户端连接失败 3 次(max_fails=3)后,30 秒内不再向该后端转发——完全由"连接失败"驱动,不需要主动探测。

4.3 主动 vs 被动:什么时候用哪个?

维度主动检查被动检查
适用协议HTTP(仅)TCP/UDP/任意四层
检查方式定期 GET 健康路径客户端连接失败计数
摘除速度interval 周期级30s 内响应
副作用后端会收到"无意义的健康探测"零副作用
踩坑点不能与被动同时必须配置 max_fails

结论HTTP 反代用主动(拿到 2xx 200 状态才算健康);stream / MQTT / 数据库连接池用被动(主动检查模块不支持 stream)。

4.4 主动检查可视化(Nginx 自带状态页)

1
2
3
4
5
6
# 启动两个测试后端
docker run -d --name nginx1 --restart=always -p {{PORT_HTTP_1}}:80 nginx:latest
docker run -d --name nginx2 --restart=always -p {{PORT_HTTP_2}}:80 nginx:latest

# 访问状态页
curl http://{{STATUS_HOST}}:{{STATUS_PORT}}/status

输出示例(源文档原文截图对应文字):

1
2
3
4
5
Nginx http upstream check status
Check upstream server number: 2, generation: 1
Index  Upstream  Name                          Status  Rise counts  Fall counts  Check type  Check port
0       cluster  {{HOST}}:{{PORT_HTTP_1}}  up      2            0            tcp          0
1       cluster  {{HOST}}:{{PORT_HTTP_2}}  up      2            0            tcp          0

停掉一个后端docker stop nginx1),状态页会显示 down + Fall counts 递增;两个全挂后服务直接 502——这就是 source 文档实测的"主动检查 + 服务降级"行为。

五、内网穿透双雄:frp 与 cpolar 选型

内网穿透解决"没有公网 IP 时,怎么让外部访问内网服务“的问题。市面上有两类典型玩家:

  • frp(fast reverse proxy):开源、自建、需要一台公网 VPS 当中转
  • cpolar:商业化、零配置、官方中转服务器(有公网域名)

5.1 frp / frpc 速读

维度详情
协议TCP / UDP / HTTP / HTTPS / QUIC
客户端frpc(运行在内网机器)
服务端frps(运行在公网 VPS)
配置格式INI(v0.50 之前)/ TOML(v0.50+)
鉴权token + TLS 可选
性能公网 VPS 带宽上限
部署成本需要 1 台公网 VPS(最低配置 1C1G)

典型 frpc 配置文件片段(公开文档参考):

1
2
3
4
5
6
7
8
9
serverAddr = "x.x.x.x"
serverPort = 7000

[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000

启动后 ssh -oPort=6000 user@x.x.x.x 就能连到内网机器的 22 端口。

5.2 cpolar 速读

维度详情
部署零配置,下载即用
中转官方中转服务器(提供二级公网域名)
限制免费档限带宽、限连接数
适合场景临时演示 / 个人远程
不适合场景长期高带宽、对延迟敏感

5.3 选型建议

  • 自建、自有 VPS、长期使用 → 选 frp
  • 临时演示、个人远程、不想运维 → 选 cpolar
  • 公司有安全合规要求、要求数据走自建 → frp
  • 想用现成公网域名做微信小程序回调 → cpolar

六、选型矩阵:按业务场景一图看懂

业务场景推荐工具理由
经典 Web 反代 + 域名路由Nginx文档最全、运维最熟
Nginx 配置 + 动态生效 + 阿里生态Tengine双 11 验证、Ingress 注解丰富
个人博客 / 小团队 + 想省心Caddy自动 HTTPS + 配置 5 行
K8s/容器编排Traefik动态发现 + Ingress 一等公民
Service Mesh 数据面EnvoyIstio 默认 + xDS 协议
超大流量七层网关(百度级别)BFE国内大厂验证
内网 SSH/MySQL 临时外访frp自建、可控、性能强
个人远程、临时演示cpolar零配置、免运维

七、常见 8 个坑点速查

  1. stream 块里用 nginx_upstream_check_module不支持,主动检查只对 HTTP 生效
  2. 主动检查 + 被动检查同时配置 → 行为未定义,只能二选一
  3. /status 状态页暴露在公网 → 加 allow / deny 或只监听内网 IP
  4. Tengine 迁移后旧证书路径不一致 → 备份+还原时注意 cert/ 相对路径
  5. HTTP/3(QUIC)开启后 443/udp 被防火墙拦 → 提前在 LB/防火墙开 UDP 443
  6. Traefik 监听 Docker 标签后服务起来没路由 → 检查 traefik.enable=true 标签
  7. frpc 配置改完忘 reload → frpc 默认不会自动 reload,用 systemctl restart frpc
  8. cpolar 免费档被限速 → 长期高带宽业务直接换 frp

前置知识 / 下一步

  • 前置:Nginx 基础配置(upstream、location、proxy_pass)、systemd 服务管理
  • 下一步:K8s Ingress 选型(Traefik vs nginx-ingress)、Service Mesh 入门(Envoy + Istio)、CDN 与反代的协同
使用 Hugo 构建
主题 StackJimmy 设计