Go HTTP服务性能优化需聚焦Handler实现、中间件、序列化和连接管理:避免同步阻塞操作,用context超时控制外部调用;日志异步化;高频对象用sync.Pool复用;启用HTTP/2并复用http.Client;JSON序列化优先静态生成或换msgpack;压测前关闭调试日志、设置GOMAXPROCS、监控GC。

Go 的 HTTP 服务默认性能已经很好,但真实业务中常见的瓶颈往往不出现在框架层,而是出在 http.Handler 实现细节、中间件滥用、序列化开销和连接管理上。
避免在 handler 中做同步阻塞操作
数据库查询、HTTP 调用、文件读写如果没加超时或没走异步,会直接拖垮整个 goroutine 池。Go 的 net/http 默认每个请求分配一个 goroutine,但数量无硬限制,阻塞多了会耗尽系统资源。
- 用
context.WithTimeout包裹所有外部调用,比如db.QueryContext(ctx, ...)或http.DefaultClient.Do(req.WithContext(ctx)) - 不要在 handler 里用
time.Sleep模拟延迟;真要限流,用golang.org/x/time/rate.Limiter - 日志写入避免同步刷盘(如直接写文件),优先走异步 logger(
zerolog.New(os.Stdout)默认就是无锁的)
合理使用 sync.Pool 减少 GC 压力
高频创建小对象(如 JSON 编码用的 bytes.Buffer、自定义结构体)会导致 GC 频繁触发,尤其在 QPS > 1k 的服务中明显。
- 对复用率高的对象建
sync.Pool,例如:var bufferPool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, } - 用完必须清空再放回池子:
b := bufferPool.Get().(*bytes.Buffer); b.Reset(); defer bufferPool.Put(b) - 注意:不能把含指针的对象(如带切片字段的 struct)盲目丢进 pool,可能引发内存泄漏或数据污染
启用 HTTP/2 和连接复用
Go 1.8+ 默认支持 HTTP/2,但只在 TLS 下自动启用;明文 HTTP/1.1 客户端频繁建连会成为瓶颈。
立即学习“go语言免费学习笔记(深入)”;
- 服务端启动时用
http.Server{TLSConfig: ...}启动 HTTPS,客户端就能自动走 HTTP/2 - 客户端务必复用
http.Client实例,设置Transport.MaxIdleConns和MaxIdleConnsPerHost(默认都只有 2) - 避免每次请求都 new
http.Client,它内部的连接池是按实例隔离的
JSON 序列化尽量避开反射
json.Marshal 和 json.Unmarshal 在字段多、嵌套深时开销显著,反射路径比静态代码慢 3–5 倍。
- 字段名固定且不多变时,用
easyjson或ffjson生成静态 marshal/unmarshal 方法 - 或者改用更轻量的格式,比如
msgpack(github.com/vmihailenco/msgpack/v5),体积小、解析快 - 如果只是返回简单结构,手写
WriteTo(w io.Writer)方法,绕过json.Encoder的接口调用开销
最常被忽略的是:压测时没关调试日志、没设 GOMAXPROCS、没检查 runtime.ReadMemStats 看 GC 频率——这些比调优代码本身更能快速定位真实瓶颈。











