故障期间一个空指针在循环里刷,日志量冲到 8000 条每秒。日志框架的 ratelimiter 配了每秒 100 条,超出部分直接丢弃,事后只能看到前 100 条,堆栈还被截断。日志里能对上时间点,这种反而好排。
限流按 logger 名计数,同一个 logger 的 INFO 和 ERROR 共用配额,异常把额度吃光后关键日志也写不进去。丢弃时没有任何计数输出,看起来像日志突然中断。下游 Loki 的 ingest 限流又丢了一次,两处叠加。这一点先确认清楚,后面就不用反复试。
logging.rate.limit=100 logging.rate.limit.exclude=ERROR logging.rate.suppressed.report=1s
「日志限流丢弃」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。
处理上按这个顺序:给 ERROR 单独开一条不限流的 appender;限流丢弃时按秒打一行 suppressed 计数 保留可观测性;同类异常做 1 分钟去重 只保留首条和最后一条;把日志平台的 ingest 限额一起核对 别让它二次丢弃。
结果对不对很好判断,故障复现时 ERROR 全部落盘,日志里能看到每秒 suppressed=7900 的统计行。
