接口偶发超时,日志里只有一句上下文超时,看不出是数据库慢还是下游接口慢。日志里能对上时间点,这种反而好排。

上下文超时沿调用链传递,父级到期后所有子调用一起中断,真正的耗时点被掩盖。这一点先确认清楚,后面就不用反复试。

ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
defer cancel()
start := time.Now()
rows, err := db.QueryContext(ctx, sql)
log.Printf("db cost=%v err=%v", time.Since(start), err)

围绕「Go 上下文超时」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。偶发问题先统计频率,一小时几次和一天一次,查法完全不同。

改完顺手把文档补一句,省得下次自己重新推一遍。监控和日志的时间要对上,时区不一致会多绕很大一圈。

临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。

处理上按这个顺序:给每层调用设置独立超时并记录耗时;区分取消与超时原因;对下游慢请求单独打点。

结果对不对很好判断,日志能明确指出耗时发生在哪一层,超时请求比例明显下降。

作者 9823189