你是否也困在redis,知其然不知其因此然~~ 項目中,到底怎麼用?? 一個簡單的實例,使用消息隊列實現下yii異步發送郵件php
首先得配置redis服務,以前寫過相關的文章,能夠參考下這裏 https://segmentfault.com/a/11...html
yii的redis操做庫:https://github.com/yiisoft/yi...git
使用composer安裝redis的依賴庫github
php composer.phar require --prefer-dist yiisoft/yii2-redis
web.php的相關配置:web
return [ //.... 'components' => [ 'redis' => [ 'class' => 'yii\redis\Connection', 'hostname' => 'localhost', 'port' => 6379, 'database' => 0, ], ] ];
到此,yii中就能夠使用redis進行操做了redis
那麼如何實現異步消息隊列發送郵件呢??數據庫
傳統的操做方法是這樣的:json
用戶輸入郵件信息swift
服務器獲取用戶輸入的數據,提交到第三方的郵件服務器segmentfault
第三方郵件服務器發送郵件,返回處理結果
異步的處理郵件發送:
用戶輸入郵件相關信息
將註冊信息存儲在內存隊列,通知用戶發送成功
服務器端監聽內存隊列,將內存隊列中的郵件數據依次發送 用戶感知不到
二者的區別在哪?
異步相對於同步來講,頁面非阻塞,減小了用戶等待的時間體驗相對來講比較好
原理:
用戶輸入郵件信息,服務器接收到輸入的郵件信息,調用mail的過程,實則是對mail類屬性賦值的過程,這個時候,咱們能夠抓取用戶的信息,存儲到隊列,而後在隊列中,依次讀取郵件信息,進行發送
//實例化mail組件 $mailer = Yii::$app->mailer->compose(); $mailer->setFrom('發件人地址'); $mailer->setTo('收件人地址'); $mailer->setSubject('發送標題'); //if ($mailer->send() && $this->reg($data, 'regbymail')) { //注意這裏 自己是直接調用 send方法 進行發送 如今重寫父類方法 使用redis進行處理 if ($mailer->queue()) { return true; }
這個時候 會去實例化mail類 進行郵件發送,這個時候 咱們能夠抓取郵件信息 存儲到隊列中
<?php namespace mail\mailerqueue; use Yii; class Message extends \yii\swiftmailer\Message { /*抓取郵件信息到redis的隊列*/ public function queue() { $redis = Yii::$app->redis; if (empty($redis)) { throw new \yii\base\InvalidConfigException('redis not found in config.'); } // 0 - 15 select 0 select 1 // db => 1 $mailer = Yii::$app->mailer; //mail郵件存儲的數據庫 是否存在 if (empty($mailer) || !$redis->select($mailer->db)) { throw new \yii\base\InvalidConfigException('db not defined.'); } //抓取郵件信息 $message = []; $message['from'] =array_keys($this->from); $message['to'] = array_keys($this->getTo()); $message['cc'] = array_keys($this->getCc()); $message['bcc'] = array_keys($this->getBcc()); $message['reply_to'] = array_keys($this->getReplyTo()); $message['charset'] = array_keys($this->getCharset()); $message['subject'] = array_keys($this->getSubject()); //獲取郵件信息及子信息 $parts = $this->getSwiftMessage()->getChildren(); if (!is_array($parts) || !sizeof($parts)) { $parts = [$this->getSwiftMessage()]; } foreach ($parts as $part) { if (!$part instanceof \Swift_Mime_Attachment) { //獲取內容類型 switch($part->getContentType()) { case 'text/html': $message['html_body'] = $part->getBody(); break; case 'text/plain': $message['text_body'] = $part->getBody(); break; } if (!$message['charset']) { $message['charset'] = $part->getCharset(); } } } //序列化抓取的內容 存放到隊列中 return $redis->rpush($mailer->key, json_encode($message)); } } 接下來就是讀取redis隊列,進行發送的過程 <?php namespace mail\mailerqueue; use Yii; class MailerQueue extends \yii\swiftmailer\Mailer { public $messageClass = "doctorjason\mailerqueue\Message"; public $key = 'mails'; public $db = '1'; /*發送郵件*/ public function process() { $redis = Yii::$app->redis; if (empty($redis)) { throw new \yii\base\InvalidConfigException('redis not found in config.'); } //若是隊列中 存在數據 if ($redis->select($this->db) && $messages = $redis->lrange($this->key, 0, -1)) { $messageObj = new Message; //遍歷郵件列表 foreach ($messages as $message) { $message = json_decode($message, true); if (empty($message) || !$this->setMessage($messageObj, $message)) { throw new \ServerErrorHttpException('message error'); } if ($messageObj->send()){ $redis->lrem($this->key, -1, json_encode($message)); } } } return true; } //設置消息頭部 public function setMessage($messageObj, $message) { if (empty($messageObj)) { return false; } if (!empty($message['from']) && !empty($message['to'])) { $messageObj->setFrom($message['from'])->setTo($message['to']); if (!empty($message['cc'])) { $messageObj->setCc($message['cc']); } if (!empty($message['bcc'])) { $messageObj->setBcc($message['bcc']); } if (!empty($message['reply_to'])) { $messageObj->setReplyTo($message['reply_to']); } if (!empty($message['charset'])) { $messageObj->setCharset($message['charset']); } if (!empty($message['subject'])) { $messageObj->setSubject($message['subject']); } if (!empty($message['html_body'])) { $messageObj->setHtmlBody($message['html_body']); } if (!empty($message['text_body'])) { $messageObj->setTextBody($message['text_body']); } return $messageObj; } return false; } }
到此 咱們就實現了redis隊列異步發送郵件