Laravel 中使用 Beanstalkd 訊息佇列系統傳送郵件

IMWNK發表於2018-09-08

Beanstalkd是一個高效能、輕量級的分散式記憶體佇列系統,最初設計的目的是想通過後臺非同步執行耗時的任務來降低高容量Web應用系統的頁面訪問延遲,支援過有9.5百萬使用者的Facebook Causes應用。處理能力接收到考驗,官網最新版本已是四年前的版本,不顧這絲毫不影響其效能。

環境準備

  • 系統環境 :centos7 + mysql 5.7 + nginx 1.14 + php7.2 + Laravel 5.6(僅供參考)

  • Supervisor 程式管理工具。 使用 Supervisor 接管 Beanstalkd ,前面文章我已說明如何安裝配置 Supervisor 。如果前面沒有閱讀過或者安裝過,建議去看一下 地址:Supervisor 安裝配置與使用詳解

  • Beanstalkd 訊息佇列系統。Beanstalkd 的安裝也在前面的文章提到過。安裝比較簡單。安裝參考地址:Beanstalkd - 高效能、輕量級的分散式記憶體佇列系統

  • Laravel Beanstalkd佇列系統擴充套件包。這裡使用 pda/pheanstalk ~3.0 使用 composer require pda/pheanstalk 命令引入或者加入到 composer.json 檔案中 。

建立任務

作為演示,這裡主要以我部落格為例子,在 Laravel 框架裡使用佇列傳送通知郵件 。首先確保前面的環境準備好 。

生成郵件傳送任務類

在你的應用程式中,佇列的任務類都預設放在 app/Jobs 目錄下。如果這個目錄不存在,那當你執行 artisan make:job 命令時目錄就會被自動建立。你可以用以下的 Artisan 命令來生成一個傳送郵件的佇列任務:

php artisan make:job SendEmail

執行命令會在 app/jobs 目錄下生成一個SendEmail 任務類。我們需要對預設的類進行修改,使其達到我們的要求。

例如:

<?php

namespace App\Jobs;

use App\Helpers\Extensions\Tool;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class SendEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * 任務最大嘗試次數。
     *
     * @var int
     */
    public $tries = 5;

    /**
     * 任務執行的超時時間。
     *
     * @var int
     */
    public $timeout = 300;

    /**
     * 收件人郵箱地址
     *
     * @var
     */
    protected $email;

    /**
     * 收件人名稱
     *
     * @var
     */
    protected $name;

    /**
     * 郵件標題
     *
     * @var
     */
    protected $subject;

    /**
     * 郵件內容資料
     *
     * @var $content
     */
    protected $data;

    /**
     * SendEmail constructor.
     * @param $param
     */
    public function __construct($param)
    {
        $this->email = $param['email'];
        $this->name = $param['name'];
        $this->subject = $param['subject'];
        $this->data = $param['data'];
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        // 這裡使用的我封裝的傳送郵件 助手函式
        Tool::sendEmail($this->email, $this->name, $this->subject, $this->data, 'emails.base');
    }
}

傳送郵件助手函式:

    /**
     * 傳送郵件函式
     *
     * @param  string $email           郵箱  如果群發 則傳入陣列
     * @param string $name             名稱
     * @param string $subject          標題
     * @param array $data              郵件模板中用的變數 示例:['name'=>'xxx','content'=>'xxx']
     * @param string $template         郵件模板
     * @return array                   傳送狀態
     */
    function sendEmail($email, $name, $subject, $data = [], $template = 'emails.base')
    {
        Mail::send($template, $data, function ($message) use ($email, $name, $subject) {
            if (is_array($email)) {
                foreach ($email as $k => $v) {
                    $message->to($v, $name)->subject($subject);
                }
            } else {
                $message->to($email, $name)->subject($subject);
            }
        });
        return (count(Mail::failures()) > 0)?['status_code' => 500, 'message' => '郵件傳送失敗']:['status_code' => 200, 'message' => '郵件傳送成功'];
    }

到這裡建立任務類完成,下面是分發任務。

分發任務

建立任務類完成 後,就是任務的觸發和分發了 。Laravel 的任務類提供 dispatch 方法分發它。傳遞給 dispatch 方法的引數將會被傳遞給任務的建構函式:

立即分發


use use App\Jobs\SendEmail;

// 具體方法中分發 ,注意 下面連結的 是 Beanstalkd 驅動
SendEmail::dispatch($param)->onConnection('beanstalkd');

延遲分發


use use App\Jobs\SendEmail;

// 延遲10分鐘
SendEmail::dispatch($param)->delay(now()->addMinutes(10));->onConnection('beanstalkd');

Laravel 中還提供很多引數 配置,這裡不再多說。具體參考 官方文件 佇列

佇列處理器

執行命令 php artisan queue:work 開啟佇列監聽。

建議使用程式管理器 Supervisor 來確保佇列處理器不會停止執行。

這裡貼出我的 Supervisor 配置:

[program:lablog-beanstalkd-queue-1]
command=/your/php/path/php /your/laravel/path/artisan queue:work beanstalkd --daemon 
process_name=%(program_name)s_%(process_num)02d
numprocs=3
autostart=true
startsecs = 5
autorestart=true
startretries=3
user=root
stopsignal=INT
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=10
stdout_capture_maxbytes=10MB
redirect_stderr=true
stdout_logfile=/etc/supervisor/logs/lablog-beanstalkd-queue-1.log

在這裡 numprocs 會告訴 Supervisor 執行 3 個 queue:work 程式並且管理它們,當它們關閉時會將其自動重啟。當然,你應該將 command 選項中的 queue:work 部分修改為你的佇列連線。

啟動 supervisor 即可進行佇列監聽。要了解更多關於 Supervisor 的資訊,查詢 Supervisor 文件

Snipaste_2018-09-08_11-39-47.png

接下來皆可以 再具體邏輯中使用任務傳送郵件,想要檢視佇列執行 的情況可以通過日誌檔案檢視。通常如下 :

[2018-09-04 15:34:09][16] Processed:  App\Jobs\SendEmail
[2018-09-04 15:42:57][17] Processing: App\Jobs\SendEmail
[2018-09-04 15:42:58][17] Processed:  App\Jobs\SendEmail
[2018-09-04 23:25:57][1] Processing: App\Jobs\SendEmail
[2018-09-04 23:25:58][1] Processed:  App\Jobs\SendEmail
[2018-09-05 21:00:35][3] Processing: App\Jobs\SendEmail
[2018-09-05 21:00:35][4] Processing: App\Jobs\SendEmail
[2018-09-05 21:00:35][2] Processing: App\Jobs\SendEmail
[2018-09-05 21:00:37][3] Processed:  App\Jobs\SendEmail
[2018-09-05 21:00:37][4] Processed:  App\Jobs\SendEmail
[2018-09-05 21:00:37][2] Processed:  App\Jobs\SendEmail

如果想 要檢視 Beanstalkd 中 佇列情況,這需要安裝具體的 Beanstalkd 視覺化工具,這裡推薦兩個:具體安裝使用參考原作者。

  1. ptrofimov/beanstalk_console 這個專案作為訊息佇列的控制檯,直觀的檢視佇列任務的執行。packagist 地址
  2. xuri/aurora aurora是一個基於Web的Beanstalk佇列伺服器控制檯,用Go編寫,適用於macOS,Linux和Windows機器。 github 地址
本作品採用《CC 協議》,轉載必須註明作者和本文連結

歡迎訪問我的個人部落格 https://imwnk.cn

相關文章