Heim  >  Artikel  >  Backend-Entwicklung  >  Verwenden Sie mixphp, um einen asynchronen E-Mail-Versand mit mehreren Prozessen zu erstellen

Verwenden Sie mixphp, um einen asynchronen E-Mail-Versand mit mehreren Prozessen zu erstellen

不言
不言Original
2018-07-06 16:14:421804Durchsuche

Dieser Artikel stellt hauptsächlich die Verwendung von mixphp zum Erstellen des asynchronen E-Mail-Versands mit mehreren Prozessen vor. Er hat einen gewissen Referenzwert. Jetzt können Freunde in Not darauf verweisen Sehr häufige Anforderung: Da der Vorgang des E-Mail-Versands im Allgemeinen zeitaufwändig ist, verwenden wir im Allgemeinen die asynchrone Verarbeitung, um die Benutzererfahrung zu verbessern, und die asynchrone Verarbeitung wird normalerweise mithilfe von Nachrichtenwarteschlangen implementiert.

Aufgrund des Mangels an Multiprozess-Entwicklungsfunktionen verwendet das herkömmliche MVC-Framework normalerweise dasselbe Skript, um mehrere Prozesse zu generieren. Mixphp kapselt TaskExecutor speziell für die Multiprozessentwicklung, sodass Benutzer entwickeln können Es ist ganz einfach eine voll funktionsfähige und hochverfügbare Multiprozessanwendung.

Das Folgende zeigt den Entwicklungsprozess eines asynchronen E-Mail-Versandsystems unter Einbeziehung von Wissenspunkten:

    Asynchronous
  • Message Queue
  • Mehrere Prozesse
  • Daemon-Prozess
  • So verwenden Sie die Nachrichtenwarteschlange, um asynchrone Prozesse zu implementieren

PHPs Verwendung von Nachrichtenwarteschlangen wird normalerweise mithilfe von Middleware implementiert:

    redis
  • rabbitmq
  • kafka
  • Dieses Mal wählen wir Redis, um den asynchronen E-Mail-Versand zu implementieren. Es gibt einen Listentyp im Datentyp von Redis, der eine Nachrichtenwarteschlange implementieren kann . Verwenden Sie den folgenden Befehl:
// 入列
$redis->lpush($key, $data);
// 出列
$data = $redis->rpop($key);
// 阻塞出列
$data = $redis->brpop($key, 10);

Architekturdesign

Dieses Beispiel verwendet das traditionelle MVC-Framework, um E-Mail-Versandanforderungen zu erfüllen, und MixPHP-Multiprozess, um die Sendeaufgabe auszuführen.

Auswahl der E-Mail-Versandbibliothek

In der Vergangenheit haben wir normalerweise die vom Framework bereitgestellte E-Mail-Versandbibliothek verwendet oder von anderen Benutzern online freigegebene Bibliotheken heruntergeladen, https://. packagist.org/ Es gibt viele hochwertige Bibliotheken im Internet, wir müssen nur die beste auswählen. In diesem Fall entscheiden wir uns für Swiftmailer.

Da die Sendeaufgabe von MixPHP ausgeführt wird, wird Swiftmailer im MixPHP-Projekt installiert. Führen Sie zur Installation den folgenden Befehl im Projektstammverzeichnis aus:

composer require swiftmailer/swiftmailer

Producer development

In der Anforderung des E-Mail-Versands bezieht sich der Produzent auf die Partei, die die Sendeaufgabe liefert. Dieser Teil muss nicht unbedingt mit mixphp entwickelt werden akzeptabel. Fügen Sie es einfach in der Benutzeroberfläche oder auf der Webseite hinzu. Veröffentlichen Sie einfach die Aufgabeninformationen in der Nachrichtenwarteschlange.

Fügen Sie den folgenden Code zum Controller des herkömmlichen MVC-Frameworks hinzu:

Normalerweise wird durch die Verwendung von Redis im Framework eine Klassenbibliothek zur Verwendung installiert. In diesem Beispiel wird zum besseren Verständnis nativer Code verwendet.

// 连接
$redis = new \Redis();
if (!$redis->connect('127.0.0.1', 6379)) {
    throw new \Exception('Redis Connect Failure');
}
$redis->auth('');
$redis->select(0);
// 投递任务
$data = [
    'to'      => ['***@qq.com' => 'A name'],
    'body'    => 'Here is the message itself',
    'subject' => 'The title content',
];
$redis->lpush('queue:email', serialize($data));
Normalerweise wird bei der asynchronen Entwicklung sofort nach Abschluss der Übermittlung eine Nachricht an den Benutzer gesendet. Natürlich wird die Aufgabe zu diesem Zeitpunkt noch nicht ausgeführt.

Verbraucherentwicklung

In diesem Beispiel verwenden wir das Multiprozess-Entwicklungstool TaskExecutor von MixPHP, um diese Anforderung zu erfüllen. Residente Prozesse werden normalerweise zur Handhabung des Warteschlangenverbrauchs verwendet, daher verwenden wir den TaskExecutor-Typ TYPE_DAEMON. MODE_PUSH-Modus.

Der MODE_PUSH-Modus von TaskExecutor verfügt über zwei Prozesse:

    Linker Prozess: Verantwortlich dafür, Aufgabendaten aus der Nachrichtenwarteschlange zu entnehmen und in den mittleren Prozess einzufügen.
  • Mittlerer Prozess: Verantwortlich für die Ausführung von E-Mail-Versandaufgaben.
  • PushCommand.php-Code lautet wie folgt:
<?php

namespace apps\daemon\commands;

use mix\console\ExitCode;
use mix\facades\Input;
use mix\facades\Redis;
use mix\task\CenterProcess;
use mix\task\LeftProcess;
use mix\task\TaskExecutor;

