0

私が直面している状況について話し合いたかっただけです。

ユーザー(多くの電子メール)に電子メールを送信したいのですが、アプリケーションの実行時にそれらを送信すると、AWS SDKは電子メールに対して低速になります(ユーザーエクスペリエンスが悪い)。少なくとも私のアプリケーションでは。

したがって、私が計画しているのは、データベースにデータ(メールアドレス、送信するコンテンツ、0)を入力し、cronジョブを起動してテーブルを読み取り、メールの送信を開始することです。メールを送信すると、データベースの行に次のようにマークが付けられます。 1.1。

私はどこかでそれを読んだのは間違った習慣であり、データベースサーバーに過負荷をかけています。

はい、インテリジェントcronを使用して、2つのcronが重複したり、偶数と奇数などにそれぞれcronを設定したりしないようにします。また、cronのhttp://www.iron.io/などのサードパーティの代替案も検討しています。

誰かが同じような状況などで彼らの経験を共有できますか?私はただインテリジェントなソリューションを使用したいだけで、データベースに大量のリソースを置いてトランザクションに多額の費用を費やしたいのではありません...

4

2 に答える 2

0

マイクさん、詳しい回答ありがとうございます。最後に、安全なユーザー名+パスワード+キーアクセスを使用してアプリケーションにREST APIを実装し、それを取得するサードパーティサービスIron.ioから実行することになりました

www.example.com/rest/messages/format/json

メッセージを反復して送信し、配列でステータスを収集します - その後、ポストバックします

www.example.com/rest/messagesposted

90日以上の間隔でメッセージをスケジュールする必要があり、キューはメッセージをたとえば14日間しか保持しないため、このアプローチに従いました。

あなたは何を偵察しますか?

于 2013-03-03T02:35:12.403 に答える
0

私は似たようなことをしなければならず、Charles Engelke が提案したように、SQS を使用しました。

メッセージの内容全体を SQS メッセージに入れることで、データベースを完全に排除しました。SQS メッセージで 64k に制限されているため、それが問題にならない限り、このアプローチは可能です。

メッセージをキューに入れるサンプル コードを次に示します。

package com.softwareconfidence.bsp.sending;

import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.model.SendMessageRequest;
import com.googlecode.funclate.json.Json;

import java.util.HashMap;
import java.util.Map;

public class EmailQueuer  {
    private final AmazonSQS sqs;
    private final String sendQueueUrl;

    public EmailQueuer(AmazonSQS sqs,String sendQueueUrl) {
        this.sqs = sqs;
        this.sendQueueUrl = sendQueueUrl;
    }

    public void queue() {
        Map<String,String> emailModel = new HashMap<String, String>(){{
            put("from","me@me.com");
            put("to","you@you.com");
            put("cc","her@them.com");
            put("subject","Greetings");
            put("body","Hello World");
        }}; 
        sqs.sendMessage(new SendMessageRequest(sendQueueUrl, Json.toJson(emailModel)));
    }
}

次に、アプリで、キューをポーリングしてメッセージを処理するエグゼキューター サービスが必要です。

new ScheduledThreadPoolExecutor(1).scheduleAtFixedRate(sendEmails(), 0, 1, MINUTES)

アプリの終了時に、このエグゼキューターで shutdown() を呼び出すようにする必要があります。とにかく、この行は毎分電子メールを送信します。 sendEmails() は、この Runnable クラスのインスタンスを返します。

package com.softwareconfidence.bsp.standalone.sending;

import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
import com.amazonaws.services.simpleemail.model.*;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.model.DeleteMessageRequest;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.ReceiveMessageResult;
import com.amazonaws.services.sqs.model.SendMessageRequest;
import com.googlecode.funclate.json.Json;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.Map;

public class FromSqsEmailer implements Runnable {
    private final AmazonSQS sqs;
    private final String sendQueueUrl;
    private final String deadLetterQueueUrl;
    private final AmazonSimpleEmailService emailService;

    public FromSqsEmailer(AmazonSimpleEmailService emailService, String deadLetterQueueUrl, String sendQueueUrl, AmazonSQS sqs) {
        this.emailService = emailService;
        this.deadLetterQueueUrl = deadLetterQueueUrl;
        this.sendQueueUrl = sendQueueUrl;
        this.sqs = sqs;
    }

    public void run() {
        int batchSize = 10;
        int numberHandled;
        do {
            ReceiveMessageResult receiveMessageResult =
                    sqs.receiveMessage(new ReceiveMessageRequest(sendQueueUrl).withMaxNumberOfMessages(batchSize));
            final List<com.amazonaws.services.sqs.model.Message> toSend = receiveMessageResult.getMessages();
            for (com.amazonaws.services.sqs.model.Message message : toSend) {
                SendEmailResult sendResult = sendMyEmail(Json.parse(message.getBody()));
                if(sendResult != null) {
                    sqs.deleteMessage(new DeleteMessageRequest(sendQueueUrl, message.getReceiptHandle()));
                }
            }
            numberHandled = toSend.size();
        } while (numberHandled > 0);
    }

    private SendEmailResult sendMyEmail(Map<String, Object> emailModel) {
        Destination to = new Destination()
                .withToAddresses(get("to", emailModel))
                .withCcAddresses(get("cc", emailModel));
        try {
            return emailService.sendEmail(new SendEmailRequest(get("from", emailModel), to, body(emailModel)));
        } catch (Exception e){
            StringWriter stackTrace = new StringWriter();
            e.printStackTrace(new PrintWriter(stackTrace));
            sqs.sendMessage(new SendMessageRequest(deadLetterQueueUrl, "while sending email " + stackTrace));
        }
        return null;
    }

    private String get(String propertyName, Map<String, Object> emailModel) {
        return emailModel.get(propertyName).toString();
    }

    private Message body(Map<String, Object> emailModel) {
        Message message = new Message().withSubject(new Content(get("subject", emailModel)));
        Body body = new Body().withText(new Content(get("body", emailModel)));
        message.setBody(body);
        return message;
    }
}

データベースを使用している場合のこのアプローチのダウンサイズの 1 つは、メール送信ステップが HTTP 呼び出しであることです。この HTTP 呼び出しの後にロールバックするデータベース トランザクションがある場合、ビジネス プロセスは元に戻されますが、電子メールは送信されます。

思考の糧。

于 2013-02-26T18:29:27.663 に答える