Async 注解原理分析
场景
邮件、审计或报表生成不应阻塞主请求,但简单加上 @Async 后,可能出现注解失效、线程池耗尽、异常丢失和事务错觉。
原理
Spring 通过后置处理器为目标 Bean 创建代理。外部调用进入拦截器后,任务被提交给 Executor,真正方法在工作线程运行;同类自调用绕过代理,因此不会异步。线程切换也意味着事务、ThreadLocal 和安全上下文不会天然继承。
设计步骤
先确认任务允许异步且定义完成语义;配置有界线程池、队列、拒绝策略和线程名;从另一个 Bean 调用异步方法;需要结果时返回 CompletableFuture;显式传递上下文,并为超时、重试、幂等和异常告警设计处理链。
权衡
异步缩短请求延迟,却没有减少总工作量;大队列看似避免拒绝,实则把故障变成长时间排队和内存压力。内存线程池实现简单,但进程重启会丢任务;可靠任务更适合消息队列或任务平台。
实践建议
按任务类型隔离线程池,监控活跃线程、队列深度、拒绝数和耗时。不要依赖调用方事务提交后异步线程读取未提交数据,可在事务提交后发布事件。重要任务落持久化状态并支持补偿;只有可丢失的短任务才适合纯 @Async。
落地检查
上线前还应做一次桌面演练:准备正常、边界、超时、重复与恶意输入,确认系统的返回、日志和指标彼此对应;在预发布环境模拟依赖不可用、进程重启和配置回滚,验证降级路径不会放大故障。上线时采用小流量观察,提前定义停止条件与负责人。稳定后复盘真实数据,删除没有收益的复杂度,并把新发现的约束补进测试、监控和设计记录,使方案能够随业务持续演进,而不是停留在一次性评审结论。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Dai Wei!
评论

