【連載】iOS/Androidアプリ開発入門「サーバ連動アプリを開発しよう!」 (9) バックグラウンドでメール送信
みなさん、こんにちは!
iOSとAndroidで本格的なアプリを開発してみたい方向けの連載の第9回です。
これまで同様、本格的なアプリを開発するためには「何を知っておかなければならないか」「何を勉強すればいいか」を中心に書いていきたいと思います。
今回は、ユーザにメールを送信する機能を追加してみましょう。
早速はじめていきましょう。
バックグラウンドでメールを送信する
メール送信処理には時間がかかる
ユーザが新規投稿したら、管理者にメールが届く仕様とします。
メール送信にはだいたい1秒から数秒の時間がかかります。
1つの処理で数秒もユーザを待たせるとユーザ経験(UX)を損ねるため、何らかの対策が必要となります。
バックグラウンドでメール送信処理を行う
そこで、サーバ側でバックグラウンドでメールを送信する仕組みを導入することにしましょう。
「キュー」という仕組みを使います。
キューというのは、タスクをためておける箱のことです。
ユーザが新規投稿したら、サーバ側で「メール送信タスク」を「キュー」に追加します。
そして、メール送信タスクの完了を待たず、すぐにユーザにレスポンスを返します。
こうすれば、ユーザ側で待ち時間が発生しません。
あとは、サーバ側で、キューに溜まったタスクをバックグラウンドで順番に実行していきます。
キューに溜まったタスクを順番に取り出して実行するプログラムのことを「ワーカー」といいます。
ワーカーがキューからタスクを取り出し、実行します。
キュー、ワーカー、タスクの実装
キューはAWSのSQSを使用する
早速実装していきましょう。
まず、キューを実装します。
自分でキューを実装することもできますが、AWSにSQSというキュー専用のサービスがありますので、それを使うと実装の手間が省けます。
利用方法は簡単です。
AWSの管理画面を開き、SQSサービスを選択し、フォームに値を入力していくだけでキューが起動します。
ほぼデフォルト値で問題ありませんので、キューの名前を決めてキューを起動しましょう。
ワーカーはライブラリを使用する
次に、ワーカーを実装します。
ワーカーは、キューに対応したものを実装する必要があります。
自分でワーカーを実装することもできますが、ネットで探すとSQS用のライブラリが見つかりますので、それを使うと実装の手間が省けます。
CakePHPを使用している場合、ワーカーにはcakephp-sqsが使えます。
インストールは、composerというPHPのパッケージ管理ツールを使えば簡単です。
メール送信サーバはAWSのSESを使用する
ワーカーが実装できたら、タスクを実装します。
今回は、タスク=メール送信処理となります。
本来であればメール送信サーバ(SMTPサーバ)を構築する必要があるところですが、AWSにSESというメール送信専用サービスがありますので、それを使うと構築の手間が省けます。
利用方法は簡単です。
AWSの管理画面を開き、SESサービスを選択し、フォームに値を入力していくだけでメール送信サーバが使えるようになります。
このとき、メール送信に使用するID・パスワードが生成されますので、紛失しないようにしましょう。
また、最初はメール送信先のアドレスに制限がかかっていますので、本番稼働前に制限解除の申請を行うのを忘れないようにしてください。
メール送信処理はフレームワークの標準機能で行う
メール送信サーバが利用できるようになれば、サーバ側にメール送信処理を実装します。
CakePHPであれば、CakeEmailという標準機能を使用してメールを送信できます。
このとき、メールのレイアウトを切り替えたり、HTMLで送信したり、高度な設定も可能です。
キュー、ワーカー、タスクを実行する
バックグラウンドで実行する前の動作確認
さて、ここまで実装できたら、キュー、ワーカー、メール送信がそれぞれうまく動作するか、一度テストをしましょう。
手動でキューにタスクを1件追加し、コマンドラインからワーカーを実行して、メールが1件送信されることを確認します。
バックグラウンドで実行する
手動テストが完了したら、いよいよワーカーをバックグラウンドで実行します。
ワーカーをバックグラウンドで実行するには、supervisordというツールを使うと便利です。
supervisordは、ワーカーのような無限ループ型のプログラムをバックグラウンドで安定的に実行してくれます。
プロセスを監視し、終了したら自動で再起動してくれます。
supervisordを使うには、サーバにインストールが必要です。
$ sudo easy_install supervisor
インストール後、設定を行っていきます。
$ sudo -i # echo_supervisord_conf > /etc/supervisord.conf # vi /etc/supervisord.conf (supervisord.confの内容) : [include] files = /etc/supervisord.d/*.conf : # mkdir /etc/supervisord.d # vi /etc/supervisord.d/worker.conf (以下省略)
設定が完了したら、supervisordを起動します。
ここで、実力のある方はシェルスクリプトを書いてsupervisordのサービス化と自動起動設定を行うと良いでしょう。
正しく設定ができていれば、supervisordを起動すれば、自動的にワーカーのプログラムがバックグラウンドで実行されます。
バックグラウンド処理の注意点
さて、ワーカーのような無限ループ型のプログラムをバックグラウンドで実行する際、注意しなければならない点があります。
- CPUに負荷がかかっていないか
- メモリを大量に消費していないか
順に見ていきます。
(1) CPUに負荷がかかっていないか
無限ループ型のプログラムは、何もしないとCPUに負荷がかかります。
プログラムが無限に動き続けるわけですから、当然といえば当然です。
そこで、何らかの待ち処理(ウェイト)を入れてCPUの負荷を抑えます。
今回のケースでは、ロングポーリングという手法でCPUの負荷を一気に下げることができます。
キューを参照し、タスクがなければ新しいタスクが来るまで10秒待機、タスクがあれば(入ってくれば)すぐに取り出して処理します。
こうすることで、処理性能を落とさず、CPUの負荷を下げることができます。
ワーカーの実装(cakephp-sqs)をカスタマイズして、ロングポーリングに変更しましょう。
(app/Plugin/SQS/Model/SimpleQueue.php) : return $this->client()->receiveMessage(array('QueueUrl' => $url, 'WaitTimeSeconds' => 10)); :
(2) メモリを大量に消費していないか
プログラムを長時間動かし続けると、意図せずメモリを大量に消費するケースがあります。
メモリの消費量は、サーバのtopコマンドで見ることができます。
$ top (Shift+Mを押すとメモリ消費量順にソートされる)
原因は、フレームワークやライブラリのメモリリークなどが考えられます。
根本対処は難しいので、暫定対処として「1万回ループしたらプログラムを終了し、再起動する」ような考え方でメモリの消費量を抑えるのが簡単な対策です。
(app/Plugin/SQS/Console/Command/Task/QueueWorkerTask.php) public function work($name = 'default', $max = 10000) { : for ($i = 0; $i < $max; $i++) { foreach ($this->_callbacks as $queue => $callback) { :
こんな感じで、1万回ループしたらプログラムが終了するようにカスタマイズすれば、supervisordが自動的にプログラムを再起動してくれます。
第9回のまとめ
ユーザ経験を損なわず、バックグラウンドでメールを送信してみましょう。
- メール送信処理は重いため、バックグラウンドで実行する
- バックグラウンド実行のために、キュー、ワーカー、タスクを実装する
- キューはAWSのSQSが便利
- ワーカーとタスクはライブラリを探してみる
- メール送信サーバはAWSのSESが便利
- バックグラウンド実行はsupervisordが便利
- CPUの負荷、メモリ消費量に注意する
本日は以上です。
連載目次
iOS/Androidアプリ開発入門「サーバ連動アプリを開発しよう!」
(10) 開発の旅をうまく乗り切る(最終回)
(9) バックグラウンドでメール送信
(8) サーバの監視とデータのバックアップ
(7) リモートサーバ(本番環境)の構築
(6) ローカルでの単体・結合テスト
(5) コントローラーとビューの実装
(4) モデル実装
(3) API実装
(2) 画面設計・データベース設計・API設計
(1) 開発環境の構築