反向代理 #

概述 #

反向代理是 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