我编写了一个调度程序,每隔一分钟运行一次,并使用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 **/
}
}
}
}
答案 0 :(得分:0)
猜测,您面临的问题是您的IMAP服务器在消息中存储了标志,因此搜索意味着100GB的磁盘I / O.存储标志是愚蠢的,但至少有一个IMAP服务器可以做到这一点。
如果我是对的,那么你可以使用范围搜索来加快速度。您现在执行的搜索是unseen
。您应该做的是uid 12345:* unseen
,其中12345比您之前处理的最高UID高一个。这使得IMAP服务器不必查看邮箱的第一部分。在Javamail中,我认为代码看起来像new AndTerm(new MessageNumberTerm(...), new FlagTerm(...))
。
高性能的方法是使用所有搜索结果。立即使用它或缓存它,但不要扔掉它。丢弃远程IMAP操作的结果不会带来高性能。