LoginSignup
23
17

More than 5 years have passed since last update.

Laravel で Redis と Supervisor を使ってメール送信を非同期にする

Last updated at Posted at 2016-11-23

やりたいこと

メール送信処理を非同期で実行できるようにしたい。
つまりphp artisan queue:workがバックグラウンドで実行されている状態を目指す。

そのためにはキャッシュサーバーと、上記コマンドがバックグラウンドで実行できる環境が必要。
なので、Redis(キャッシュサーバー)と Supervisor(上述コマンドがバックグラウンドで実行できる環境)を導入する。

※Queue サービスが SQS とかになってもこの手順は変わらないはず。

環境

  • CentOS 7
  • PHP 7
  • Laravel 5.3

Redis インストール

インストール

sudo yum --enablerepo=remi,remi-test,epel install redis

起動

sudo systemctl start redis

起動確認

redis-cli ping

PONG

と表示されればOK

Redis クライアントライブラリインストール

設定周り変更

.env
QUEUE_DRIVER=redis
config/queue.php
'default' => env('QUEUE_DRIVER', 'redis'),
composer.json
"predis/predis": "~1.0"

Jobを作成する

php artisan make:job SampleJob

->Job created successfully.

確認用に適当な出力を書く

app/Jobs/SampleJob.php
public function handle()
{
    echo 123;
}

Queue に登録する

SampleController.php
  dispatch(new \App\Jobs\SampleJob());

Queue リスナー起動

php artisan queue:listen

123

と表示されればOK

Supervisor インストール

supervisorsupervisordが紛らわしいので注意。

インストール

sudo yum install supervisor

バージョン確認

rpm -qa | grep supervisor

supervisord 起動

sudo systemctl start supervisord.service

起動確認

sudo systemctl status supervisord.service

自動起動にする

sudo systemctl enable supervisord.service

設定ファイル編集

必要最低限の部分だけ編集する。
そもそもこの場所に無いかもしれないので注意。

/etc/supervisord.conf
[inet_http_server]  ; inet (TCP) server disabled by default
port=0.0.0.0:9001   ; (ip_address:port specifier, *:port for all iface)
username=user       ; (default is no username (open server))
password=123        ; (default is no password (open server))

[program:worker]
command=php artisan queue:work redis --tries=1 --sleep=3  ; the program (relative uses PATH, can take args)
process_name=%(program_name)s_%(process_num)02d           ; process_name expr (default %(program_name)s)
numprocs=2                                                ; number of processes copies to start (def 1)
directory=/home/projectname                               ; directory to cwd to before exec (def no cwd)
autostart=true                                            ; start at supervisord start (default: true)
autorestart=true                                          ; retstart at unexpected quit (default: true)
user=root                                                 ; setuid to this UNIX account to run the program
redirect_stderr=true                                      ; redirect proc stderr to stdout (default false)
stdout_logfile=/home/projectname/storage/logs/worker.log  ; stdout log path, NONE for none; default AUTO

設定ファイル編集の Tips

  • [inet_http_server]の欄をアンコメントすれば Supervisor をブラウザで管理できる
  • numprocs=はサーバーのコア数と同じにするのが一般的
  • directory=はフルパスにしないと正常に動作しない

supervisord 再起動

sudo systemctl restart supervisord.service

config の再読み込み

sudo supervisorctl reread
reloadではないので注意

設定の反映

sudo supervisorctl update

サービス(ワーカー)起動

sudo supervisorctl start worker:*

確認

sudo supervisorctl status

worker:worker_00 RUNNING pid 667, uptime 2:40:00

のように表示されればOK

ログの場所

  • ワーカー(上述の設定ファイルの記述先)
    • /home/project/storage/logs
  • Supervisor 自体
    • /var/log/supervisor/supervisord.log

非同期でメール送信する

以前投稿したメール送信処理記事のコードを少しだけ変更して、メール送信時にキューを使用するようにする。

app/Mail/RegisterShipped.php
class RegisterApplied extends Mailable implements ShouldQueue
{

と言ってもShouldQueueインターフェイスを追加するだけ。

正常にキューを使用しているか確認

  1. Supervisor を停止
  2. メール送信をする
  3. メールが届いていないことを確認
  4. Supervisor を起動
  5. メールが届いていることを確認

おまけ

実際には Ansible を使って Redis と Supervisor を導入した。
Supervisor 用のsupervisorctlというモジュールが用意されているが、staterereadを指定できなかったので、commandモジュールを使用した。

main.yml
...
- name: reread supervisor
  command: supervisorctl reread
...
23
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
17