必须显式配置ReadTimeout、WriteTimeout和IdleTimeout三类超时,复用bytes.Buffer等对象减少GC,禁用http.DefaultServeMux改用独立ServeMux,启用HTTP/2需正确配置TLS。

用 http.Server 配置超时,避免连接堆积
HTTP 服务卡顿的常见原因是长连接不释放、慢请求拖垮整个服务。Go 默认的 http.Server 没有设置任何超时,一旦后端依赖(如数据库、第三方 API)响应慢,goroutine 就会一直挂着,内存和文件描述符持续增长。
必须显式配置三类超时:
-
ReadTimeout:从客户端读取请求头和请求体的总时间上限(含 TLS 握手) -
WriteTimeout:从服务端写完响应头+响应体的总时间上限 -
IdleTimeout:Keep-Alive 连接空闲等待新请求的最长时间(推荐设为 30–60s)
示例:
srv := &http.Server{
Addr: ":8080",
Handler: myMux,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 60 * time.Second,
}注意:ReadTimeout 和 WriteTimeout 不覆盖中间件或 handler 内部耗时;它们只管网络 I/O 阶段。真正耗时的业务逻辑仍需单独加 context 超时控制。
立即学习“go语言免费学习笔记(深入)”;
用 sync.Pool 复用 HTTP 相关对象,减少 GC 压力
高频 HTTP 服务中,http.Request 和 http.ResponseWriter 本身不可复用,但它们携带的底层缓冲区(如 bytes.Buffer、json.Encoder)可以池化。尤其在 JSON API 场景下,反复 new bytes.Buffer 会导致大量小对象分配,触发频繁 GC。
典型可池化对象:
-
*bytes.Buffer:用于序列化响应体 -
*json.Encoder:绑定到bytes.Buffer后可复用 - 自定义结构体(如带预分配字段的响应 wrapper)
示例(复用 bytes.Buffer):
var bufferPool = sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
func jsonHandler(w http.ResponseWriter, r http.Request) {
buf := bufferPool.Get().(bytes.Buffer)
buf.Reset()
defer bufferPool.Put(buf)
enc := json.NewEncoder(buf)
enc.Encode(map[string]string{"status": "ok"})
w.Header().Set("Content-Type", "application/json")
w.Write(buf.Bytes())}
注意:池中对象无生命周期保证,不能存任何跨请求的上下文数据;每次取用后必须 Reset(),否则残留内容会污染后续响应。
网趣网上购物系统HTML静态版
网趣购物系统静态版支持网站一键静态生成,采用动态进度条模式生成静态,生成过程更加清晰明确,商品管理上增加淘宝数据包导入功能,与淘宝数据同步更新!采用领先的AJAX+XML相融技术,速度更快更高效!系统进行了大量的实用性更新,如优化核心算法、增加商品图片批量上传、谷歌地图浏览插入等,静态版独特的生成算法技术使静态生成过程可随意掌控,从而可以大大减轻服务器的负担,结合多种强大的SEO优化方式于一体,使
下载
禁用 http.DefaultServeMux,改用轻量路由或直接 http.ServeMux
用 http.HandleFunc 注册路由看似方便,实则暗藏性能隐患:它默认往全局 http.DefaultServeMux 注册,而该 mux 是线程安全的(内部用 sync.RWMutex),高并发下所有路由匹配都争抢同一把读锁,成为瓶颈。
更优做法:
- 显式创建
http.ServeMux实例(无锁,纯 map 查找) - 对简单路径前缀路由足够用;复杂场景优先考虑
chi或gorilla/mux(它们内部已做 trie 优化) - 完全避免
http.DefaultServeMux,防止第三方库悄悄注册路由导致冲突或锁竞争
示例:
mux := http.NewServeMux()
mux.HandleFunc("/api/users", usersHandler)
mux.HandleFunc("/health", healthHandler)
http.ListenAndServe(":8080", mux)
注意:http.ServeMux 只支持前缀匹配(如 /api/),不支持通配符或正则;若需要路径参数(如 /user/{id}),必须换专用路由器,别硬套 ServeMux。
启用 HTTP/2 和连接复用,但小心 TLS 配置陷阱
Go 1.8+ 默认支持 HTTP/2,但仅当服务启用 TLS 且满足条件时才自动协商。未配好 TLS 会导致降级回 HTTP/1.1,失去多路复用、头部压缩等优势。
关键检查点:
- 证书必须有效(非自签名,或客户端信任该 CA)
- 使用
http.Server.TLSConfig显式配置,并开启NextProtos: []string{"h2", "http/1.1"} - 避免在
TLSConfig.CipherSuites中禁用所有 ALPN 支持的密钥套件(如移除TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384等) - 监听必须用
srv.ListenAndServeTLS(),不能混用ListenAndServe()+ 反向代理 TLS
示例最小 TLS 启动:
srv := &http.Server{
Addr: ":443",
Handler: mux,
TLSConfig: &tls.Config{
NextProtos: []string{"h2", "http/1.1"},
},
}
srv.ListenAndServeTLS("cert.pem", "key.pem")注意:本地开发用自签名证书时,客户端(如 curl、浏览器)可能拒绝协商 HTTP/2;验证是否生效,用 curl -v https://localhost 看响应头是否有 ALPN: h2,而非只看是否走 HTTPS。










