我只是想讨论一下我面临的情况。
我想向用户发送电子邮件 - 很多电子邮件 - 但如果我在应用程序运行时发送它们,AWS SDK对于电子邮件来说速度慢 - 用户体验不佳 - 至少对我的应用程序而言。
所以我打算做的是在数据库中输入数据(电子邮件地址,要发送的内容,0)并启动一个cron作业来读取表格并开始发送电子邮件 - 一旦发送电子邮件 - 它标记了数据库行为1。
我在某处读到了一个错误的做法,并在数据库服务器上放置了重载。
是的,我会使用智能crons,以便没有2个crons重叠或为偶数和奇数等设置一个cron。我也在寻找第三方替代品,如crons的http://www.iron.io/。
有人可以分享他们在类似情况下的经验等等。我只是想使用智能解决方案,而不仅仅是在数据库上投入大量资源并在交易上花费大量......
答案 0 :(得分:0)
我必须做类似的事情,并且像Charles Engelke建议的那样 - 我使用了SQS。
通过将整个消息内容放在SQS消息中,我完全消除了数据库。你被限制在64k in an SQS message,所以只要这不是问题,这种方法是可行的。
以下是排队邮件的示例代码:
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;
}
}
如果您使用数据库,这种方法的一个缩小是电子邮件发送步骤是HTTP调用。如果您有一个在此HTTP调用后回滚的数据库事务,则会撤消您的业务流程,但会发送该电子邮件。
深思熟虑。
答案 1 :(得分:0)
感谢Mike的详细回复。我最终为我的应用程序实现了一个REST API,它具有安全的用户名+密码+密钥访问权限,并从获得的第三方服务Iron.io运行
www.example.com/rest/messages/format/json
它迭代并发送收集状态的消息在一个数组中 - 然后它回发到
www.example.com/rest/messagesposted
我遵循这种方法,因为我不得不安排消息 间隔90天,队列只保留14天的消息。
你在做什么调查?