##やりたいこと
メール送信処理を非同期で実行できるようにしたい。
つまり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 クライアントライブラリインストール
設定周り変更
QUEUE_DRIVER=redis
'default' => env('QUEUE_DRIVER', 'redis'),
"predis/predis": "~1.0"
Jobを作成する
php artisan make:job SampleJob
->Job created successfully.
確認用に適当な出力を書く
public function handle()
{
echo 123;
}
Queue に登録する
dispatch(new \App\Jobs\SampleJob());
Queue リスナー起動
php artisan queue:listen
123
と表示されればOK
Supervisor インストール
※supervisor
とsupervisord
が紛らわしいので注意。
インストール
sudo yum install supervisor
バージョン確認
rpm -qa | grep supervisor
supervisord 起動
sudo systemctl start supervisord.service
起動確認
sudo systemctl status supervisord.service
自動起動にする
sudo systemctl enable supervisord.service
設定ファイル編集
必要最低限の部分だけ編集する。
そもそもこの場所に無いかもしれないので注意。
[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 をブラウザで管理できる - http://192.168.00.00(IP):9001
-
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
非同期でメール送信する
以前投稿したメール送信処理記事のコードを少しだけ変更して、メール送信時にキューを使用するようにする。
class RegisterApplied extends Mailable implements ShouldQueue
{
と言ってもShouldQueue
インターフェイスを追加するだけ。
正常にキューを使用しているか確認
- Supervisor を停止
- メール送信をする
- メールが届いていないことを確認
- Supervisor を起動
- メールが届いていることを確認
##おまけ
実際には Ansible を使って Redis と Supervisor を導入した。
Supervisor 用のsupervisorctl
というモジュールが用意されているが、state
にreread
を指定できなかったので、command
モジュールを使用した。
...
- name: reread supervisor
command: supervisorctl reread
...