直接运行二进制代理文件即可启动,但必须验证config.yaml路径、监听端口是否空闲、上游服务是否可达;https代理需配置有效tls证书,否则客户端报ssl握手失败;转发时须同步rawpath并清除hop-by-hop头,高并发下需显式限制transport连接池参数。

直接运行二进制文件就能用,但别跳过配置校验
绝大多数 Go 轻量代理(如 1proxy、vibeproxy、ccproxy)发布时就是一个静态编译的二进制文件,下载后 chmod +x 就能 ./1proxy -c config.yaml 启动。但实际部署失败,90% 是因为没验证三件事:config.yaml 路径是否正确、监听端口是否被占用、上游目标服务是否可达。
常见错误现象:listen tcp :8080: bind: address already in use 或启动后 curl 代理地址返回 connection refused。
- 用
lsof -i :8080(Linux/macOS)或netstat -ano | findstr :8080(Windows)确认端口空闲 - 配置文件路径必须是绝对路径,或确保当前工作目录与
-c参数指向一致 - 如果配置里指定了上游
upstream: https://api.example.com,先手动curl -v https://api.example.com确认网络通路和 TLS 证书有效性
HTTPS 代理必须处理 TLS 证书,否则客户端报错
Go 实现的 HTTP/HTTPS 代理(如 vibeproxy 或自定义 httputil.NewSingleHostReverseProxy)默认不提供中间人证书。浏览器或 curl 访问 HTTPS 目标时,会因证书链不信任而中断连接,报错类似:ssl_error_ssl_handshake_failed(Firefox)或 curl: (35) SSL connect error。
这不是代理代码写错了,而是缺少证书信任链。
- 开发调试:用
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes生成自签名证书,再在代理启动时通过--cert cert.pem --key key.pem加载(需代理支持) - 客户端必须手动将
cert.pem导入系统或浏览器的受信任根证书库,否则无效 - 生产环境不要用自签名;应使用 Let’s Encrypt 的证书,或让代理监听 HTTP,由 Nginx 前置做 TLS 终止
转发规则写错会导致 400/502,重点检查 Host 和 RawPath
用 httputil.NewSingleHostReverseProxy 自定义代理时,最常踩的坑是直接改 req.URL.Host 却忘了同步 req.URL.RawPath,或者没清除 hop-by-hop 头(如 Connection、Keep-Alive),导致上游返回 400 Bad Request 或 502 Bad Gateway。
正确做法是复用官方推荐的 Director 模式:
director := func(req *http.Request) {
req.URL.Scheme = "https"
req.URL.Host = "backend.example.com"
// 必须同步 RawPath,否则含特殊字符的路径会被 double-encode
if req.URL.RawPath != "" {
req.URL.Path = ""
}
// 清除 hop-by-hop 头,否则某些反向代理(如 Nginx)会拒绝请求
for _, h := range hopHeaders {
req.Header.Del(h)
}
}
hopHeaders 应包含:Connection、Keep-Alive、Proxy-Authenticate、Proxy-Authorization、Te、Trailers、Transfer-Encoding、Upgrade。
并发高时内存暴涨?别忽略 Transport 连接池设置
Go 代理在高并发下(比如每秒数百请求)若没调优 http.Transport,会出现内存持续增长甚至 OOM。这不是内存泄漏,而是默认连接池无限制累积 idle 连接。
所有基于 http.Client 转发的代理(包括 ccproxy 内部实现)都依赖这个底层 Transport。
-
MaxIdleConns和MaxIdleConnsPerHost必须显式设为合理值(如 100),否则默认 1000+,极易耗尽 fd -
IdleConnTimeout建议设为 30–90 秒,避免大量长连接闲置占用资源 - 若代理本身要作为客户端访问上游 HTTPS 服务,
TLSHandshakeTimeout和ExpectContinueTimeout也需设(如 5s),防止慢握手拖垮整个连接池
真正容易被忽略的是:这些参数必须在创建 http.Transport 时一次性设定,运行中无法动态修改;且不同代理项目对 Transport 的封装深度不同,有些需要 patch 源码才能暴露配置入口。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