/**
 * 推送模式范例
 * @author 刘健 <coder.liu@qq.com>
 */
class PushCommand extends BaseCommand
{

    // 配置信息
    const HOST = &#39;smtpdm.aliyun.com&#39;;
    const PORT = 465;
    const SECURITY = &#39;ssl&#39;;
    const USERNAME = &#39;****@email.***.com&#39;;
    const PASSWORD = &#39;****&#39;;

    // 初始化事件
    public function onInitialize()
    {
        parent::onInitialize(); // TODO: Change the autogenerated stub
        // 获取程序名称
        $this->programName = Input::getCommandName();
        // 设置pidfile
        $this->pidFile = "/var/run/{$this->programName}.pid";
    }

    /**
     * 获取服务
     * @return TaskExecutor
     */
    public function getTaskService()
    {
        return create_object(
            [
                // 类路径
                &#39;class&#39;         => &#39;mix\task\TaskExecutor&#39;,
                // 服务名称
                &#39;name&#39;          => "mix-daemon: {$this->programName}",
                // 执行类型
                &#39;type&#39;          => \mix\task\TaskExecutor::TYPE_DAEMON,
                // 执行模式
                &#39;mode&#39;          => \mix\task\TaskExecutor::MODE_PUSH,
                // 左进程数
                &#39;leftProcess&#39;   => 1,
                // 中进程数
                &#39;centerProcess&#39; => 5,
                // 任务超时时间 (秒)
                &#39;timeout&#39;       => 5,
            ]
        );
    }

    // 启动
    public function actionStart()
    {
        // 预处理
        if (!parent::actionStart()) {
            return ExitCode::UNSPECIFIED_ERROR;
        }
        // 启动服务
        $service = $this->getTaskService();
        $service->on(&#39;LeftStart&#39;, [$this, &#39;onLeftStart&#39;]);
        $service->on(&#39;CenterStart&#39;, [$this, &#39;onCenterStart&#39;]);
        $service->start();
        // 返回退出码
        return ExitCode::OK;
    }

    // 左进程启动事件回调函数
    public function onLeftStart(LeftProcess $worker)
    {
        try {
            // 模型内使用长连接版本的数据库组件,这样组件会自动帮你维护连接不断线
            $queueModel = Redis::getInstance();
            // 保持任务执行状态,循环结束后当前进程会退出,主进程会重启一个新进程继续执行任务,这样做是为了避免长时间执行内存溢出
            for ($j = 0; $j < 16000; $j++) {
                // 从消息队列中间件阻塞获取一条消息
                $data = $queueModel->brpop(&#39;queue:email&#39;, 10);
                if (empty($data)) {
                    continue;
                }
                list(, $data) = $data;
                // 将消息推送给中进程去处理,push有长度限制 (https://wiki.swoole.com/wiki/page/290.html)
                $worker->push($data, false);
            }
        } catch (\Exception $e) {
            // 休息一会,避免 CPU 出现 100%
            sleep(1);
            // 抛出错误
            throw $e;
        }
    }

    // 中进程启动事件回调函数
    public function onCenterStart(CenterProcess $worker)
    {
        // 保持任务执行状态,循环结束后当前进程会退出,主进程会重启一个新进程继续执行任务,这样做是为了避免长时间执行内存溢出
        for ($j = 0; $j < 16000; $j++) {
            // 从进程消息队列中抢占一条消息
            $data = $worker->pop();
            if (empty($data)) {
                continue;
            }
            // 处理消息
            try {
                // 处理消息,比如:发送短信、发送邮件、微信推送
                var_dump($data);
                $ret = self::sendEmail($data);
                var_dump($ret);
            } catch (\Exception $e) {
                // 回退数据到消息队列
                $worker->rollback($data);
                // 休息一会,避免 CPU 出现 100%
                sleep(1);
                // 抛出错误
                throw $e;
            }
        }
    }

    // 发送邮件
    public static function sendEmail($data)
    {
        // Create the Transport
        $transport = (new \Swift_SmtpTransport(self::HOST, self::PORT, self::SECURITY))
            ->setUsername(self::USERNAME)
            ->setPassword(self::PASSWORD);
        // Create the Mailer using your created Transport
        $mailer = new \Swift_Mailer($transport);
        // Create a message
        $message = (new \Swift_Message($data[&#39;subject&#39;]))
            ->setFrom([self::USERNAME => &#39;**网&#39;])
            ->setTo($data[&#39;to&#39;])
            ->setBody($data[&#39;body&#39;]);
        // Send the message
        $result = $mailer->send($message);
        return $result;
    }

}

Test

    Starten Sie das push-residente Programm in der Shell.
  1. [root@localhost bin]# ./mix-daemon push start
    mix-daemon 'push' start successed.
    Rufen Sie die Schnittstelle auf, um Aufgaben in die Nachrichtenwarteschlange zu stellen.
  1. Zu diesem Zeitpunkt druckt das Shell-Terminal:

Verwenden Sie mixphp, um einen asynchronen E-Mail-Versand mit mehreren Prozessen zu erstellen Die Test-E-Mail wurde erfolgreich empfangen:

Verwenden Sie mixphp, um einen asynchronen E-Mail-Versand mit mehreren Prozessen zu erstellenDas Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, er wird für das Studium aller hilfreich sein. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website.

Verwandte Empfehlungen:

Shmop-Erweiterung für PHP aktivieren, um Shared Memory zu implementieren


PHP implementiert Shared-Memory-Prozesskommunikationsfunktion ( _shm )

Das obige ist der detaillierte Inhalt vonVerwenden Sie mixphp, um einen asynchronen E-Mail-Versand mit mehreren Prozessen zu erstellen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn