应使用连接池优化数据库性能并异步处理耗时操作。需调优SetMaxOpenConns、SetMaxIdleConns和SetConnMaxLifetime;HTTP handler中仅校验与入队,耗时任务通过channel+goroutine或消息队列异步执行。

用连接池减少数据库开销
数据库连接创建和销毁是高频API的性能瓶颈。Golang标准库的database/sql本身支持连接池,但默认配置偏保守。需显式调优:
- SetMaxOpenConns:控制最大打开连接数,建议设为预期并发请求数的1.5–2倍(如QPS 200,设300),避免排队等待
-
SetMaxIdleConns:空闲连接数建议与
MaxOpenConns一致,减少新建连接频率 - SetConnMaxLifetime:设为5–10分钟,防止长连接因网络中断或数据库侧超时导致的“stale connection”错误
示例初始化:
db, _ := sql.Open("postgres", dsn)db.SetMaxOpenConns(300)
db.SetMaxIdleConns(300)
db.SetConnMaxLifetime(7 * time.Minute)
把耗时操作移出HTTP处理流程
HTTP handler必须快进快出。文件上传、发邮件、写日志到远程服务、复杂计算等,都不该阻塞响应。用channel+goroutine或轻量消息队列解耦:
- 定义任务结构体(如
type ProcessOrderTask struct{ OrderID string; UserID int }) - handler中只做校验和入队:
taskCh ,立即返回202 Accepted - 后台启动固定数量worker goroutine消费channel:
for task := range taskCh { process(task) }
注意:channel需带缓冲(如make(chan Task, 1000)),避免突发流量压垮内存;若需持久化和重试,可换用Redis Stream或NATS。
立即学习“go语言免费学习笔记(深入)”;
复用HTTP客户端连接
若API需频繁调用其他内部服务(如认证中心、用户服务),默认http.DefaultClient会为每次请求新建TCP连接。应自定义client并启用连接复用:
- 设置
Transport.MaxIdleConns和MaxIdleConnsPerHost(如都设为100) - 启用
IdleConnTimeout(如30秒),及时释放空闲连接 - 禁用
ExpectContinueTimeout(设为0),避免小请求多一次RTT
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 100,
IdleConnTimeout: 30 * time.Second,
},
}
避免在handler里做同步I/O密集型操作
常见陷阱包括:同步读大文件、用time.Sleep模拟延迟、调用未设超时的第三方API、序列化超大JSON。这些都会卡住goroutine调度器:
- 文件读取改用
io.Copy流式处理,或异步预加载到内存缓存 - 所有外部HTTP调用必须设
context.WithTimeout,超时时间≤你API的SLA(如整体响应要求≤200ms,则下游调用设≤150ms) - 大JSON响应先用
json.Encoder直接写入http.ResponseWriter,避免json.Marshal生成大byte切片
基本上就这些。吞吐量优化不是堆硬件,而是让每个goroutine尽可能少等、少分配、少切换。










