【问题标题】:Is it acceptable to leave the javamail session Transport open?让 javamail 会话传输打开是否可以接受?
【发布时间】:2011-05-19 01:19:06
【问题描述】:

我的应用程序需要临时发送电子邮件。我正在使用 javamail 的 getDefaultSession 和 getTransport 来发送消息,并且一切正常。

但是我注意到发送可能需要很长时间 - 每次发送最多 7 秒。如果我分解步骤,像这样:

Transport transport = session.getTransport("smtp");
transport.connect();
transport.sendMessage( msg, addresses )
transport.close();

...我可以看到每次几乎所有时间都是 connect() 调用。

我发现的所有示例都是这样做的 - 获取传输、连接、发送、断开连接。但当然,它们都是单次示例,或者在一次调用中发送大量电子邮件。

我在想我可以让连接保持打开状态,如下所示:

Transport transport = session.getTransport("smtp");
if (!transport.isConnected())
    transport.connect();
transport.sendMessage( msg, addresses )

(这里有一个变体:java mail keeping Transport object connected)。

我最终将不得不关闭它,在某种关闭挂钩中。而且我可能必须有一个后备(如果连接已丢失但传输没有实现)。但是,有什么理由不在应用程序生命周期内就这样保持打开状态吗?

谢谢, 阿拉斯泰尔

【问题讨论】:

    标签: java jakarta-mail


    【解决方案1】:

    根据@Bill Shannon(JavaMail 的作者)的回答: Threadsafety in Javamail

    由于 Transport 表示与邮件服务器的连接,并且一次只能有一个线程使用该连接,因此 Transport 将同步来自多个线程的访问以维护线程安全,但您真的只想使用它来自一个线程。

    因此,如果您打算使用 多线程 中的单个 Transport 实例(现在通常是这种情况),那么 性能实际上是非常坏主意观点。您最好使用ThreadLocal 开发某种Transport 实例池。

    【讨论】:

    • 如果有人需要此类池的代码示例 - 请在此处发表评论,我将用它扩展我的答案
    • 你好 Yura,我对某些示例感兴趣,实际上我开发了一个代码,用于从多线程读取带有 imap 的邮件,我在单例 ejb 中有会话,但其他代码用于访问邮件信息在无状态 ejb 中。非常感谢。
    • @Gaalvarez 这可能会对您有所帮助,如果您真的想要,只需将池大小设置为 1:github.com/nithril/smtp-connection-pool
    【解决方案2】:

    我认为保持单个 SMTP 连接打开没有任何问题,建议使用传输对象来重用连接(请参阅JavaMail tutorial)。

    此外,我建议您在您的应用程序中仅保持一个 smpt 连接(通过传输)打开,将其保持在单个管理器实例中(即使用单例模式),从而避免保持另一个连接打开的最终成本每个需要发送消息的组件。

    【讨论】:

    • 嗨 Tomas,谢谢你——正是我所希望的。我确实计划在单例“EmailSender”实例中使用它,所以这应该没问题。
    • 这种方法可能会在我的回答中概述的多线程环境中导致严重的性能问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-14
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 2012-05-27
    • 1970-01-01
    • 2011-06-26
    相关资源
    最近更新 更多