php 在Laravel应用程序上实现电子邮件服务的负载均衡器(循环)

72qzrwbm  于 2023-10-15  发布在  PHP
关注(0)|答案(1)|浏览(73)

我有两个发送电子邮件的服务,Postmark和SendGrid。我使用工厂模式是为了具有可扩展性和灵活性。
EmailProviderInterface

namespace App\Services\Notifications;

interface EmailProviderInterface
{
    public function sendEmail(string $to, string $templateName, array $data);
}

PostMarkEmailService

<?php

namespace App\Services\Notifications;

use App\Traits\SendEmailTrait;

class PostmarkEmailService implements EmailProviderInterface
{
    use SendEmailTrait;

    /**
     * send email using postmark
     *
     * @param string $to
     * @param string $templateName
     * @param array $data
     * @return array
     */
    public function sendEmail(string $to, string $templateName, array $data): array
    {

        $templateInfo = $this->getHtmlRender($templateName, $data);
        if (!$templateInfo['success']) {
            return $templateInfo;
        }
        
        try {
            // implement logic calling external api and passing the html

            return $this->successHandler();
        } catch (\Exception $e) {
            return $this->handleErrors($e);
        }
    }
}

SendGridEmailService

<?php

namespace App\Services\Notifications;

use App\Traits\SendEmailTrait;

class SendGridEmailService implements EmailProviderInterface
{

    use SendEmailTrait;

    /**
     * Send Email Using SendGrid
     *
     * @param string $to
     * @param string $templateName
     * @param array $data
     * @return array
     */
    public function sendEmail(string $to, string $templateName, array $data): array
    {

        $templateInfo = $this->getHtmlRender($templateName, $data);
        if (!$templateInfo['success']) {
            return $templateInfo;
        }
        try {
            // implement logic calling external api and passing the html

            return $this->successHandler();
        } catch (\Exception $e) {
            return $this->handleErrors($e);
        }
    }
}

这是EmailServiceProvider将使用它:

<?php

namespace App\Services\Notifications;

class EmailServiceProvider
{
    private EmailProviderInterface $emailProvider;

    public function __construct(bool $highPriority = true)
    {
        if ($highPriority) {
            $this->emailProvider = new PostmarkEmailService();
        } else {
            $this->emailProvider = new SendGridEmailService();
        }
    }

    /**
     * Send email using the email provider
     *
     * @param string $to
     * @param string $templateName
     * @param array $data
     * @return array
     */
    public function sendMail(string $to, string $templateName, array $data): array
    {
        return $this->emailProvider->sendEmail($to, $templateName, $data);
    }

}

我需要实现一个带有重试机制的负载均衡器(使用循环策略)。这将在EmailService提供程序上操作,以便在PostMark和SendGrid服务之间进行交换。
如果要实现一个队列,如何应用这样的负载均衡器?

56lgkhnf

56lgkhnf1#

要在EmailServiceProvider中实现带重试的负载平衡,可以更新constructorsendMail方法。

<?php

namespace App\Services\Notifications;

class EmailServiceProvider
{
    private array $emailProviders;
    private int $currentProviderIndex;

    public function __construct()
    {
        $this->emailProviders = [
            new PostmarkEmailService(),
            new SendGridEmailService(),
        ];
        $this->currentProviderIndex = 0;
    }

    public function sendMail(string $to, string $templateName, array $data): array
    {
        $maxRetries = count($this->emailProviders);

        for ($retry = 0; $retry < $maxRetries; $retry++) {
            try {
                $provider = $this->emailProviders[$this->currentProviderIndex];
                $response = $provider->sendEmail($to, $templateName, $data);
                return $response;
            } catch (\Exception $e) {
                $this->rotateProvider();
            }
        }

        return ['success' => false, 'message' => 'Failed to send email'];
    }

    private function rotateProvider(): void
    {
        $this->currentProviderIndex++;
        if ($this->currentProviderIndex >= count($this->emailProviders)) {
            $this->currentProviderIndex = 0;
        }
    }
}

您还可以通过利用消息代理(如RabbitMQRedis)在队列级别实现负载平衡。
这些消息代理支持开箱即用的负载平衡机制,允许您将电子邮件作业的处理分布在多个工作进程或计算机上。

相关问题