MimeMessage.saveChanges 真的很慢 [英] MimeMessage.saveChanges is really slow
问题描述
由于包含 m.saveChanges()
,以下测试大约需要 5 秒才能执行.
The following test is taking around 5 seconds to execute due to the inclusion of m.saveChanges()
.
import org.junit.Before;
import org.junit.Test;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@Test
public void test1() throws MessagingException, IOException {
Session s = Session.getDefaultInstance(new Properties());
MimeMessage m = new MimeMessage(s);
m.setContent("<b>Hello</b>", "text/html; charset=utf-8");
m.saveChanges();
assertEquals(m.getContent(), "<b>Hello</b>");
assertEquals(m.getContentType(), "text/html; charset=utf-8");
}
我也用 mockito 嘲笑了 Session,但它没有帮助:
I have also mocked the Session with mockito but it doesn't help:
Session s = mock(Session.class);
when(s.getProperties()).thenReturn(new Properties());
这里有什么问题?我可以模拟什么来加快速度?
What is the problem here? What can I mock to speed things up?
推荐答案
修复最常见的错误人们首先在您的代码中使用 JavaMail 时.
DNS 查找 可能会影响某些机器的性能.对于 JDK,您可以更改缓存 DNS 查找的安全属性 networkaddress.cache.ttl
和 networkaddress.cache.negative.ttl
或设置系统属性 sun.net.inetaddr.ttl
和 sun.net.inetaddr.negative.ttl
.JDK 7 及更高版本中的默认行为在缓存方面做得很好,因此您不必更改这些设置.
DNS lookup can hurt performance on some machines. For the JDK you can change the security properties for caching DNS lookup networkaddress.cache.ttl
and networkaddress.cache.negative.ttl
or set the system properties sun.net.inetaddr.ttl
and sun.net.inetaddr.negative.ttl
. The default behavior in JDK 7 and later does a good job of caching so you shouldn't have to change these settings.
最好使用会话属性来避免某些此类查找.
Preferably, you can use the session properties to avoid some these lookups.
- 为
mail.from
或设置会话属性mail.host
(不是协议版本),因为这会阻止在InternetAddress.getLocalAddress(Session)
.调用MimeMessage.saveChanges()
,MimeMessage.updateHeaders()
,MimeMessage.updateMessageID()
,或MimeMessage.setFrom()
将触发调用以获取本地地址.如果未设置上述属性,则此方法将尝试查询主机名.通过设置属性,此方法将从会话中提取主机名字符串,而不是尝试昂贵的 DNS 查找. - 为设置会话属性
mail.smtp.localhost
或mail.smtps.localhost
以防止在 HELO 命令上查找名称. - 为
mail.smtp.from
或mail.smtps.from
以防止查找 EHLO 命令. - 或者,您可以设置系统属性
mail.mime.address.usecanonicalhostname
到false
如果您的代码依赖于setFrom()
但是如果您应用了点,这将被处理#1. - 对于IMAP,您可以尝试设置
mail.imap.sasl.usecanonicalhostname
或mail.imaps.sasl.usecanonicalhostname
到false
这是默认值.
- Set session property for
mail.from
ormail.host
(not the protocol versions) as that will prevent the name lookup onInternetAddress.getLocalAddress(Session)
. CallingMimeMessage.saveChanges()
,MimeMessage.updateHeaders()
,MimeMessage.updateMessageID()
, orMimeMessage.setFrom()
will trigger a call to get the local address. If the above properties are not set then this method will attempt to query for the host name. By setting the properties, this method will pull the host name string from the session instead of attempting the expensive DNS lookup. - Set the session property for
mail.smtp.localhost
ormail.smtps.localhost
to prevent name lookup on the HELO command. - Set session property for
mail.smtp.from
ormail.smtps.from
to prevent lookup on EHLO command. - Alternatively, you can set the system property
mail.mime.address.usecanonicalhostname
tofalse
if your code is relying on thesetFrom()
but this will be handled if you applied point #1. - For IMAP, you can try to set
mail.imap.sasl.usecanonicalhostname
ormail.imaps.sasl.usecanonicalhostname
tofalse
which is the default value.
由于您不传输消息,请将代码更改为:
Since your are not transporting a message, apply rule #1 by changing your code to:
@Test
public void test1() throws MessagingException, IOException {
Properties props = new Properties();
props.put("mail.host", "localhost"); //Or use IP.
Session s = Session.getInstance(props);
MimeMessage m = new MimeMessage(s);
m.setContent("<b>Hello</b>", "text/html; charset=utf-8");
m.saveChanges();
assertEquals(m.getContent(), "<b>Hello</b>");
assertEquals(m.getContentType(), "text/html; charset=utf-8");
}
如果您正在传输消息,则组合规则 #1、#2 和 #3,这将阻止访问主机系统进行名称查找.如果您想在传输过程中阻止所有 DNS 查找,则必须使用 IP 地址.
If you are transporting a message then combine the rules #1, #2, and #3 which will prevent accessing the host system for a name lookup. If you want to prevent all DNS lookups during a transport then you have to use IP addresses.
这篇关于MimeMessage.saveChanges 真的很慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!