You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel集成AWS SES/SNS大规模邮件通知服务器负载过高优化咨询

解决SES+SNS批量邮件通知导致服务器资源耗尽的问题

针对你用Laravel+AWS SDK开发邮件营销系统时,一万条SEND/DELIVERY通知拉满服务器CPU和内存的问题,我给你几个实用的解决方案,从AWS配置到Laravel代码优化都有覆盖:

1. 开启SES的批量事件通知(最直接的减少通知数量方法)

AWS SES本身支持将多个相同类型的事件合并成一个SNS通知发送,不用再逐条推送。你可以通过配置集(Configuration Set)来开启这个功能,设置批量大小和等待间隔:

代码配置(用AWS SDK for PHP)

use Aws\Ses\SesClient;

// 初始化SES客户端
$sesClient = new SesClient([
    'version' => 'latest',
    'region' => '你的AWS区域', // 比如us-east-1
    'credentials' => [
        'key' => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
    ],
]);

// 更新配置集的事件目标,开启批量通知
$sesClient->updateConfigurationSetEventDestination([
    'ConfigurationSetName' => '你的营销活动配置集名称',
    'EventDestination' => [
        'Name' => 'SnsNotificationDestination',
        'Enabled' => true,
        'MatchingEventTypes' => ['send', 'delivery'], // 你需要监听的事件类型
        'SnsDestination' => [
            'TopicARN' => '你的SNS主题ARN',
        ],
        'BatchConfigurations' => [
            'BatchSize' => 100, // 每攒够100条事件就发送一个通知
            'BatchInterval' => 300, // 最多等待5分钟(300秒),到点不管够不够都发送
        ],
    ],
]);

这样原本一万条的通知会被合并成最多100个(按100条/批),直接把请求量降到原来的1%,服务器压力会大幅降低。

2. 用Laravel队列异步处理通知

即使开启了批量通知,短时间内的批量请求还是可能压垮服务器,这时候把通知处理逻辑放到队列里异步执行是必须的:

步骤1:创建队列任务

生成一个处理SES通知的任务类:

php artisan make:job ProcessSesBatchNotification

然后在任务类里处理批量事件:

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Aws\Sns\MessageValidator;

class ProcessSesBatchNotification implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $snsPayload;

    public function __construct(array $snsPayload)
    {
        $this->snsPayload = $snsPayload;
    }

    public function handle()
    {
        // 先验证SNS消息的真实性,防止伪造请求
        $validator = new MessageValidator();
        $validator->validate($this->snsPayload);

        // 解析SNS消息内容
        $messageContent = json_decode($this->snsPayload['Message'], true);
        
        // 如果是批量通知,Messages是事件数组;否则是单条事件
        $events = isset($messageContent['Messages']) ? $messageContent['Messages'] : [$messageContent];

        // 批量收集统计数据,减少数据库操作
        $notificationRecords = [];
        foreach ($events as $event) {
            $parsedEvent = json_decode($event['Message'], true);
            $notificationRecords[] = [
                'message_id' => $parsedEvent['mail']['messageId'],
                'event_type' => $parsedEvent['eventType'],
                'timestamp' => $parsedEvent['timestamp'],
                'created_at' => now(),
                'updated_at' => now(),
            ];
        }

        // 批量插入数据库,比逐条插入高效得多
        if (!empty($notificationRecords)) {
            \App\Models\SesNotification::insert($notificationRecords);
        }
    }
}

步骤2:配置SNS Webhook路由

在routes/api.php里添加接收SNS通知的路由,直接把请求丢到队列:

use App\Jobs\ProcessSesBatchNotification;
use Illuminate\Http\Request;

Route::post('/ses/sns/webhook', function (Request $request) {
    // 立即分发任务到队列,快速响应SNS,避免超时
    ProcessSesBatchNotification::dispatch($request->all());
    
    // 返回200给SNS,确认接收
    return response()->json(['status' => 'received'], 200);
});

3. 可选:用Lambda中转处理通知

如果你的服务器资源还是紧张,可以加一层AWS Lambda作为中转:

  • 让SNS把批量通知推送给Lambda
  • Lambda把所有事件整理后,一次性批量调用Laravel的API(或者直接写入数据库)
  • Laravel只需要处理少量的批量请求,彻底避免高频请求的压力

这种方式适合超大规模的邮件活动,能进一步解耦通知接收和业务处理。

关键注意事项

  • 一定要验证SNS消息:防止恶意请求伪造通知,上面的代码里已经包含了验证逻辑,不要省略。
  • 优化队列配置:用Supervisor管理Laravel队列worker,设置合适的进程数(比如根据CPU核心数设置),避免队列堆积。
  • 测试批量效果:先发送100条邮件测试,确认SNS确实会合并成一个通知,再跑大规模活动。

内容的提问来源于stack exchange,提问作者Ivan Vasilega

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:25:14