Maison > Article > développement back-end > Utilisez mixphp pour créer un envoi d'e-mails asynchrone multi-processus
Cet article présente principalement l'utilisation de mixphp pour créer un envoi d'e-mails asynchrone multi-processus. Il a une certaine valeur de référence. Maintenant, je le partage avec vous. Les amis dans le besoin peuvent s'y référer
L'envoi d'e-mails est un. exigence très courante., Étant donné que l'opération d'envoi d'e-mails prend généralement du temps, nous utilisons généralement le traitement asynchrone pour améliorer l'expérience utilisateur, et le traitement asynchrone est généralement mis en œuvre à l'aide de files d'attente de messages.
En raison du manque de capacités de développement multi-processus, le framework MVC traditionnel utilise généralement le même script pour être exécuté plusieurs fois pour générer plusieurs processus. Mixphp encapsule TaskExecutor spécifiquement pour le développement multi-processus, et les utilisateurs peuvent développer. très simplement. Une application multi-processus entièrement fonctionnelle et hautement disponible.
Ce qui suit démontre le processus de développement d'un système d'envoi d'e-mails asynchrone, impliquant des points de connaissance :
Asynchrone
File d'attente de messages
Processus multiples
Processus démon
L'utilisation par PHP des files d'attente de messages est généralement implémentée à l'aide d'un middleware de messages couramment utilisé :
redis
rabbitmq
.kafka
Cette fois, nous choisissons redis pour implémenter l'envoi d'e-mails asynchrone. Il existe un type de liste dans le type de données de redis, qui peut implémenter une file d'attente de messages. . Utilisez la commande suivante :
// 入列 $redis->lpush($key, $data); // 出列 $data = $redis->rpop($key); // 阻塞出列 $data = $redis->brpop($key, 10);
Cet exemple utilise le framework MVC traditionnel pour répondre aux exigences d'envoi d'e-mails et le multi-processus MixPHP pour effectuer la tâche d'envoi.
Dans le passé, nous utilisions généralement la bibliothèque d'envoi d'e-mails fournie par le framework, ou téléchargeions des bibliothèques partagées par d'autres utilisateurs en ligne Après l'apparition de composer, https://. packagist.org/ Il existe de nombreuses bibliothèques de haute qualité sur Internet, il suffit de choisir la meilleure. Dans ce cas, nous choisissons Swiftmailer.
La tâche d'envoi étant exécutée par MixPHP, Swiftmailer est installé dans le projet MixPHP. Exécutez la commande suivante dans le répertoire racine du projet pour installer :
composer require swiftmailer/swiftmailer
// 连接 $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));Habituellement, dans le développement asynchrone, un message sera répondu à l'utilisateur immédiatement une fois la livraison terminée. Bien entendu, la tâche n'est pas exécutée à ce moment-là. Développement consommateurDans cet exemple, nous utilisons l'outil de développement multi-processus de MixPHP, TaskExecutor, pour remplir cette exigence. Les processus résidents sont généralement utilisés pour gérer la consommation de file d'attente, nous utilisons donc le type TYPE_DAEMON de TaskExecutor. MODE_PUSH. Le mode MODE_PUSH de TaskExecutor comporte deux processus :
<?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.
Activer l'extension shmop pour PHP afin d'implémenter la mémoire partagée
php implémente la fonction de communication du processus de mémoire partagée ( _shm )
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!