Rails使用AWS SES发送数千封邮件时应用离线(错误码524)
问题分析与解决方案
问题根源
524是Cloudflare的超时错误,触发原因是你的Rails请求主线程同步执行数千封邮件发送操作,耗时远超Cloudflare默认的100秒响应阈值,导致请求被中断;同时同步循环长时间占用应用线程,使得应用无法处理其他请求,最终引发离线。此外当前实现还有两个额外性能问题:
- 每次发送邮件都新建
Aws::SES::Client实例,重复建立连接增加资源开销 - 逐个调用
send_email接口,API调用次数过多效率低下
解决方案
1. 改用异步任务处理(核心修复)
把邮件发送逻辑从请求主线程移到后台异步任务,避免阻塞请求。Rails自带的Active Job结合Sidekiq/Resque即可实现:
步骤1:生成异步Job
rails generate job SendBulkEmail
步骤2:编写Job代码(复用SES客户端+批量发送)
# app/jobs/send_bulk_email_job.rb class SendBulkEmailJob < ApplicationJob queue_as :default def perform(email_list, subject, html_body) # 复用SES客户端,避免重复建立连接 ses_client = Aws::SES::Client.new(region: 'ap-west-1') sender = 'hello@example.com' encoding = 'UTF-8' text_body = "This email was sent with Amazon SES using the AWS SDK for Ruby." # 拆分邮箱列表为小批量(根据SES发送配额调整,比如50个/批) email_list.each_slice(50) do |batch| begin # 使用SES批量发送接口,减少API调用次数 response = ses_client.send_bulk_email({ source: sender, destinations: batch.map { |email| { to_addresses: [email] } }, message: { subject: { charset: encoding, data: subject }, body: { html: { charset: encoding, data: html_body }, text: { charset: encoding, data: text_body } } } }) # 记录失败的收件人,后续重试 failed_emails = response.failed_recipients.map(&:email_address) SendBulkEmailJob.perform_later(failed_emails, subject, html_body) if failed_emails.any? rescue Aws::SES::Errors::ServiceError => e Rails.logger.error "批量邮件发送失败:#{e.message}" # 可选:将整个批次重新加入队列重试 SendBulkEmailJob.perform_later(batch, subject, html_body) end # 速率控制:避免超过SES发送配额,根据你的配额调整间隔 sleep 1 end end end
步骤3:在控制器中触发异步任务
# 控制器中的处理逻辑 def trigger_bulk_email @emails = ['abc@gmail.com', 'abc@example.com'] # 数千个邮箱 SendBulkEmailJob.perform_later(@emails, @email_subject, @email_body_html) redirect_to your_path, notice: "批量邮件任务已启动,后台将自动处理" end
2. 配置异步任务适配器
以Sidekiq为例:
- 添加Gem到Gemfile:
gem 'sidekiq'
- 安装并配置:
bundle install
- 修改
config/application.rb:
config.active_job.queue_adapter = :sidekiq
- 启动Sidekiq进程处理队列:
bundle exec sidekiq
3. 额外优化建议
- 检查SES配额:在AWS控制台查看SES的发送速率限制和每日配额,调整批量大小和间隔,避免被限流
- 添加日志监控:记录邮件发送状态,方便排查失败原因
- 使用模板邮件:如果邮件内容固定,改用SES的模板邮件接口(
send_templated_email/send_bulk_templated_email),进一步提升效率
内容的提问来源于stack exchange,提问作者user9769384
相关产品推荐
相关产品推荐

