java批量邮件异步群发系统核心是资源可控、压力可缓冲、状态可追踪:采用有界队列+手动配置threadpoolexecutor(核心线程数cpu×1.5~2、最大10~20、队列200~500)+callerrunspolicy/abortpolicy;通过mailqueue内存队列削峰填谷;每封邮件绑定traceid实现全程状态跟踪与查询;复用smtp transport连接提升吞吐。

Java构建高性能批量邮件异步群发系统,核心不在“并发数堆得多”,而在于资源可控、压力可缓冲、状态可追踪。重点是把网络I/O密集型任务从Web请求线程中剥离,用有界队列+合理线程池+统一状态管理形成闭环。
线程池必须手动配置,禁用Executors默认工厂
Executors.newFixedThreadPool()等方法底层使用无界LinkedBlockingQueue,高并发入队极易引发OOM。生产环境应直接使用ThreadPoolExecutor构造:
- 核心线程数设为 CPU 核数 × 1.5~2(如8核机器配12~16),保障基础吞吐不闲置
- 最大线程数控制在10~20之间,避免上下文切换开销反噬性能
- 队列容量设为有界值(推荐200~500),配合拒绝策略使用
- 拒绝策略优先选CallerRunsPolicy(调用方线程执行任务,自然限流)或AbortPolicy(快速失败,便于上层重试)
加一层内存队列实现削峰填谷
业务层不直连线程池,而是先写入阻塞队列,由独立消费者线程拉取执行。这层缓冲能隔离突发流量,防止下游被压垮:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 定义单例MailQueue,内部使用LinkedBlockingQueue(QUEUE_MAX_SIZE = 500)
- Controller接收请求后只做produce入队,响应立即返回
- 启动1~3个固定消费者线程,持续poll队列并submit到邮件执行线程池
- 队列满时直接返回“系统繁忙”,比让整个服务雪崩更可控
每封邮件绑定唯一traceId并全程状态可查
异步不是“发完就丢”,必须支持追溯、补发与监控:
- 提交任务时生成UUID作为traceId,存入ConcurrentHashMap
- EmailStatus包含status(PENDING/SUCCESS/FAILED/TIMEOUT)、sendTime、failReason、retryCount字段
- 异步执行完成后更新状态;超时未完成的PENDING任务由定时任务扫描(如30秒阈值),标记TIMEOUT并告警
- 提供/mail/status?traceId=xxx接口供前端或运维实时查询
复用SMTP连接提升吞吐,避免单邮件单连接
频繁建立/断开TCP连接是性能杀手。应复用Transport实例,在单次连接内批量发送:
- 创建Session后,调用session.getTransport("smtp")获取Transport对象
- transport.connect("sender@xx.com", "auth_code")只需执行一次
- 循环构建MimeMessage,每次调用message.setRecipients(Message.RecipientType.TO, addresses)更新收件人
- 每封邮件调用transport.sendMessage(message, message.getAllRecipients()),共用同一连接
- 全部发送完毕再transport.close()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










