默认http.DefaultTransport生产环境不可直接使用:无超时导致goroutine永久阻塞,MaxIdleConnsPerHost默认仅2引发高频建连,IdleConnTimeout为0致fd泄漏,且不处理Cookie与重定向。

默认的 http.DefaultTransport 在生产环境几乎不可直接使用——它没设任何超时、连接池极小、空闲连接永不释放,很容易导致请求堆积、连接耗尽、goroutine 泄漏。
不设超时,请求会永久卡死
默认 Transport 的 DialContext、TLSHandshakeTimeout、ResponseHeaderTimeout 全为 0,意味着:DNS 解析失败、TCP 连接卡住、TLS 握手挂起、服务端迟迟不发响应头……都会让 goroutine 一直阻塞,直到客户端被系统 kill 或进程重启。
- 不要指望
context.WithTimeout包裹client.Do就能解决——它无法中断正在建连的 TCP 握手 - 必须显式配置
Transport的各阶段超时,尤其是DialContext(含 DNS + TCP)和TLSHandshakeTimeout -
ResponseHeaderTimeout控制从发完请求到收到第一个字节响应头的时间,防后端“只写不发”
连接池太小,高并发下频繁建连
默认 MaxIdleConns 是 100,MaxIdleConnsPerHost 是 2,这意味着:同一域名最多只缓存 2 个空闲连接;超过的请求全得新建 TCP 连接,TLS 握手开销大,延迟陡增,还容易触发服务端连接数限制。
- 线上建议至少设
MaxIdleConnsPerHost: 100,避免单 host 成为瓶颈 -
IdleConnTimeout默认是 0(永不超时),必须设为 30–90 秒,否则空闲连接长期占着 fd 不释放 - HTTP/2 下复用更激进,但前提是 Transport 没禁用它;别碰已废弃的
ForceAttemptHTTP2
没有自动处理 Cookie 和重定向逻辑
http.DefaultTransport 本身不管理 Cookie,也不干预重定向——这些行为由 http.Client 层控制。但很多人误以为 “用了 DefaultTransport 就等于用了 DefaultClient”,结果:client.CheckRedirect 没配,重定向跳 10 次才停;client.Jar 没设,登录态无法透传。
立即学习“go语言免费学习笔记(深入)”;
- Transport 只管“怎么连”,Cookie 和重定向是 Client 层职责,二者不能混为一谈
- 若需自定义跳转逻辑(比如只允许同域跳转),必须在
http.Client上设CheckRedirect函数 - 需要维持会话时,务必给 client 显式赋值
http.CookieJar,别依赖默认 nil 值
真正难的不是把 Transport 配对,而是理解每个字段生效的位置:DialContext 管建连,TLSHandshakeTimeout 管握手,ResponseHeaderTimeout 管首字节,IdleConnTimeout 管连接回收——少设一个,就可能在线上某个边缘场景里静默拖垮整个服务。


















