0

我有一个要求,其中我想读取来自 Outlook 的传入电子邮件,然后进行一些处理。我正在使用 JavaMail API 和 IMAP 协议来实现这一点。我编写了一个 java 类,它在 messagesAdded 事件上读取电子邮件。

它在单服务器环境中与下面的代码完美配合,但是当我将它部署到我们有两台服务器的生产环境中时,我最终会处理每封电子邮件两次,因为两台服务器上都部署了相同的代码,一旦收到电子邮件,两者都会尝试阅读在邮箱中。

下面是我用来连接邮箱和阅读电子邮件的代码片段:

 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();
}

关于我应该如何限制在多服务器环境中只处理一次电子邮件的任何建议?

4

1 回答 1

0

也许解决它的最简单方法是使用分布式锁;有很好的图书馆。但是如果你想在 javamail 中得到答案,那么有两种方法。

首先,您可以使用一个Flag并调用message.isSet()来检查其他服务器是否设置了该标志,然后message.setFlags()进行锁定。不幸的是,比赛。这场比赛可以通过一些涉及另外两个标志或名为 condstore 的 IMAP 扩展来解决,javamail 显然不支持 - setFlags() 需要一个新long参数来设置标志,只有在标志没有改变的情况下客户最后一次注意到。

其次,您可以使用一系列邮箱并通过它移动邮件。您需要四个邮箱,即收件箱和另外三个可能称为“处理-a”、“处理-b”和“已处理”的邮箱。服务器 A 处理“处理-a”中的所有消息,然后将每个消息移动到“已处理”,B 负责“处理-b”。当每个服务器完成其“处理foo ”后,它会在收件箱中查找新消息并调用moveMessages()以原子方式将一条或几条消息移动到自己的邮箱中。moveMessages() 使用名为 move 的 IMAP 扩展以原子方式移动消息,大多数服务器都支持,但不是全部。

于 2019-05-06T08:28:57.440 回答