JavaMail,IMAP,大量文件夹的性能



我们正在为IMAP帐户开发一个基于java的邮件客户端,并使用最新的java邮件api(1.5.6)。我们的客户拥有400多个文件夹的邮件帐户。用户对文件夹执行检查邮件,并迭代每个文件夹并获取新邮件,例如,

folder.getMessagesByUid(lastStoredUID, UIDFolder.LastUID)

或者获取未读邮件的数量需要太多时间,因为文件夹数量庞大。(我们必须迭代 400 个文件夹)

为了提高性能,我们在线程中使用了平行工作连接,我们有一个 SESSION 实例,但每个线程(连接)都有自己的 STORE 实例。当我们必须获取新消息时,我们会动态生成 10 个线程及其 STORE 实例,分别连接/登录它们,在该 STORE 上获取文件夹实例,打开文件夹,执行文件夹操作,关闭文件夹,然后关闭 SESSION。但对我来说不清楚,我是否必须保持文件夹的意图,我也不清楚文件夹是否应该保持打开状态,或者我们应该明确关闭后部,或者我们可以保持所有打开状态(将关闭操作留给邮件服务器)。

在我当前的实现中,

new Thread() {
public void run() {
//Get a new store instance
Store tempStore = MySingleSession.getStore("imap");
tempStore.connect(..);
//Get a folder for example inbox
Folder inbox = tempStore.get("INBOX");
inbox.open(Folder.READ);
// Perform get new messages
inbox.getMessagesByUd(lastUID, UIDFolder.MaxUID);
inbox.close();
tempStore.close();
..

检查性能时,我发现打开/关闭文件夹需要很长时间,尤其是在包含超过 100.000 封邮件的文件夹中。而且我看到即使我关闭文件夹的存储,文件夹仍然处于打开状态,如果我们不明确关闭该文件夹,我们可以对其进行操作。如果我更改我的实现并且没有显式关闭文件夹并使它们保持打开状态,这种机制的缺点是什么?

  • 例如,将文件夹引用保存在按其全名键入的哈希表中 "收件箱" -> IMAPFolder 并在任何操作之前执行 isOpen 检查 (getMessages),但在完成后,不要像我当前的实现那样显式关闭。这样做时,我们可能会打开 400 个文件夹,这对邮件服务器和邮件服务器关闭它们似乎很糟糕,但我会先检查每个文件夹的运行情况,如果它被打开。因此,文件夹将尽可能保持打开状态(直到邮件服务器关闭连接),如果再次需要相同的文件夹,我们不必再次打开它。

  • 我不明白,为什么我仍然可以在商店关闭的文件夹上操作?

  • mail.imap.connectionpoolsize的默认值为 1,在这种情况下增加此值是否有帮助?

  • 我不明白下面的这种情况会发生什么?

    Store tempStore = MySingleSession.getStore("imap");
    tempStore.connect(..);
    Folder f = tempStore.getFolder("INBOX");
    f.open(Folder.READ_ONLY);
    // close the store!!!
    tempStore.close();
    // now folder f becomes closed,
    // but we may open it again even if its Store is disconnected!
    f.open(Folder.READ_ONLY);
    // we can continue operating on folder f
    
  • 哪种方法更好,将文件夹引用保存在按全名键入的 hastable 中,还是每次都执行 tempStore.getFolder(文件夹名称)?例如,我们必须处理收件箱,第一个选项使用

IMAPFolder f = folderCache.get("INBOX");//假设已经放入 hashtable folderCache

IMAPFolder f = tempStore.getFolder("INBOX");

我按需生成存储实例,然后关闭它们,以免使用邮件服务器上的大量资源。但是再次打开文件夹而不手动关闭不是一个好方法,因为它仍然使用资源?或者使用这种方式是可以接受的,因为邮件服务器可能会在需要时关闭它,我们只需要检查是否

  • 如果文件夹已打开,请继续操作,
  • 如果文件夹已关闭,请先打开,然后操作,保持打开状态以供进一步使用?

一个帖子的问题太多了。 让我试着回答其中的几个...

关闭文件夹后,不应使用该文件夹中的任何 Message 对象,因此请仅在使用完文件夹的邮件后关闭该文件夹。

如果单个用户有 400 个文件夹,则可以使用单个应用商店连接,因为每个打开的文件夹都将获得自己的连接。

如果您经常打开和关闭文件夹,增加连接池大小会有所帮助,因为已关闭文件夹的连接将添加到池中,并在打开新文件夹时重复使用,而无需创建新连接。

关闭应用商店应关闭该应用商店的所有文件夹,但如果涉及多个线程,则存在固有的争用条件。 关闭应用商店是一种在使用完后清理所有连接的方法,而不是阻止其他线程重新打开文件夹的方法。

与每次调用 getFolder 相比,为已关闭的文件夹缓存文件夹对象不太可能是一个很大的优势。

最新更新