队列满之后接口线程池的 Tomcat 工作线程全部在执行导出任务,新请求连不进来,健康检查也开始超时,整个实例被摘掉。第一次遇到会往复杂处想,其实漏掉的多是个小前提。
if (!pool.getQueue().offer(task)) {
throw new RejectedExecutionException("export queue full");
}
CallerRunsPolicy 让提交任务的线程自己执行,这里是 Tomcat 的请求线程。导出任务跑几十秒,Web 线程被占住,接收队列跟着堆满。这一点先确认清楚,后面就不用反复试。
「CallerRunsPolicy 反压」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。
备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。
具体做法是,Web 线程池提交任务时不要用 CallerRunsPolicy;队列满时直接拒绝 返回 429 让上游限流;异步任务用独立池 和请求线程彻底分开;压测把队列打满 确认 Tomcat 线程数没有跟着涨。
改完照着核一遍,队列满时接口返回 429,Tomcat 工作线程数保持在基线,健康检查正常。
