反向代理 #
概述 #
反向代理是 Caddy 的核心功能之一,可以将请求转发到后端服务器,同时提供负载均衡、健康检查、WebSocket 支持等高级功能。
text
┌─────────────────────────────────────────────────────────────┐
│ 反向代理架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 客户端 ──→ Caddy (反向代理) ──→ 后端服务器 │
│ │ │
│ ├── 负载均衡 │
│ ├── 健康检查 │
│ ├── SSL 终止 │
│ ├── 压缩 │
│ └── 缓存 │
│ │
└─────────────────────────────────────────────────────────────┘
基本配置 #
最简单的代理 #
caddyfile
example.com {
reverse_proxy localhost:3000
}
完整代理配置 #
caddyfile
example.com {
reverse_proxy localhost:3000 {
# 健康检查
health_uri /health
health_interval 10s
health_timeout 5s
# 超时设置
transport http {
read_timeout 30s
write_timeout 30s
}
# 头部处理
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
代理目标 #
单个后端 #
caddyfile
example.com {
reverse_proxy localhost:3000
}
# 或使用完整地址
example.com {
reverse_proxy 127.0.0.1:3000
}
多个后端(负载均衡) #
caddyfile
example.com {
reverse_proxy {
to localhost:3000
to localhost:3001
to localhost:3002
}
}
Unix Socket #
caddyfile
example.com {
reverse_proxy unix//var/run/app.sock
}
动态后端 #
caddyfile
example.com {
reverse_proxy {
# 使用 SRV 记录发现
dynamic srv {
service app
proto tcp
}
}
}
负载均衡策略 #
轮询(默认) #
caddyfile
example.com {
reverse_proxy {
to localhost:3000
to localhost:3001
to localhost:3002
lb_policy round_robin
}
}
最少连接 #
caddyfile
example.com {
reverse_proxy {
to localhost:3000
to localhost:3001
to localhost:3002
lb_policy least_conn
}
}
IP 哈希 #
caddyfile
example.com {
reverse_proxy {
to localhost:3000
to localhost:3001
to localhost:3002
lb_policy ip_hash
}
}
随机选择 #
caddyfile
example.com {
reverse_proxy {
to localhost:3000
to localhost:3001
to localhost:3002
lb_policy random
}
}
URI 哈希 #
caddyfile
example.com {
reverse_proxy {
to localhost:3000
to localhost:3001
to localhost:3002
lb_policy uri_hash
}
}
带权重的负载均衡 #
caddyfile
example.com {
reverse_proxy {
to localhost:3000 {
weight 3
}
to localhost:3001 {
weight 2
}
to localhost:3002 {
weight 1
}
lb_policy weighted_round_robin
}
}
健康检查 #
被动健康检查 #
caddyfile
example.com {
reverse_proxy {
to localhost:3000
to localhost:3001
# 被动健康检查
fail_duration 30s
max_fails 3
unhealthy_status 500 502 503 504
unhealthy_latency 5s
}
}
主动健康检查 #
caddyfile
example.com {
reverse_proxy {
to localhost:3000
to localhost:3001
# 主动健康检查
health_uri /health
health_port 3000
health_interval 10s
health_timeout 5s
health_status 200
health_body "OK"
# 健康检查头部
health_headers {
X-Health-Check "true"
}
}
}
健康检查参数说明 #
| 参数 | 说明 | 默认值 |
|---|---|---|
health_uri |
健康检查路径 | / |
health_port |
健康检查端口 | 后端端口 |
health_interval |
检查间隔 | 30s |
health_timeout |
超时时间 | 5s |
health_status |
期望状态码 | 200 |
health_body |
期望响应体 | - |
fail_duration |
失败持续时间 | - |
max_fails |
最大失败次数 | 1 |
unhealthy_status |
不健康状态码 | - |
unhealthy_latency |
不健康延迟 | - |
头部处理 #
添加请求头部 #
caddyfile
example.com {
reverse_proxy localhost:3000 {
# 添加头部
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Host {host}
header_up X-Request-ID {uuid}
}
}
删除请求头部 #
caddyfile
example.com {
reverse_proxy localhost:3000 {
# 删除头部
header_up -Cookie
header_up -Authorization
# 删除响应头部
header_down -Server
header_down -X-Powered-By
}
}
修改响应头部 #
caddyfile
example.com {
reverse_proxy localhost:3000 {
# 添加响应头部
header_down X-Served-By "Caddy"
# 修改响应头部
header_down Set-Cookie ".*" "Secure; HttpOnly"
# 删除响应头部
header_down -X-Powered-By
}
}
常用代理头部 #
caddyfile
example.com {
reverse_proxy localhost:3000 {
# 标准代理头部
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Port {server_port}
}
}
WebSocket 支持 #
自动 WebSocket 代理 #
caddyfile
# Caddy 自动处理 WebSocket 升级
ws.example.com {
reverse_proxy localhost:3000
}
显式 WebSocket 配置 #
caddyfile
ws.example.com {
reverse_proxy localhost:3000 {
# WebSocket 超时
transport http {
read_timeout 0
write_timeout 0
}
}
}
WebSocket 路径匹配 #
caddyfile
example.com {
# WebSocket 路径
handle /ws/* {
reverse_proxy localhost:3001
}
# HTTP API
handle /api/* {
reverse_proxy localhost:3000
}
# 静态文件
handle {
root * /var/www/html
file_server
}
}
超时配置 #
基本超时 #
caddyfile
example.com {
reverse_proxy localhost:3000 {
transport http {
# 读取超时
read_timeout 30s
# 写入超时
write_timeout 30s
# 拨号超时
dial_timeout 10s
# TLS 握手超时
tls_timeout 10s
}
}
}
长连接配置 #
caddyfile
example.com {
reverse_proxy localhost:3000 {
transport http {
# 保持连接
keepalive 90s
keepalive_idle_conns 10
# 禁用连接池
# keepalive off
}
}
}
SSL/TLS 配置 #
代理到 HTTPS 后端 #
caddyfile
example.com {
reverse_proxy https://backend.example.com {
# 信任后端证书
transport http {
tls
tls_insecure_skip_verify
}
}
}
自定义 TLS 配置 #
caddyfile
example.com {
reverse_proxy https://backend.example.com {
transport http {
tls {
# 使用自定义 CA
trusted_ca_file /etc/ssl/certs/ca.pem
# 客户端证书
client_certificate_file /etc/ssl/client.pem
client_certificate_key_file /etc/ssl/client.key
}
}
}
}
流式传输 #
禁用缓冲 #
caddyfile
stream.example.com {
reverse_proxy localhost:3000 {
# 禁用响应缓冲
flush_interval -1
transport http {
read_timeout 0
write_timeout 0
}
}
}
SSE(Server-Sent Events) #
caddyfile
sse.example.com {
reverse_proxy localhost:3000 {
# SSE 流式传输
flush_interval -1
}
}
大文件上传 #
caddyfile
upload.example.com {
reverse_proxy localhost:3000 {
transport http {
read_timeout 300s
write_timeout 300s
}
}
}
路径重写 #
去除路径前缀 #
caddyfile
example.com {
# /api/users -> /users
handle_path /api/* {
reverse_proxy localhost:3000
}
}
添加路径前缀 #
caddyfile
example.com {
handle /app/* {
reverse_proxy localhost:3000 {
# /app/users -> /v1/app/users
rewrite * /v1{uri}
}
}
}
正则重写 #
caddyfile
example.com {
handle /api/v*/* {
reverse_proxy localhost:3000 {
# /api/v1/users -> /users
uri strip_prefix /api/v*
}
}
}
高级配置 #
重试机制 #
caddyfile
example.com {
reverse_proxy {
to localhost:3000
to localhost:3001
# 失败重试
fail_duration 10s
max_retries 3
try_duration 30s
}
}
连接限制 #
caddyfile
example.com {
reverse_proxy localhost:3000 {
transport http {
# 最大空闲连接
max_idle_conns 100
# 每主机最大空闲连接
max_idle_conns_per_host 10
# 连接超时
dial_timeout 5s
}
}
}
响应缓冲 #
caddyfile
example.com {
reverse_proxy localhost:3000 {
# 响应缓冲大小
flush_interval 100ms
}
}
完整示例 #
微服务网关 #
caddyfile
api.example.com {
# 用户服务
handle /users/* {
reverse_proxy localhost:3001 {
header_up X-Service "users"
}
}
# 订单服务
handle /orders/* {
reverse_proxy localhost:3002 {
header_up X-Service "orders"
}
}
# 产品服务
handle /products/* {
reverse_proxy {
to localhost:3003
to localhost:3004
lb_policy round_robin
health_uri /health
}
}
# WebSocket 服务
handle /ws/* {
reverse_proxy localhost:3005 {
flush_interval -1
}
}
# 默认路由
handle {
respond "Not Found" 404
}
}
Node.js 应用代理 #
caddyfile
app.example.com {
reverse_proxy localhost:3000 {
# 标准代理头部
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
# WebSocket 支持
transport http {
read_timeout 0
write_timeout 0
}
# 健康检查
health_uri /health
health_interval 30s
}
# 日志
log {
output file /var/log/caddy/app.log
}
}
Python/Django 应用 #
caddyfile
django.example.com {
reverse_proxy localhost:8000 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
# 静态文件直接服务
@static path /static/* /media/*
handle @static {
root * /var/www/django
file_server
}
}
}
PHP-FPM #
caddyfile
php.example.com {
root * /var/www/html
# PHP 文件代理到 PHP-FPM
php_fastcgi localhost:9000
# 静态文件
file_server
}
多环境配置 #
caddyfile
# 开发环境
dev.example.com {
reverse_proxy localhost:3000 {
header_up X-Environment "development"
}
}
# 测试环境
test.example.com {
reverse_proxy {
to test-server-1:3000
to test-server-2:3000
lb_policy round_robin
}
}
# 生产环境
example.com {
reverse_proxy {
to prod-server-1:3000 weight 3
to prod-server-2:3000 weight 2
to prod-server-3:3000 weight 1
lb_policy weighted_round_robin
health_uri /health
health_interval 10s
fail_duration 30s
max_fails 3
}
}
故障排查 #
检查代理状态 #
bash
# 查看后端状态
curl localhost:2019/reverse_proxy/upstreams
# 输出示例
[
{
"address": "localhost:3000",
"healthy": true,
"requests": 100,
"fails": 0
}
]
常见问题 #
caddyfile
# 问题1:WebSocket 连接断开
# 解决:增加超时时间
reverse_proxy localhost:3000 {
transport http {
read_timeout 0
write_timeout 0
}
}
# 问题2:大文件上传失败
# 解决:增加超时和缓冲区
reverse_proxy localhost:3000 {
transport http {
read_timeout 300s
write_timeout 300s
}
}
# 问题3:后端获取不到真实 IP
# 解决:添加代理头部
reverse_proxy localhost:3000 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}
下一步 #
现在你已经掌握了反向代理配置,接下来学习 负载均衡 深入了解负载均衡策略!
最后更新:2026-03-28