Amazon SES 利用時、最大送信レート制限に引っかからない方法を考える

| コメントをどうぞ

Amazon SES 利用時、何も考えずメールを大量送信していると以下のようなエラーが出ることがあります。

Maximum sending rate exceeded

最大送信レートを超過したぞ、というエラーメッセージです。

最大送信レートとは

SESのドキュメントには以下のようにあります。

最大送信レート – Amazon SES が 1 秒あたりにアカウントから受け付ける E メールの最大数。この制限を瞬間的に超えることはできますが、制限を超えた状態が長時間続くことは許可されません。

1秒あたりの送信メール数制限ということですね。これを超えると前述のエラーが発生するわけです。

制限に到達した場合、それ以降のメールは送信されず破棄されてしまいます。

どうやって制限を回避するの?

大きく分けて2つの方法が考えられます。

  • Amazon に送信レート制限を引き上げてもらう
    送信レート制限は、基本的に SES の利用制限解除時に申請した数値になっています(利用制限解除方法はこちら
    手順は制限解除のときと同じです。「希望する最大送信レート」の数値を引き上げて申請しましょう。
    ただしあまりにも大きい数値は蹴られます。わたしは 200 を申請して蹴られました。(90までは上げてもらえました)
  • アプリケーションで制御する
    こちらが現実的になると思います。アプリケーション側で最大送信レート制限に達しないように調整を行います。
    ドキュメントには「無作為的に 0~10 分間待機したうえで送信リクエストを再試行するようにアプリケーションをプログラムする必要があります」とあるのみで、具体的なプラクティスは提示されていません。

アプリケーションで制御する

いくつかの実装方法を考えてみました。

エラーをキャッチしたらSleep後にリトライする

ゴリ押し気味ですが、確実性があり簡単な方策。

エラーが発生したら時点で一定時間スリープ後、リトライをかけます。以下は簡単な例。

try {
    SendEmailResult result = client.sendEmail(request);
} catch (AmazonServiceException e) {
    if ("Maximum sending rate exceeded.".equals(e.getMessage())) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            return;
        }
        // リトライ処理
    }
}

エラーを頻発させると Amazon の心象が悪化する気がしなくもないので、送信レート制限分送出した後にも Sleep を入れたほうがいいかもしれません。

キューに送信メッセージを蓄え、一定周期で送出する

送信メッセージを直ちに送出せず、キューに蓄えます。 Timer クラスなどを利用してキューに対してポーリングを行い、送信レート制限分だけ送信メッセージを取り出し、送出します。

デメリットは、オペレーションを行ったユーザが送信エラーを知ることができない点が挙げられます。バッチ処理などなら問題はありませんが。

 

送信レート制限の上限は、運用を続けていると Amazon 側で徐々に引き上げてくれるようです。上限を確認し、必要であれば Sleep やポーリング周期を調整する必要があるでしょう。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>