apacheにはMPM(マルチプロセッシングモジュール)というのがあって、代表的なものに
- prefork
- worker
- event
てのがある。RHEL8では、eventがデフォルトになっている。
preforkのMaxClientsとかは計算がしやすかったし、httpd.confに数字がもともと書いてた気がする。RHEL7のyum版apche2.4とかだと。
RHEL7のyum版apche2.4だと、eventの設定された数字がconf内に見当たらない。
デフォルトでどれくらいのリクエストをさばけるの?
結論
手元の、RHEL8.4 (またはRockyLinux 8.5)、Apache2.4 環境だと、以下だった。
ワーカースレッド(実際に働くやつ):400
リスナースレッド(受け付けのやつ):800
合計:1200
qiita
この解説してる方の図、めっちゃわかりやすい。。
リクエストが来たら、リスナースレッドが受け取って、ワーカースレッドが処理すると。
ポイント1.プロセス内のワーカースレッドの数は固定
プロセス内のワーカースレッドの数は固定で、ワーカースレッドの数はワーカープロセス単位で増減します
ワーカースレッド(ThreadsPerChild)が25だったら、
接続数が増えても、プロセス内のスレッドの数は増えずに、ワーカースレッド25を持つプロセスが増えて行く。
ってイメージなんですね。
ポイント2.eventでは、ワーカースレッドより多くの接続数を捌ける
worker_mpmではワーカースレッドの数と接続の数は同じでしたが、event MPMではリスナースレッドに返したぶんだけ接続の方が多くなる場合があります
たとえば、
- 現在の接続が、3
だったとして、そのうちの1つが、
keep aliveな接続でレスポンスを返し終わって次のリクエストを待っている時
などの条件に該当して、リスナースレッドに返された場合、
接続は3だけど、
- 処理中(busy)のワーカースレッド数は、2
- 処理中(処理待ちと言うべき?)のリスナースレッドの数は、1
になるんじゃな。
実際に自分のApache環境で確認してみる
、実際のところはどうなっているのでしょうか。プロセスとワーカースレッドの状態はスコアボードから参照することができます。
スコアボードというのは、server-status で見ることができる。
conf.d/serverstatustest.conf
みたいな新規ファイル追加する。内容は以下。
<Location /server-status> SetHandler server-status </Location>
(※※本番環境でこれまるごと設置したままにしちゃ駄目ですよ!)
実際自分で試したら、以下のようになった。(環境はRockyLinux8.5 Apache2.4 dnf版)
この場合、3つのプロセスが立ち上がってて、それぞれ25のスレッドが在る。
その下に表示されていたワーカースレッドの状態が以下。
____W___________________________________________________________
___________.....................................................
................................................................
................................................................
................................................................
................................................................
................
- _・・・アイドル
- w・・・書き込み中
- .・・・空きスロット
数えてみると全部で400だった。
てことはワシの環境のeventの最大処理数のデフォ値は、400以上っぽい。
⇒400「以上」と書いたのは、さっき見たとおり、400の他にリスナースレッドに返される分があるから
まとめ
ということで設定の指針としてはこんな感じになるのではないかと思います。MaxRequestWorkers
同時リクエスト処理数~以下略~
eventの最高パフォーマンスを叩き出した設定値
静的コンテンツに対する同時接続数100程度に対して最高のパフォーマンスを示すevent_mpmの設定は以下のようになりました。
StartServers 4
MinSpareThreads 4
MaxSpareThreads 4
ThreadsPerChild 2
MaxRequestWorkers 2
MaxConnectionsPerChild 0
MaxRequestWorkers 2
コア4つのメモリ8G環境で、同時接続数を万のオーダーで処理できるような設定を検討した結果、以下のような設定になりました。
AsyncRequestWorkerFactor 2
ServerLimit 32
MaxRequestWorkers 8192
ThreadLimit 256
StartServers 2048
MinSpareThreads 2048
MaxSpareThreads 2048
ThreadsPerChild 256
MaxConnectionsPerChild 0
event概要
eventは、一つのプロセスで複数のリクエストを処理する。
workerやpreforkは、
keep-alive待ちのプロセスはタイムアウト待ちまで待ち続けるという事が起きていたが、
eventは、
eventではkeep-alive周りの処理を整理し、HTTPに関してはひとつのプロセスで複数の処理を行なえる。
ほうほう。
slowattackとかにも強そうですな。
最大接続数の計算式
最大接続数の計算式(はてぶ)
ワーカースレッドを使い尽くした場合でも非同期処理が
できるように
!?
ワーカースレッド使い尽くしてもまだリクエスト処理できるってコツ?
非同期処理っていうのはワーカースレッドからリスナースレッドに返されてる処理のことですな。
アイドル状態のワーカースレッドの平均値がわかる場合、全プロセスでの最大接続数は以下の式で算出できます。
(ThreadsPerChild +( AsyncRequestWorkerFactor × アイドル状態のワーカースレッド数)) × ServerLimit
eventの最大同時接続数計算
最大接続数の計算
max_connections = (ThreadsPerChild + (AsyncRequestWorkerFactor * idle_workers)) * ServerLimit
max_connections = (AsyncRequestWorkerFactor + 1) * MaxRequestWorkers
あれ?てことは、さっきqiitaの記事であったMaxRequestWorkersが最大接続数ってのとは違ってくるな。。。
前者の計算式はさきほどのはてぶのと同じ。
後者の計算式で行くと、ワシの環境で考えれば、
- AsyncRequestWorkerFactor が、2(デフォルト値)
- MaxRequestWorkers が、400 ぽいので、
(2 + 1) * 400 = 1,200
ということになりますな。
繰り返しになるが、AsyncRequestWorkerFactor の値の意味は、ワーカースレッドからリスナースレッドに返される非同期処理のキャパ。
デフォルトが2なので、ワーカースレッドの倍の数を取ってるということ。
計算式の中にある「+ 1」は、ワーカースレッドの積(掛け算)用の係数でしょうな。
apche公式にも同じ計算式が載ってる。
てことは、ワシの環境でのeventの最大接続数は1,200ってことか。。
ThreadsPerChildとは
それぞれの子プロセスで生成される スレッド数を設定します。 子プロセスは開始時にこれらのスレッドを生成して、 その後は生成しません
1プロセスの中にあるスレッドの数は固定ってことですね。さっき見たqiitaの記事にもありましたね。
mpm_winntでの ThreadsPerChild のデフォルト値は 64 で、他の場合は 25 です。
てことはデフォ値は25であると。
さっき見た自分の環境(server-status)でも25であること確認しましたね。
AsyncRequestWorkerFactorとは
プロセスごとの同時接続を制限する
各設定項目の意味やデフォルト値が表にされてるサイトさま
こちらのサイトにわかりやすくまとめてくださっているではないか!
ここの計算だと、
MaxRequestWorkers(ワーカースレッド全体合計の最大値)の、デフォルト値は
ServerLimit(16) × ThreadsPerChild(25) = 400
てことになりますな。
ワテの環境(RockyLinux8.5、dnf版Apache2.4)とも一致。
ab (apache bench) コマンド で、1,000同時アクセス してみる
(ab コマンド参考)gg
ab -n 1000 -c 1000 http://localhost/
で同時に1000人アクセスさせてみる。
すると、server-status/ では以下のようになった。(以下は、1000人アクセスの数秒後の画面)
busy と idle 合わせて400になってますなー。
しつこいけど、この400は、ワーカースレッドのキャパ。
リスナースレッドは800あるはずだで。
また、apacheのerror_logにも以下が出力されていた。
[mpm_event:error] [pid 100:tid 140375903906112] AH00484: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting
コメント