JavaMail、IMAP和大量文件夹的性能

JavaMail、IMAP和大量文件夹的性能,java,multithreading,email,jakarta-mail,imap,Java,Multithreading,Email,Jakarta Mail,Imap,我们正在为IMAP帐户开发一个基于java的邮件客户端,并使用最新的java邮件api(1.5.6)。我们的客户拥有超过400个文件夹的邮件帐户。例如,用户对文件夹执行检查邮件,对每个文件夹进行迭代,并获取新邮件 folder.getMessagesByUid(lastStoredUID, UIDFolder.LastUID) 或者,由于文件夹数量庞大,获取未读邮件的数量需要花费太多时间。(我们必须迭代400个文件夹) 为了提高性能,我们在线程中使用并行工作连接,我们有一个会话实例,但每个线程

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

folder.getMessagesByUid(lastStoredUID, UIDFolder.LastUID)
或者,由于文件夹数量庞大,获取未读邮件的数量需要花费太多时间。(我们必须迭代400个文件夹)

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

在我目前的实施中

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();
        ..
在检查性能时,我发现打开/关闭文件夹需要很长时间,尤其是包含超过100000条消息的文件夹。我看到,即使我关闭了文件夹的存储,文件夹仍然保持打开状态,如果我们没有明确关闭该文件夹,我们可以对其进行操作。如果我更改了实现,没有明确关闭文件夹并保持其打开状态,那么这种机制的缺点是什么

  • 例如,在哈希表中保持文件夹引用的全名 “收件箱”->IMAPFolder并在任何操作(getMessages)之前执行IsOpen检查,但完成后,不会像我当前的实现中那样显式关闭。当这样做时,我们可能会打开400个文件夹,这可能会对邮件服务器和邮件服务器关闭它们不好,但我会首先检查每个文件夹的操作,如果它被打开或没有。因此,文件夹将尽可能保持打开状态(直到mailserver关闭连接),如果再次需要相同的文件夹,我们不必再次打开它

  • 我不明白,为什么我仍然可以对一个已关闭存储的文件夹进行操作

  • 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
    
  • 哪种方法更好,将文件夹引用保存在一个由fullname键入的hastable中,还是每次执行tempStore.getFolder(foldername)?例如,我们必须处理收件箱,第一个选项是使用

IMAPFolder f=folderCache.get(“收件箱”);//假设已经放入hashtable folderCache中

IMAPFolder f=tempStore.getFolder(“收件箱”)

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

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

    • 一篇文章的问题太多了。让我试着回答其中的几个问题

      关闭文件夹后,不应使用该文件夹中的任何邮件对象,因此只有在使用完其邮件后才能关闭该文件夹

      如果单个用户有400个文件夹,则可以使用单个存储连接,因为每个打开的文件夹都有自己的连接

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

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


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

      由于您必须随时处理故障,因此在尝试操作之前,应检查文件夹是否打开,以避免在正常路径上浪费时间。只需尝试该操作,并在引发异常时尝试恢复。谢谢您的回复。但我有点困惑。在另一篇帖子中,你说:*你可以尝试使用多个存储到同一台服务器,并多次连接以获得多个连接,然后并行地将请求分割到多个连接。*使用这种方法,速度会更快,但现在您可以使用单个存储,因为每个文件夹都有自己的连接。我再次尝试使用单一商店,但增加了池大小。“多存储”方法始终快速。某些操作在文件夹打开时使用文件夹的连接,在文件夹关闭时使用单个单独的存储连接。后者将受益于多个商店,每个商店都有自己的连接。前者不会。