订单接口压测 QPS 卡在 1200,火焰图里 StringBuilder.append 占了 18% 的采样,日志那几行全是字符串加号拼接。乍看像缓存或者权限的锅,追下去往往不是。

logger.debug("order={} user={} amount={}", orderNo, userId, amount);
if (logger.isDebugEnabled()) { logger.debug("detail={}", buildDetail()); }

追下去是这么回事:加号拼接在参数求值时就执行,日志级别不够也照样拼完再丢弃。每次都新建 StringBuilder 并复制字符数组,字段越多开销越大。

碰到「日志拼接性能」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。

先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。别只看报错的最后一行,往上看几行,真正的起因通常在上面。

同类问题如果隔一段时间又出现,多半是某个定时任务或重启流程把改动冲掉了。

具体做法是,改用占位符写法 让框架在级别通过后才格式化;大对象先判断 isDebugEnabled;高频日志合并成一条 不要每个字段一行;压测对比改前改后的火焰图。

验收就看一点,火焰图里字符串拼接占比降到 2% 以下 QPS 回到 1600。

作者 9823189