![使用 Perl NET::SMTP 通过 Exim 发送的电子邮件,然后 Postfix 从某个特定服务器发送时速度会变慢](https://linux22.com/image/784289/%E4%BD%BF%E7%94%A8%20Perl%20NET%3A%3ASMTP%20%E9%80%9A%E8%BF%87%20Exim%20%E5%8F%91%E9%80%81%E7%9A%84%E7%94%B5%E5%AD%90%E9%82%AE%E4%BB%B6%EF%BC%8C%E7%84%B6%E5%90%8E%20Postfix%20%E4%BB%8E%E6%9F%90%E4%B8%AA%E7%89%B9%E5%AE%9A%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%8F%91%E9%80%81%E6%97%B6%E9%80%9F%E5%BA%A6%E4%BC%9A%E5%8F%98%E6%85%A2.png)
我们在 Debian 11(Bullseye)上设置了多台服务器。我们在白天使用 cron 在所有服务器上定期运行的进程之一是 perl 脚本,该脚本从 MySQL 数据库读取并发送包含相关数据的电子邮件。电子邮件数量各不相同,但通常每批在 5 到 20 封之间。除了在夜间,另一个进程将汇编信息并准备数百封电子邮件。这些通常都与下一批一起发送。除了我们的一台服务器。
我们不久前安装了这台服务器,最近又在上面添加了一个新客户端。此客户端生成的电子邮件数量比其他客户端多。我们注意到这会导致问题,因为在这台特定的机器上,电子邮件的发送速度不如其他机器快。这意味着 Perl 脚本将再次将待处理的电子邮件排队,并且它们将开始堆积。
perl 脚本与本地安装的 Exim4 进行通信。我们在所有服务器上使用的配置都是相同的。以下是文件update-exim4.conf.con
:
dc_eximconfig_configtype='smarthost'
dc_other_hostnames=''
dc_local_interfaces='127.0.0.1 ; ::1'
dc_readhost='******.com'
dc_relay_domains=''
dc_minimaldns='false'
dc_relay_nets=''
dc_smarthost='1**.***.***.**6'
CFILEMODE='644'
dc_use_split_config='true'
dc_hide_mailname='true'
dc_mailname_in_oh='true'
dc_localdelivery='mail_spool'
如您所见,Exim 将连接到我们的另一台服务器,即运行 postfix 的智能主机,每封电子邮件都会在该服务器中发送到其最终目的地。
我们遇到的问题是,该特定服务器上的电子邮件开始发送速度非常快(~20/s),然后速度减慢、停滞、冻结并最终停止,并出现以下错误:
unable to establish SMTP connection to (localhost) port 25
Trace begun at /usr/share/perl5/Email/Sender/Transport/SMTP.pm line 224
Email::Sender::Transport::SMTP::_throw('Email::Sender::Transport::SMTP=HASH(0x55d021f74620)', 'unable to establish SMTP connection to (localhost) port 25') called at /usr/share/perl5/Email/Sender/Transport/SMTP.pm line 174
Email::Sender::Transport::SMTP::_smtp_client('Email::Sender::Transport::SMTP=HASH(0x55d021f74620)') called at /usr/share/perl5/Email/Sender/Transport/SMTP.pm line 233
据我了解,Exim 会先将电子邮件保存到磁盘,然后将其添加到队列,然后通过智能主机发送(在我们的例子中)。如果是这种情况,则意味着 perl 脚本和 Exim 之间可能存在一些连接问题。我尝试过许多配置更改,但到目前为止都无济于事。
当我使用该标志从命令行运行 Exim 时-d+all
,我得到了大量数据。对我来说,有趣的部分在于差距:
[...]
12:33:00.959 394267 postfork: daemon-accept-delivery
12:33:00.959 394266 SMTP>>(close on process exit)
12:33:00.959 394266 >>>>>>>>>>>>>>>> Exim pid=394266 (daemon-accept) terminating with rc=0 >>>>>>>>>>>>>>>>
12:33:00.959 394267 exec /usr/sbin/exim4 -d=0xfff9ffff -MCd daemon-accept-delivery -Mc 1pY9HA-001eZ8-TG
12:33:00.960 394250 child 394266 ended: status=0x0
12:33:00.960 394250 normal exit, 0
12:33:00.960 394250 0 SMTP accept processes now running
12:33:00.960 394250 Listening...
[...]
12:33:02.998 394360 search_tidyup called
12:33:02.998 394360 search_tidyup called
12:33:02.998 394360 >>>>>>>>>>>>>>>> Exim pid=394360 (daemon-accept-delivery) terminating with rc=0 >>>>>>>>>>>
12:33:03.063 394365 read response data: size=75
12:33:03.063 394365 SMTP<< 250 2.1.0 Ok
12:33:03.063 394365 sync_responses expect rcpt
12:33:03.063 394365 SMTP<< 250 2.1.5 Ok
12:33:03.063 394365 SMTP<< 250 2.0.0 Ok: 1376 bytes queued as EDDF2F5F5E
[...]
12:33:03.087 394364 DSN: Remote SMTP server supports DSN: 1
12:33:03.087 394364 DSN: not sending DSN success message
12:33:03.087 394364 LOG: MAIN
12:33:03.087 394364 Completed QT=0.385s
12:33:03.087 394364 end delivery of 1pY9HC-001eag-Me
12:33:03.087 394364 search_tidyup called
12:33:03.087 394364 search_tidyup called
12:33:03.088 394364 >>>>>>>>>>>>>>>> Exim pid=394364 (daemon-accept-delivery) terminating with rc=0 >>>>>>>>>>>
**Why a 4 seconds gap here?**
12:33:07.772 394366 DNS lookup of localhost (AAAA) gave HOST_NOT_FOUND
12:33:07.772 394366 returning DNS_NOMATCH
12:33:07.772 394366 faking res_search(AAAA) response length as 65535
12:33:07.772 394366 writing neg-cache entry for localhost-AAAA-800043, ttl 86400
12:33:07.773 394366 DNS lookup of localhost (A) gave HOST_NOT_FOUND
[...]
12:33:08.417 394438 DSN: Remote SMTP server supports DSN: 1
12:33:08.417 394438 DSN: not sending DSN success message
12:33:08.417 394438 LOG: MAIN
12:33:08.417 394438 Completed QT=0.343s
12:33:08.417 394438 end delivery of 1pY9HI-001ebt-2N
12:33:08.417 394438 search_tidyup called
12:33:08.417 394438 search_tidyup called
12:33:08.417 394438 >>>>>>>>>>>>>>>> Exim pid=394438 (daemon-accept-delivery) terminating with rc=0 >>>>>>>>>>>
**Another 4-5 seconds gap**
12:33:13.146 394440 DNS lookup of ip6-localhost (AAAA) gave HOST_NOT_FOUND
12:33:13.146 394440 returning DNS_NOMATCH
每条接受和发送的消息都会DNS lookup of localhost gave HOST_NOT_FOUND
返回结果,因此这可能不是导致问题的原因。
随着处理的邮件数量增加,电子邮件之间的间隔变得越来越频繁。每次间隔所花的时间也越来越长。最终会出现超时。
以下是 Perl 代码的摘要。请注意,实际代码更复杂,包含许多类和子类,但其要点如下:
# Create SMTP server
$smtp_transport = Email::Sender::Transport::SMTP->new( $params );
my $unsent_messages = get_unsent_messages( $messages_args );
foreach my $message ( @$unsent_messages ) {
# Create email and assign args
my $email = Email::Stuffer->new();
$email->to( $message->{to} );
# [...] other arguments, headers, etc.
$email->send_or_die( transport => $smtp_transport );
}
是什么原因导致了这个问题。我该如何调试并找出问题的根源?配置与我们在其他服务器上的配置完全相同,可以在一分钟内发送数百封电子邮件,所以我怀疑这不是配置设置。这可能是硬件差异吗?
使用 Exim 版本 4.94.2 #2 构建于 2021 年 7 月 13 日 16:04:57 和 Postfix mail_version = 3.4.23。
更新
一个简单的 for 循环(见下文)以闪电般的速度发送消息,没有延迟。所以问题似乎来自 Perl。
for f in {1..111}; do mail -s TestDeCourriel [email protected] <<< "Mail content"; done
第二次更新
使用 s-nail 连接到本地 SMTP 服务器而不是使用 mail/sendmail 的相同循环可以重现该问题。
for i in {1..111}; do echo "This is a test message. $(date)" | s-nail -S mta=smtp://localhost:25 -s "Some s-nail mail" [email protected]; done