リクエスト処理中にapache2をstopしたら、そのリクエストスレッドは途中で中断するのでしょうか?リクエストスレッドの処理が終わるのを待つのでしょうか?
結果
停止コマンド | リクエストスレッドの結果 |
---|---|
sudo systemctl stop apache2 | 途中で中断 |
sudo apachectl stop | 途中で中断 |
sudo apachectl graceful-stop | 処理完了を待つ、ただし新しいリクエストは拒否 |
AWS Beastalkのデプロイやオートスケール縮小でインスタンス削除しますが、このときのapache2の停止方法がstopなのかgraceful-stopなのかがわかりませんでした。
インスタンス削除するとき、処理中のスレッドは中断されるのでしょうか、処理が終わるのを待ってから、インスタンス削除するのでしょうか?
それを調べるための下調べです。
なぜ、こんなことを調べたいのかといいますと、
リクエストスレッドの処理で、MySQLへのDBアクセスしかしていないなら、トランザクション開始しておくことで、スレッドが中断してしまっても不正なデータが保存されることはありません。
ところが最近は、外部サービスのAPIと連携することも多いです。
APIレスポンスを待ってDB保存まで完了できるのなら、あまり心配はありません。
しかし、APIレスポンスを待っている途中で中断してしまったら、外部サービスの状態とこちらの状態が不整合になってしまうことがあります。結果整合性を保てるようにシステムや処理を組み立てる必要があります。
実験準備
/var/www/html/longprocess.php を用意します。
処理内容は、
- /var/www/html/log.txtに日時を記録
- 20秒待つ
- /var/www/html/log.txtに日時を記録
ブラウザに表示するだけでいいと思うけど、log.txtへの保存は必要なの?
ブラウザとの接続は切断しても、リクエストスレッド処理は継続しているかもしれないことを考えたのね
#1<br>
<?php
$i = $_GET['i'];
$fp = fopen("/var/www/html/log.txt", "a");
fputs($fp, "i=$i\n");
fputs($fp, "i=$i " . strftime('%H:%M:%S') . "\n");
fclose($fp);
$time = time();
while (time() < $time + 20) {
$x = sin(time());
}
$fp = fopen("/var/www/html/log.txt", "a");
fputs($fp, "i=$i " . strftime('%H:%M:%S') . "\n");
fclose($fp);
?>
#9<br>
Code language: HTML, XML (xml)
ターミナル1
log.txtを新規作成して、chmod 666 しておきます。log.txtをtail -f で監視します。
$ cd /var/www/html
$ sudo touch log.txt
$ sudo chmod 666 log.txt
$ tail -f log.txt
Code language: JavaScript (javascript)
ターミナル2
apache2を起動します。
$ sudo systemctl start apache2
ブラウザ1http://localhost/longprocess.php?i=1
にアクセスします。ブラウザ上には、約20秒かかって、
#1
#9
Code language: CSS (css)
と表示されます。
ターミナル1には、次のような表示がされます。
i=1
i=1 17:59:37
i=1 17:59:57
実験1 systemctl stop apache2
ターミナル2
apache2を起動します。
$ sudo systemctl start apache2
ブラウザ1http://localhost/longprocess.php?i=1
にアクセスします。
ターミナル1
すぐに表示されます。
i=1
i=1 18:21:22
ターミナル2
apache2を停止します。
$ sudo systemctl stop apache2
ターミナル1
20秒待っても、さきほどの表示から変化はありません。20秒間の処理の途中で、中断してしまいました。
i=1
i=1 18:21:22
実験2 apachectl stop
ターミナル2
apache2を起動します。
$ sudo systemctl start apache2
ブラウザ1http://localhost/longprocess.php?i=1
にアクセスします。
ターミナル1
すぐに表示されます。
i=1
i=1 18:24:44
ターミナル2
apache2を停止します。
$ sudo apachectl stop
ターミナル1
20秒待っても、さきほどの表示から変化はありません。20秒間の処理の途中で、中断してしまいました。
i=1
i=1 18:24:44
実験3 apachectl graceful-stop
ターミナル2
apache2を起動します。
$ sudo systemctl start apache2
ブラウザ1http://localhost/longprocess.php?i=1
にアクセスします。
ターミナル1
すぐに表示されます。
i=1
i=1 18:26:36
ターミナル2
apache2を停止します。
$ sudo apachectl graceful-stop
ブラウザ1
ブラウザのクルクルは回ったままです。
ターミナル1
20秒待つと、2回目の日時表示が表示されました。リクエストスレッドの処理が最後まで処理されました。
i=1
i=1 18:26:36
i=1 18:26:56
実験4 apachectl graceful-stopしてからブラウザアクセスすると
ターミナル2
apache2を起動します。
$ sudo systemctl start apache2
ブラウザ1http://localhost/longprocess.php?i=1
にアクセスします。
ターミナル1
すぐに表示されます。
i=1
i=1 18:26:36
ターミナル2
apache2を停止します。
$ sudo apachectl graceful-stop
ブラウザ1
ブラウザのクルクルは回ったままです。
ブラウザ2
http://localhost/longprocess.php?i=2
にアクセスします。
しかし、接続拒否でした。
ターミナル1
i=2 の表示はありません。
20秒待つと、i=1の2回目の日時表示が表示されました。リクエストスレッドの処理が最後まで処理されました。
i=1
i=1 18:26:36
i=1 18:26:56