【发布时间】: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 条消息。仍然远远落后于目标。
标签: java jakarta-mail imap