AWS Lightsail: WordPress にアクセス過多で 504 エラー

AWS Lightsail: WordPress にアクセス過多で 504 エラー

November 20, 2022

*ところどころ説明口調で書いてはいますが、内容は個人用の備忘録です。

友人のウェブサイトのお手伝いをしているのですが、あるとき少しバズってアクセスが集中した結果、アクセスしようとするとブラウザに以下のエラーが表示される事態になっていた様子。

厳密に言うと、十中八九トラフィック過多が原因でしょうという認識はあったものの、この時点では原因調査前のため、原因はあくまで予想に過ぎません。

Failed to load resource: the server responded with a status of 504 (Gateway Timeout)

急ぎで対応する必要もないし、ケセラセラで、という判断が下されたので、特に対応をしないまま1日近くアクセス不可が続いたのち自然解消。

そこから1、2日たって念の為の事後調査の記録。

1.LightSail のメトリクスから CPU 使用率を確認 #

特に問題ないだろうなと思いつつ一応確認。問題なかった。

LightSail Metric

どちらかというとメモリ使用率の方が知りたかったのだが、これは LightSail のメトリクスからだと確認ができず、各自で Cloud Watch に連携するようにしておかないといけないとのことをこのとき知る。

2.Apache のエラーログを確認 #

ということでウェブサーバのログを見るのが早いのでさっそく確認。

サーバに SFTP 接続。

sftp -i ./LightsailDefaultKey-ap-northeast-1.pem bitnami@12.34.567.890

Apache のログをすべてローカルにコピー。

cd /opt/bitnami/apache/logs/

get -r .

コピーしたものはこんな感じ。

-rw-r--r-- 1 root root 403761 Nov 14 09:37 access_log
-rw-r--r-- 1 root root 184538 Oct 22 23:57 access_log-20221023.gz
-rw-r--r-- 1 root root 199274 Oct 29 23:56 access_log-20221030.gz
-rw-r--r-- 1 root root 250880 Nov  5 23:59 access_log-20221106.gz
-rw-r--r-- 1 root root 230368 Nov 12 23:57 access_log-20221113.gz
-rw-r--r-- 1 root root  32884 Nov 13 23:24 error_log
-rw-r--r-- 1 root root   2345 Oct 22 10:13 error_log-20221023.gz
-rw-r--r-- 1 root root   3114 Oct 29 21:45 error_log-20221030.gz
-rw-r--r-- 1 root root   7500 Nov  5 23:48 error_log-20221106.gz
-rw-r--r-- 1 root root   5679 Nov 12 23:55 error_log-20221113.gz

error_log を確認。

less error_log

必要なら gzip ファイルも展開して確認。

gzip -d error_log-20221113.gz

less error_log-20221113

その結果、ある時点から次のエラーが絶え間なく発生していることが確認できた。

[Sat Nov 12 04:13:52.190883 2022] [mpm_event:error] [pid 1023:tid 140421935123328] AH03490: scoreboard is full, not at MaxRequestWorkers.Increase ServerLimit.
[Sat Nov 12 04:13:53.208420 2022] [mpm_event:error] [pid 1023:tid 140421935123328] AH03490: scoreboard is full, not at MaxRequestWorkers.Increase ServerLimit.
[Sat Nov 12 04:13:53.821376 2022] [mpm_event:alert] [pid 22969:tid 140421391083264] (11)Resource temporarily unavailable: AH03104: ap_thread_create: unable to create worker thread
[Sat Nov 12 04:13:54.209533 2022] [mpm_event:error] [pid 1023:tid 140421935123328] AH03490: scoreboard is full, not at MaxRequestWorkers.Increase ServerLimit.
[Sat Nov 12 04:13:55.210656 2022] [mpm_event:error] [pid 1023:tid 140421935123328] AH03490: scoreboard is full, not at MaxRequestWorkers.Increase ServerLimit.
[Sat Nov 12 04:13:56.211738 2022] [mpm_event:error] [pid 1023:tid 140421935123328] AH03490: scoreboard is full, not at MaxRequestWorkers.Increase ServerLimit.
[Sat Nov 12 04:13:57.212819 2022] [mpm_event:error] [pid 1023:tid 140421935123328] AH03490: scoreboard is full, not at MaxRequestWorkers.Increase ServerLimit.
[Sat Nov 12 04:13:58.213947 2022] [mpm_event:error] [pid 1023:tid 140421935123328] AH03490: scoreboard is full, not at MaxRequestWorkers.Increase ServerLimit.
[Sat Nov 12 04:13:59.261584 2022] [mpm_event:alert] [pid 23104:tid 140421391083264] (11)Resource temporarily unavailable: AH03104: ap_thread_create: unable to create worker thread

このエラーは、サイトが復旧してアクセスできるようになった時間まで続いていた。無事にアクセスできるようになった時間帯以降、上記エラーは発生していない。

3.原因はトラフィック過多 #

上記のエラーメッセージで調べてみると、大方の予想通りトラフィック過多で Apache が捌ききれなくなったのが原因の様子。

メモ:

エラーメッセージで検索しているときに引っかかったので。昔の Apatche にはこんな感じのバグがあったらしい。

When the Apache scoreboard is full, no more new connections can be made and pending connections must wait until an existing connection closes to be able to connect to the server. This can result in slow loading times and time-out errors. This is a known bug in Apache versions before 2.4.7.

でもこれは何年も前の話で、今回は関係ないですね。一応自分の LightSail の Apache のバージョンを確認したら以下でした。まあそりゃそうだ。

httpd -v
# または
apachectl -v

Server version: Apache/2.4.53 (Unix)
Server built: Mar 14 2022 13:20:59

今回の場合は、バグでもなんでもなく、純粋にトラフィック過多が原因でしょう。

4.対策を調べる #

エラーメッセージで検索したときに出てきた次のサイトが非常に参考になりました。

エラーの原因については、このサイトにも、

this problem will happend when you have too much client connection to your website

とはっきり書いてありますね。

対策は Apache の設定を変更して、ServerLimit、ThreadsPerChild、MaxRequestWorkers の調整することです。

実は Apache のエラーログのメッセージにもその旨がはっきり書いてありました。

scoreboard is full, not at MaxRequestWorkers.Increase ServerLimit.

その後見つけたこちらの記事も参考になりました。

5.Apache の設定ファイルを覗いてみる #

cd /opt/bitnami/apache/conf/extra

cat httpd-mpm.conf
# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxRequestWorkers: maximum number of server processes allowed to start
# MaxConnectionsPerChild: maximum number of connections a server process serves
#                         before terminating
<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers          5
    MaxSpareServers         10
    MaxRequestWorkers      250
    MaxConnectionsPerChild   0
</IfModule>

# worker MPM
# StartServers: initial number of server processes to start
# MinSpareThreads: minimum number of worker threads which are kept spare
# MaxSpareThreads: maximum number of worker threads which are kept spare
# ThreadsPerChild: constant number of worker threads in each server process
# MaxRequestWorkers: maximum number of worker threads
# MaxConnectionsPerChild: maximum number of connections a server process serves
#                         before terminating
<IfModule mpm_worker_module>
    StartServers             3
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25
    MaxRequestWorkers      400
    MaxConnectionsPerChild   0
</IfModule>

# event MPM
# StartServers: initial number of server processes to start
# MinSpareThreads: minimum number of worker threads which are kept spare
# MaxSpareThreads: maximum number of worker threads which are kept spare
# ThreadsPerChild: constant number of worker threads in each server process
# MaxRequestWorkers: maximum number of worker threads
# MaxConnectionsPerChild: maximum number of connections a server process serves
#                         before terminating
<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25
    MaxRequestWorkers      400
    MaxConnectionsPerChild   0
</IfModule>

# 以降省略

MPM のセクションが複数見つかる。どこを変更すれば良いのかよくわからなかったので補完調査。

この記事がわかりやすいかったです。

で、まずは自分の現在の設定を確認。

httpd -V | grep MPM

>> Server MPM: event

変更した記憶もないので、どうやらデフォルトが event のようですね。

ということで以下のセクションを変更すれば良いようです。

<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25
    MaxRequestWorkers      400
    MaxConnectionsPerChild   0
</IfModule>

ここに ServerLimit を 16(がデフォルト)以上で追加、それに合わせて ThreadsPerChild と MaxRequestWorkers を調整すればよい様子ですが、はて今のサーバの状態ではどれくらい追加割り当てできるものなのか。

6.割り当て可能容量を算出する #

いまいちどれが良いのかわからない。あくまでも見積りなので、絶対の正解のない世界なのかも。

とりあえず後者の記事を参考に。

free -m

>>               total        used        free      shared  buff/cache   available
>> Mem:            482         255          41          42         185         171
>> Swap:          4730         325        4405

出力結果の見方はこちらを参考に。

available が 171(MB) です。

ps -ylC httpd --sort:rss

>> S   UID   PID  PPID  C PRI  NI   RSS    SZ WCHAN  TTY          TIME CMD
>> S     0   715     1  0  80   0  8824  3150 -      ?        00:03:21 httpd
>> S     1  6161   715  0  80   0 10492 400834 -     ?        00:00:00 httpd
>> S     1  6429   715  0  80   0 11380 400835 -     ?        00:00:00 httpd
>> S     1  6162   715  0  80   0 11684 400788 -     ?        00:00:00 httpd

ここでは分かりやすく Apache 1プロセスあたり約 10MB(= 10000KB) と考えることにしました。

ちなみに一般常識として Apache の1プロセスは大体 10MB らしいです。ですのでこの数値は確からしい。

先の記事に従うと、計算式は以下ですので、

「MaxClients 最大値 = (総メモリ量 - システム全体の消費メモリ量)/(Apache 1 プロセスあたりの消費メモリ量)」

自分のサーバの数字を割り当てるとこうなります。

「MaxClients 最大値 = 171(MB) / 10(MB)」

ということで MaxClients に設定してもいい最大値は「17」ですね。

ちなみに、ここで MaxClients と書いてあるのは MaxRequestWorkers に読み替えます。apache2.4 以前は MaxClients という名称だったものが、MaxRequestWorkers に変わったようですので。

では MaxRequestWorkers に設定できるのは 17 なのね!…あれ、でもいまの設定だと MaxRequestWorkers は 400 になっていたはず。

デフォルトが 400 になっているようだが計算して算出された上限値は 17、これは如何に…。

<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25
    MaxRequestWorkers      400
    MaxConnectionsPerChild   0
</IfModule>

ということで、デフォルト設定でも、少なくとも算出した値以上の数値が設定されている様子であり、ここをいじるのであればもう少し理解を深めてからにしないと危ないな…と思って現在放置されています 😂

おわり #

そもそも友人が LightSail をやめて普通のレンタルサーバに移動しようかなどとも言っていたこともあり、上記の通り深追いせずに途中で調査をやめてしまいました(反省)🐒