簡體   English   中英

AWS SES:如何發送大量電子郵件(一次 > 10000)

[英]AWS SES: how to send a large amount of emails (> 10000 at a time)

我正在構建一個電子郵件發送服務(lambda、Nodejs),它將同時向地址列表發送電子郵件。

因為需求:每個地址接收不同的郵件內容,我不能一個請求發送多封郵件,而是一個一封。

_array = ... // list of address + html content, > 10000 records
for (var i = 0; i < _array.length; i++) {
    var params = {
        Destination: {/* required */
            ToAddresses: [_array[i].email]
        },
        Message: {/* required */
            Body: { /* required */
                Html: {
                    Data: _array[i].html,
                    Charset: 'UTF-8'
                },
            },
            Subject: { /* required */
                Data: 'Your order detail', /* required */
                Charset: 'UTF-8'
            }
        },
        Source: "mytestemail@email.com"
    }

    let send = await ses.sendEmail(params).promise();

}

目前,我沒有要測試的大數據,但是我測試了 100-200 封電子郵件,它正在工作,並且需要 15-40 秒才能完成發送電子郵件。 從數學上講,10000 需要超過 25 分鍾才能完成任務。 因此,這種方法不可擴展,因為 lambda 超時限制為 15 分鍾

任何更好的方法或建議表示贊賞。

編輯:

@Thales Minussi 的解決方案很棒,我實現了它並且它正在工作。 我將其標記為答案,但我仍然歡迎所有解決此問題的最佳實踐。 快樂地分享、學習和編碼

不推薦:可以做的是並行化sendEmail調用。 所以你可以創建一個很大的 Promises 數組,然后使用await Promises.all(yourPromisesArray) ,所以 Node.js 會根據你運行 Lambda 函數的機器上可用的內核數量盡力優化這個過程,意思是要充分利用它,您需要將 Lambda 的 RAM 內存設置為 3GB(機器與 RAM 量成正比,這意味着您設置的 RAM 越多,代碼運行的機器就越好) . 但這仍然是錯誤的,因為現在我們談論的是 10000 封電子郵件,但是如果這個數字增長到 100000 呢? 100萬? 這只是一種解決方案,無法隨着需求的增長而擴展到足以滿足需求,因此這還不夠。 另一件事是,如果出現問題(例如一個 Promise 失敗),則很難恢復。

推薦:我建議您使用 SQS 將創建電子郵件正文的函數與實際發送它的函數分離,長話短說,而不是調用await ses.sendEmail(params).promise()作為你在上面做的,你應該把這個消息放在一個 SQS 隊列中(尊重每條消息 256KB 的限制),並將另一個 Lambda 訂閱到這個 SQS 隊列。 每個 Lambda 最多可以從 SQS 讀取 10 條消息(並且每條消息可以包含許多電子郵件),這會顯着加快進程,特別是因為默認情況下,您的 Lambda 函數將擴展以滿足需求。

讓我們進行一個簡單的數學計算:如果您向 SQS 發送 100 條消息,並且每條消息都有 10 封電子郵件,這意味着,在最佳情況下,將啟動 10 個 Lambda,每個消耗一批 10 條消息,但因為每條消息包含 10電子郵件,每個 Lambda 將處理 100 封電子郵件,因此您將在眨眼間處理 1000 封電子郵件!

重要的是要注意,並非所有 Lambda 每次都會提取 10 個批次,它們可能會提取較小的批次,因此可能會發生 10 個以上的 Lambda 函數同時啟動,但我認為您了解並行處理的想法

編輯:由於電子郵件可以由大量負載(圖像、長字符串等)組成,我建議您僅將相關信息發送到 SQS 隊列以優化負載大小。 如果您需要處理圖像或一些預定義的模板,只需在 S3(或您可能使用的其他存儲)中發送它們各自的位置,以便實際負責發送電子郵件的 Lambda 是獲取該信息的那個並將其添加到正文中。 本質上,您發送給 SQS 的消息應該只包含元數據,以盡可能保持有效負載的輕量級,這樣您就可以利用 256KB 的限制。 這樣的事情應該足以讓你離開地面:

{
    "to": "to@email.com",
    "images": ["s3://bucket/image.jpg", "s3://bucket/image2.jpg"],
    "template": "s3://bucket/template.html"
}

架構流程

太晚了,但這是我想出的架構。 Cloudwatch 規則在特定時間觸發。 它調用一個 lambda。 lambda 獲取在此特定時間發送的所有電子郵件的計數,將其分塊為 10 個塊,然后將每個 10 個塊發布到 SNS“send_email_topic”的主題,該主題進一步調用發送電子郵件的 lambda . 從 SNS 調用的每個 lambda 都會收到塊大小,在我們的例子中是 10 和偏移值。 調用的 lambda 命中數據庫並獲取要發送的電子郵件行,將塊大小作為限制和偏移量(偏移量以避免不同的 lambdas 發送相同的電子郵件)並發送電子郵件。 每個調用的 lambda 將發送多達 10 封電子郵件。

失敗

如果電子郵件失敗,電子郵件 ID 將被發送到隊列。 SQS 在收到消息時將發布到 SNS 上不同的主題“retry_email_send”,該主題將再次調用 lambda,但稍有不同的 lambda 會接收要重試的電子郵件的電子郵件 ID,從數據庫中獲取單個電子郵件並重試

重點說明

  1. 您需要增加 Lambda 的超時時間。 300 秒是最大限制。
  2. SES 可能不是其配額限制的最佳選擇,您可能需要專用的 SMTP 服務器。
  3. 您也可以選擇 SendGrid,因為它無需任何設置即可提供所有這些,除非您嘗試制作類似 sendgrid 本身的東西

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM