【问题标题】:Java Mail IMAP search taking lot of time when there are lot of messages in mail box当邮箱中有大量邮件时,Java Mail IMAP 搜索会花费大量时间
【发布时间】:2016-07-20 18:29:41
【问题描述】:

我编写了一个调度程序,每分钟运行一次,并使用 IMAP (SSL) API 获取所有未读消息,然后仅将其中的 200 条消息标记为已读,然后逐条读取每条消息 (200) 的内容。我面临的问题是当邮箱有大约 400k 条消息(100GB)时,第一个获取未读消息的命令本身需要 10 多分钟。我不确定这是否是 imap 的行为方式,还是邮箱或网络级别的速度很慢。最终,我的目标是在 24 小时内从邮箱中读取大约 500k 封电子邮件,其中一封邮件大小约为 250kb,然后将每封 HTML 邮件作为 blob 存储在 oracle DB 中。目前我离实现这个目标还很遥远。我在下面附上我的代码。它在一分钟内只处理 50 条消息。如果有人能指导我修复代码中的任何性能问题,我将不胜感激。此外,如果有人有从邮箱中提取 HTML 电子邮件并使用任何方式保存在数据库中的经验,那么如果您能分享您的知识,那将非常有帮助。谢谢!

public void readMails() {



    int arraySize = fetchSize / threadCount;

    try {
            FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
            msgs = inbox.search(ft);

            if (msgs.length > fetchSize) {
                batchMsgs = Arrays.copyOfRange(msgs, 0, fetchSize - 1);
            } else {
                batchMsgs = msgs;
            }

            inbox.setFlags(batchMsgs, new Flags(Flags.Flag.SEEN), true);


        if (batchMsgs.length != 0) {
            archiveTaskExecutor.initialize();
            List<Message> tempMsgs = new ArrayList<Message>();
            // Message[] tempMsgs = new Message[arraySize];
            // int i = 0;
            int j = batchMsgs.length;
            for (Message m : batchMsgs) {
                tempMsgs.add(m);
                // i++;
                if (tempMsgs.size() >= arraySize || j <= 1) {
                    archiveTaskExecutor
                            .execute(new ExtractAndPersist(tempMsgs
                                    .toArray(new Message[tempMsgs.size()])));
                    tempMsgs = new ArrayList<Message>();
                    // tempMsgs = new Message[arraySize];
                    // i = 0;
                }
                j--;
            }
            archiveTaskExecutor.shutdown();
            try {
                archiveTaskExecutor.getThreadPoolExecutor()
                        .awaitTermination(15, TimeUnit.MINUTES);
            } catch (InterruptedException e) {

                archiveTaskExecutor.getThreadPoolExecutor().shutdownNow();
            }

        }
    } catch (Exception e) {
        /** revert all messages to UNREAD here **/

    }
}

private class ExtractAndPersist implements Runnable {

    final Logger log = Logger.getLogger(ExtractAndPersist.class);

    private Message[] messages;

    public ExtractAndPersist(Message[] m) {
        this.messages = m;
    }

    @Override
    public void run() {

        try {


            for (Message message : messages) {
                if (message != null) {


                    String mailContent = processMessageBody(message);


                    status = updateMailContent(mailId, mailContent);

                    }
                }
            }

         catch (Exception e) {
            /** set messages as UNREAD **/

        }
        }
    }


}

【问题讨论】:

  • 如果您尝试使用 Thunderbird 等 IMAP 客户端获取未读邮件,会发生什么情况?我怀疑你会发现限制是 IMAP 服务器搜索 400K 消息的能力。
  • 如果您打开JavaMail session debugging,您应该会看到JavaMail 正在向服务器发送一个SEARCH 命令,所有时间都用于搜索匹配的消息。对此您无能为力,但您可以使用Folder.fetch 方法加快后续处理消息的速度。
  • 感谢 Jim 和 Bill 的 cmets。我实际上删除了看不见的搜索,而是使用此链接 stackoverflow.com/questions/8322836/… 上建议的 Fetch 提供消息范围。这大大提高了性能,我现在可以在 1 分钟内处理 1000 条消息。仍然远远落后于目标。
  • 这终于帮助了我:stackoverflow.com/questions/8322836/…

标签: java jakarta-mail imap


【解决方案1】:

猜测一下,您面临的问题是您的 IMAP 服务器在消息中存储了标志,因此搜索意味着 100GB 的磁盘 I/O。在那里存储标志是愚蠢的,但至少有一个 IMAP 服务器会这样做。

如果我是对的,那么您可以通过使用范围搜索来加快速度。您现在进行的搜索是unseen。您应该做的是uid 12345:* unseen,其中12345 比您之前处理的最高UID 高一。这使 IMAP 服务器不必查看邮箱的第一部分。在 Javamail 中,我认为代码看起来像 new AndTerm(new MessageNumberTerm(...), new FlagTerm(...))

高性能的方法是使用所有搜索结果。一次使用或缓存,但不要扔掉。丢弃远程 IMAP 操作的结果不会带来高性能。

【讨论】:

  • 我会试试你提供的搜索。现在,我尝试按范围获取消息,而不是寻找看不见的消息。我还发现,如果必须处理大量消息,imap 提供的 getContent(message) api 会很慢。下载 1 封电子邮件的内容大约需要 2500 毫秒。我通过引用此链接 stackoverflow.com/questions/8322836/… 并进行批量提取来提高性能,但仍远远落后于我的目标。
猜你喜欢
  • 2015-03-14
  • 1970-01-01
  • 1970-01-01
  • 2018-01-10
  • 2011-03-15
  • 2016-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多