当邮箱中有大量邮件时,Java Mail IMAP搜索需要花费大量时间

时间:2016-04-01 04:26:55

标签: java javamail imap

我编写了一个调度程序,每隔一分钟运行一次,并使用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 **/

        }
        }
    }


}

1 个答案:

答案 0 :(得分:0)

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

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

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