redis的簡單使用 異步發送郵件

你是否也困在redis,知其然不知其因此然~~ 項目中,到底怎麼用?? 一個簡單的實例,使用消息隊列實現下yii異步發送郵件php

redis~~準備工做:

首先得配置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

redis~~同步與異步

那麼如何實現異步消息隊列發送郵件呢??數據庫

傳統的操做方法是這樣的:json

  1. 用戶輸入郵件信息swift

  2. 服務器獲取用戶輸入的數據,提交到第三方的郵件服務器segmentfault

  3. 第三方郵件服務器發送郵件,返回處理結果

異步的處理郵件發送:

  1. 用戶輸入郵件相關信息

  2. 將註冊信息存儲在內存隊列,通知用戶發送成功

  3. 服務器端監聽內存隊列,將內存隊列中的郵件數據依次發送 用戶感知不到

二者的區別在哪?

異步相對於同步來講,頁面非阻塞,減小了用戶等待的時間體驗相對來講比較好

redis~~郵件發送

原理:
用戶輸入郵件信息,服務器接收到輸入的郵件信息,調用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隊列異步發送郵件

相關文章
相關標籤/搜索