Heim > Artikel > Backend-Entwicklung > Verwenden Sie mixphp, um einen asynchronen E-Mail-Versand mit mehreren Prozessen zu erstellen
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:
// 入列 $redis->lpush($key, $data); // 出列 $data = $redis->rpop($key); // 阻塞出列 $data = $redis->brpop($key, 10);
Architekturdesign
Auswahl der E-Mail-Versandbibliothek
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
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
Der MODE_PUSH-Modus von TaskExecutor verfügt über zwei Prozesse:
<?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 = 'smtpdm.aliyun.com'; const PORT = 465; const SECURITY = 'ssl'; const USERNAME = '****@email.***.com'; const PASSWORD = '****'; // 初始化事件 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( [ // 类路径 'class' => 'mix\task\TaskExecutor', // 服务名称 'name' => "mix-daemon: {$this->programName}", // 执行类型 'type' => \mix\task\TaskExecutor::TYPE_DAEMON, // 执行模式 'mode' => \mix\task\TaskExecutor::MODE_PUSH, // 左进程数 'leftProcess' => 1, // 中进程数 'centerProcess' => 5, // 任务超时时间 (秒) 'timeout' => 5, ] ); } // 启动 public function actionStart() { // 预处理 if (!parent::actionStart()) { return ExitCode::UNSPECIFIED_ERROR; } // 启动服务 $service = $this->getTaskService(); $service->on('LeftStart', [$this, 'onLeftStart']); $service->on('CenterStart', [$this, 'onCenterStart']); $service->start(); // 返回退出码 return ExitCode::OK; } // 左进程启动事件回调函数 public function onLeftStart(LeftProcess $worker) { try { // 模型内使用长连接版本的数据库组件,这样组件会自动帮你维护连接不断线 $queueModel = Redis::getInstance(); // 保持任务执行状态,循环结束后当前进程会退出,主进程会重启一个新进程继续执行任务,这样做是为了避免长时间执行内存溢出 for ($j = 0; $j < 16000; $j++) { // 从消息队列中间件阻塞获取一条消息 $data = $queueModel->brpop('queue:email', 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['subject'])) ->setFrom([self::USERNAME => '**网']) ->setTo($data['to']) ->setBody($data['body']); // Send the message $result = $mailer->send($message); return $result; } }
Test
[root@localhost bin]# ./mix-daemon push start mix-daemon 'push' start successed.
Die Test-E-Mail wurde erfolgreich empfangen:
Das 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 implementierenPHP 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!