我们正在使用MailKit
通过创建客户端,建立连接和发送邮件来成功发送电子邮件。非常标准的东西,当我们在我们的应用程序中收到消息时工作得很好,我们做了一些事情并发送电子邮件
但是,我们希望能够尽快处理数以千计的电子邮件。
我们的目标电子邮件服务器可能不可用,因此我们可以快速备份邮件,从而产生积压。
使用MailKit
,处理邮件的最佳和最快捷方式是什么,以便尽快发送邮件。例如,目前每个邮件可以一个接一个地处理,如果每个邮件花费一秒钟进行处理,则可能需要很长时间才能发送40000封邮件。
我们一直在使用parallel foreach
来启动多个线程但这有局限性。任何建议或建议将不胜感激。
添加了代码示例: CORRECTION,新代码示例已添加。这要快得多,但每次都无法创建新连接。 Exchange抛出错误&已发送的发件人'。目前平均每秒发送大约6封邮件。
var rangePartitioner = Partitioner.Create(0, inpList.Count, 15);
var po = new ParallelOptions { MaxDegreeOfParallelism = 30 };
Parallel.ForEach(rangePartitioner, (range, loopState) =>
{
using (var client = new SmtpClient(new SlabProtocolLogger()))
{
client.Connect(_appSettings.RelayAddress, _appSettings.RelayPort);
client.AuthenticationMechanisms.Remove("XOAUTH2");
for (int i = range.Item1; i < range.Item2; i++)
{
var message = _outboundQueueRepository.Read(inpList[i]).Load();
client.Send(message.Body, message.Metadata.Sender, message.Metadata.Recipients.Select(r => (MailboxAddress)r));
_outboundQueueRepository.Remove(inpList[i]);
};
}
});
答案 0 :(得分:1)
如果我错了,请纠正我,但在我看来,它的工作方式是Parallel.Foreach正在创建一些线程。然后每个线程创建一个SMTP连接,然后循环以发送一批消息。
这对我来说似乎很合理。
我可以给你的唯一建议可能会更好地优化这一点,如果这些消息中有许多具有完全相同的内容和相同的发件人地址,唯一的区别是收件人是谁,你可以大大减少消息的数量你需要发送。
例如,如果您当前正在发送以下3条消息:
消息#1:
From: no-reply@company.com
To: Joe The Plumber <joe@plumbing-masters.com>
Subject: We've got a new sale! 50% off everything in stock!
some message text goes here.
消息#2
From: no-reply@company.com
To: Sara the Chef <sara@amazing-chefs.com>
Subject: We've got a new sale! 50% off everything in stock!
some message text goes here.
消息#3:
From: no-reply@company.com
To: Ben the Cobbler <ben@cobblers-r-us.com>
Subject: We've got a new sale! 50% off everything in stock!
some message text goes here.
您的代码可能会创建3个线程,在每个线程中发送1条消息。
但是,如果您创建了以下单个消息,那该怎么办:
From: no-reply@company.com
To: undisclosed-recipients:;
Subject: We've got a new sale! 50% off everything in stock!
some message text goes here.
然后使用以下代码发送给同一MimeMessage
的所有3位客户?
var sender = new MailboxAddress (null, "no-reply@company.com");
var recipients = new List<MailboxAddress> ();
recipients.Add (new MailboxAddress ("Joe the Plumber", "joe@plumbing-masters.com"));
recipients.Add (new MailboxAddress ("Sara the Chef", "sara@amazing-chefs.com"));
recipients.Add (new MailboxAddress ("Ben the Cobbler", "ben@cobblers-r-us.com"));
client.Send (message, sender, recipients);
您的所有3位客户都会收到相同的电子邮件,而您不必发送3条消息,您只需发送1条消息。
你可能已经理解了这个概念,所以这可能对你没有任何帮助 - 我只是提到它,因为我已经注意到这并不是每个人都能立即明白的。有些人认为他们需要为每个收件人发送1条消息,因此他们最终会尝试优化发送1000条消息,而实际上他们只需要发送1条消息。
答案 1 :(得分:1)
因此,除了我们在Parrallel ForEach循环中发现的改进之外,我们还发现了一个更广泛的修复方案,它可以大大提高性能。与MailKit无关,但我认为无论如何我都会分享。我们的调用代码创建inputList的方式是使用DirectoryInfo.GetDirectories枚举目录中的所有第一个。在某些情况下,我们的代码需要2秒才能在目录中执行40k文件。我们将此更改为EnumerateDirectories,它有效地释放了邮件发送代码以发送许多电子邮件。
所以要确认,并行循环工作得很好,其他地方的潜在性能问题是真正的瓶颈。