Symfony 5,通过邮件程序发送多封电子邮件时内存泄漏
Symfony 5, memory leaking when send multiple emails through mailer
我在发送群发邮件时内存泄漏。我需要每月向大约 100 000 名用户发送时事通讯。
它发生在生产环境和开发环境中。
我正在使用:
- Symfony 5.1.11
- Docker
- Php 7.4.10
下面你可以看到我的命令的主要部分来自 execute
方法。
// Total Users
$totalRecords = $this->getUserRepository()->count(['newsletter' => true]);
if ($totalRecords === 0) {
$output->writeln('No records found');
return Command::SUCCESS;
}
$offers = $this->fetchOffersByType($type);
$totalOffers = count($offers);
// Check if we have popular offers
if ($totalOffers === 0) {
$output->writeln('No Offers was found');
return Command::SUCCESS;
}
$totalPages = ceil($totalRecords / self::BUFFER_SIZE);
// Initializing one time and assign to users
$newsletter = (new Newsletter())
->setSentAt(new DateTime())
->setType(NewsletterType::MAP[$type]);
$totalSuccessSent = 0;
$total = 0;
for ($page = 1; $page <= $totalPages; $page++) {
// Get users to who we will send newsletters
$users = $this->getUserRepository()
->findBy(['newsletter' => true], null, self::BUFFER_SIZE, self::BUFFER_SIZE * ($page - 1));
foreach ($users as $user) {
$total++;
if (empty($user->getEmail())) {
continue;
}
if ($this->emailService->sendNewsletter($user, $type, $offers)) {
$user->addNewsletter($newsletter);
$this->em->persist($user);
$totalSuccessSent++;
}
}
$this->em->flush();
// Make clean up after specific number of users
if ($total % self::CLEAN_UP_AFTER === 0) {
$output->writeln('Clean Up');
$this->em->clear();
gc_collect_cycles();
}
}
基本上我让所有订阅时事通讯并发送 9 个热门优惠的用户。
这篇文章与sendNewsletter
有关。
try {
$email = (new TemplatedEmail())
->from(new Address($this->parameterBag->get('noReplayEmail'), $this->parameterBag->get('noReplayEmailName')))
->to($user->getEmail())
->priority(Email::PRIORITY_NORMAL)
->subject($subject)
->htmlTemplate($template)
->context([
'offers' => $offers,
]);
$this->mailer->send($email);
return true;
} catch (TransportExceptionInterface | RfcComplianceException | JsonException $e) {
return false;
}
经过调查,我确定 $this->mailer->send($email)
是问题所在。
此命令的内存限制为 512,最多可以发送 +- 1500 封电子邮件。
我正在使用 mailgun。
在某些情况下,错误可能会有所不同,但这种错误发生的时间更长:
php.CRITICAL: Fatal Error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 245760 bytes) {"exception":"[object] (Symfony\Component\ErrorHandler\Error\OutOfMemoryError(code: 0): Error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 245760 bytes) at /home/***/vendor/symfony/mime/Encoder/QpContentEncoder.php:36)"}
我还尝试将 MAILER_DSN
用作 null://null
进行测试,这意味着它不会发送电子邮件。发生同样的问题。
我还能做什么?
更新:
通过 Symfony Messages 异步发送电子邮件对我没有帮助。
此问题的一个解决方案是使用异步发送。
例如,您可以使用 Symfony 组件 Messenger(或其他解决方案):
https://symfony.com/doc/current/mailer.html#sending-messages-async
此问题已在 Symfony 5.2 中修复。
这是错误的详细信息:https://github.com/symfony/symfony/pull/37712
所以对于所有遇到同样问题的人,请升级您的 symfony。
我在发送群发邮件时内存泄漏。我需要每月向大约 100 000 名用户发送时事通讯。 它发生在生产环境和开发环境中。
我正在使用:
- Symfony 5.1.11
- Docker
- Php 7.4.10
下面你可以看到我的命令的主要部分来自 execute
方法。
// Total Users
$totalRecords = $this->getUserRepository()->count(['newsletter' => true]);
if ($totalRecords === 0) {
$output->writeln('No records found');
return Command::SUCCESS;
}
$offers = $this->fetchOffersByType($type);
$totalOffers = count($offers);
// Check if we have popular offers
if ($totalOffers === 0) {
$output->writeln('No Offers was found');
return Command::SUCCESS;
}
$totalPages = ceil($totalRecords / self::BUFFER_SIZE);
// Initializing one time and assign to users
$newsletter = (new Newsletter())
->setSentAt(new DateTime())
->setType(NewsletterType::MAP[$type]);
$totalSuccessSent = 0;
$total = 0;
for ($page = 1; $page <= $totalPages; $page++) {
// Get users to who we will send newsletters
$users = $this->getUserRepository()
->findBy(['newsletter' => true], null, self::BUFFER_SIZE, self::BUFFER_SIZE * ($page - 1));
foreach ($users as $user) {
$total++;
if (empty($user->getEmail())) {
continue;
}
if ($this->emailService->sendNewsletter($user, $type, $offers)) {
$user->addNewsletter($newsletter);
$this->em->persist($user);
$totalSuccessSent++;
}
}
$this->em->flush();
// Make clean up after specific number of users
if ($total % self::CLEAN_UP_AFTER === 0) {
$output->writeln('Clean Up');
$this->em->clear();
gc_collect_cycles();
}
}
基本上我让所有订阅时事通讯并发送 9 个热门优惠的用户。
这篇文章与sendNewsletter
有关。
try {
$email = (new TemplatedEmail())
->from(new Address($this->parameterBag->get('noReplayEmail'), $this->parameterBag->get('noReplayEmailName')))
->to($user->getEmail())
->priority(Email::PRIORITY_NORMAL)
->subject($subject)
->htmlTemplate($template)
->context([
'offers' => $offers,
]);
$this->mailer->send($email);
return true;
} catch (TransportExceptionInterface | RfcComplianceException | JsonException $e) {
return false;
}
经过调查,我确定 $this->mailer->send($email)
是问题所在。
此命令的内存限制为 512,最多可以发送 +- 1500 封电子邮件。
我正在使用 mailgun。 在某些情况下,错误可能会有所不同,但这种错误发生的时间更长:
php.CRITICAL: Fatal Error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 245760 bytes) {"exception":"[object] (Symfony\Component\ErrorHandler\Error\OutOfMemoryError(code: 0): Error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 245760 bytes) at /home/***/vendor/symfony/mime/Encoder/QpContentEncoder.php:36)"}
我还尝试将 MAILER_DSN
用作 null://null
进行测试,这意味着它不会发送电子邮件。发生同样的问题。
我还能做什么?
更新: 通过 Symfony Messages 异步发送电子邮件对我没有帮助。
此问题的一个解决方案是使用异步发送。 例如,您可以使用 Symfony 组件 Messenger(或其他解决方案): https://symfony.com/doc/current/mailer.html#sending-messages-async
此问题已在 Symfony 5.2 中修复。 这是错误的详细信息:https://github.com/symfony/symfony/pull/37712
所以对于所有遇到同样问题的人,请升级您的 symfony。