[英]how to ensure that an email is read only once by one of the server in multiserver environment while using JavaMail API
我有一个要求作为其中一部分,我想从outlook读取传入的电子邮件,然后做一些处理。我正在使用JavaMail API和IMAP协议来实现这一点。我编写了一个java类,它读取messagesAdded事件的电子邮件。
在单一服务器环境中使用以下代码完美地工作正常,但是当我将其部署到我们有2台服务器的生产时,由于在两台服务器上部署了相同的代码,因此我们最终处理每封电子邮件两次,两者都试图在收到邮件后再次阅读在邮箱中。
以下是我用来连接邮箱和阅读电子邮件的代码段:
try {
Properties props = System.getProperties();
// Get a Session object
Session session = Session.getInstance(props, null);
// session.setDebug(true);
// Get a Store object
Store store = session.getStore("imap");
// Connect
store.connect(argv[0], argv[1], argv[2]);
// Open a Folder
Folder folder = store.getFolder(argv[3]);
if (folder == null || !folder.exists()) {
System.out.println("Invalid folder");
System.exit(1);
}
folder.open(Folder.READ_WRITE);
// Add messageCountListener to listen for new messages
folder.addMessageCountListener(new MessageCountAdapter() {
public void messagesAdded(MessageCountEvent ev) {
Message[] msgs = ev.getMessages();
System.out.println("Got " + msgs.length + " new messages");
// Process incoming mail.
} catch (Exception ex) {
ex.printStackTrace();
}
关于如何限制在多服务器环境中仅处理一次电子邮件的任何建议?
也许最简单的解决方法是使用分布式锁; 有很好的图书馆。 但是如果你想在javamail中找到答案,那么有两种方法。
首先,您可以使用Flag并调用message.isSet()来检查其他服务器是否已设置标志,然后将message.setFlags()锁定。 不幸的是那场比赛。 可以通过一些不合适的hackery来修复竞争,这些hackery涉及另外两个标志或者一个名为condstore的IMAP扩展 ,javamail显然不支持 - 只有当标志没有改变时, setFlags()需要一个新的long
参数来设置标志自从客户最后注意到。
其次,您可以使用邮箱的进度并通过它移动邮件。 您需要四个邮箱,即收件箱和另外三个称为“processing-a”,“processing-b”和“processed”的邮箱。 服务器A处理“处理-a”中的所有消息,然后将每个消息移动到“已处理”,B处理“处理-b”。 当每个服务器完成其“processing- foo ”时,它会在收件箱中查找新消息,并调用moveMessages()将一个或几个消息原子地移动到它自己的邮箱。 moveMessages()使用名为move的IMAP扩展以原子方式移动消息,并且大多数服务器都支持,但不是全部。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.