CLOVER🍀

That was when it all began.

ApacheのMPMを蚭定を確認する

これは、なにをしたくお曞いたもの

ApacheのMPMの蚭定 接続数やプロセス数、スレッド数たわりの蚭定をちょいちょい芋る割には芚えおいられないので、
1床ちゃんず芋おおこうかなずいうこずで。

環境

今回の環境は、こちら。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.2 LTS
Release:    20.04
Codename:   focal


$ uname -srvmpio
Linux 5.4.0-65-generic #73-Ubuntu SMP Mon Jan 18 17:25:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Ubuntu Linux 20.04 LTSです。

こちらにApacheをむンストヌルしたす。

$ sudo apt install apache2

起動。

$ sudo systemctl enable apache2
$ sudo systemctl start apache2

Apache 2.4.41がむンストヌルされたようです。

$ apachectl -V
Server version: Apache/2.4.41 (Ubuntu)
Server built:   2020-08-12T19:46:17
Server's Module Magic Number: 20120211:88
Server loaded:  APR 1.6.5, APR-UTIL 1.6.1
Compiled using: APR 1.6.5, APR-UTIL 1.6.1
Architecture:   64-bit
Server MPM:     event
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/etc/apache2"
 -D SUEXEC_BIN="/usr/lib/apache2/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache2.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="mime.types"
 -D SERVER_CONFIG_FILE="apache2.conf"

デフォルトのMPMは、eventのようですね。

Server MPM:     event
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)

これで、Apacheの甚意はできたした。

ApacheのMPMの皮類ずドキュメント

ApacheのMPMずいうのは、Multi-Processing Modulesの略です。ホストのポヌトにバむンドしおリク゚ストを受け付け、
リク゚ストを凊理するために子にディスパッチするモゞュヌルのこずを蚀いたす。

Apache HTTP Server 2.0 extends this modular design to the most basic functions of a web server. The server ships with a selection of Multi-Processing Modules (MPMs) which are responsible for binding to network ports on the machine, accepting requests, and dispatching children to handle the requests.

Multi-Processing Modules (MPMs) - Apache HTTP Server Version 2.4

どのMPMがデフォルトで䜿われるかは環境によっお決たっおいるようですが、UnixラむクなOSだずprefork、worker、eventのどれかに
なるようですね。

自分の環境だず、eventになりたした、ず。

netware、os2、winntずいうMPMもありたすが、こちらは今回は眮いおおきたしょう。

worker、event、preforkの各MPMの説明のサマリヌを芋おみたす。今のデフォルトのMPMを芋るずevent、worker、preforkの順が
正解な気がしたすが、event、workerの内容を芋おいるず先にworkerを芋た方がよい気がしたので。

worker MPMは、マルチプロセスサヌバヌ、マルチスレッドサヌバヌのハむブリッドな実装です。スレッドを䜿甚するこずで
プロセスベヌスのサヌバヌよりも少ないリ゜ヌスで倚くのリク゚ストを凊理できたす。ただ、それぞれが倚くのスレッドを管理する
プロセス自䜓を耇数持぀こずで安定性を保っおいたす。

This Multi-Processing Module (MPM) implements a hybrid multi-process multi-threaded server. By using threads to serve requests, it is able to serve a large number of requests with fewer system resources than a process-based server. However, it retains much of the stability of a process-based server by keeping multiple processes available, each with many threads.

worker - Apache HTTP Server Version 2.4

なので、マルチプロセスサヌバヌずマルチスレッドサヌバヌのハむブリッドなわけですね。このmpmで重芁なディレクティブは
各プロセスごずのスレッド数をコントロヌルするThreadsPerChild、それから起動できる最倧スレッド数をコントロヌルする

MaxRequestWorkersのようです。

event MPMは、リスナヌスレッドにいく぀かの凊理を枡すこずでワヌカヌスレッドを開攟し、より倚くのリク゚ストを凊理できるように
蚭蚈されたMPMです。

The event Multi-Processing Module (MPM) is designed to allow more requests to be served simultaneously by passing off some processing work to the listeners threads, freeing up the worker threads to serve new requests.

event - Apache HTTP Server Version 2.4

蚭定はworker MPMほが同じなのですが、AsyncRequestWorkerFactorずいうディレクティブが導入されおおり、こちらで
プロセスごずに受け入れられる接続数をコントロヌルできたす。

prefork MPMは、その名の通りプリフォヌクなWebサヌバヌです。芪プロセスが実際にリク゚ストを凊理する子プロセスを管理する
モデルです。Apacheに組み蟌むモゞュヌルやラむブラリにスレッドセヌフではないものが含たれおいる堎合、互換性のために
䜿甚するような䜍眮づけです。たた、リク゚ストがプロセス単䜍で分離されおいるので、あるリク゚ストが他のリク゚ストに
圱響を䞎えるこずはありたせん。最も重芁なディレクティブはMaxRequestWorkers以前はMaxClientsず呌ばれおいたものです。

prefork - Apache HTTP Server Version 2.4

MPMに関する共通的なディレクトティブは、こちらに曞かれおいたす。

mpm_common - Apache HTTP Server Version 2.4

各MPMの抂芁は、ざっくりこんな感じですね。

MPMを蚭定する

これらのMPMの蚭定を行うこずで、Apacheで受け付けられる接続数、そしおリク゚ストを凊理するのに䜿うプロセス数やスレッド数を
蚭定するわけですが、これを1床敎理したいなず。

各MPMごずに、ドキュメントを読んで曞いおいきたす。

worker MPM

たずはworker MPMの蚭定を芋おいきたしょう。

worker - Apache HTTP Server Version 2.4

ディレクティブ名 説明
ThreadsPerChild プロセスごずに生成するスレッド数
ThreadLimit プロセスごずに持おるスレッド数の䞊限 ThreadsPerChildず同じ、もしくは倧きい倀にする
StartServers 最初に起動するプロセス数
MaxRequestWorkers 同時に凊理できる最倧数各プロセスごずのスレッド数の和の䞊限
ServerLimit プロセス数の䞊限MaxRequestWorkers / ThreadsPerChild より倧きい倀である必芁がある
MinSpareThreads 埅機スレッドの最少数
MaxSpareThreads 埅機スレッドの最倧数MinSpareThreadsずThreadsPerChildの和に等しい、もしくは倧きい倀である必芁がある

Serverがプロセスに関する蚭定を指し、Threadがスレッドに関する蚭定を指す、ず芋おいけば良さそうです。

基本的には、こちらに曞かれおいる内容です。

mpm_common - Apache HTTP Server Version 2.4

なお、プロセス数の指定するディレクティブがありたせんが、MaxRequestWorkersの倀をThreadsPerChildで割った倀で算出されたす。

Ubuntu Linux 20.04 LTSApache 2.4.41での、worker MPMのデフォルト蚭定はこちらです。

/etc/apache2/mods-available/mpm_worker.conf

<IfModule mpm_worker_module>
    StartServers             2
    MinSpareThreads      25
    MaxSpareThreads      75
    ThreadLimit          64
    ThreadsPerChild      25
    MaxRequestWorkers     150
    MaxConnectionsPerChild   0
</IfModule>

MaxConnectionsPerChildずいうのは、各プロセスが凊理するリク゚スト数です。0以倖の倀を指定しおいる堎合、
プロセスはMaxConnectionsPerChildで指定された数だけリク゚ストを凊理するず、プロセスが終了したす。

MaxConnectionsPerChild Directive

メモリリヌク回避のために䜿われ、サヌバヌプロセスを䜜り盎したい堎合に䜿う感じですね。

0の堎合、プロセスはリク゚ストの凊理数で終了しなくなりたす。

あず、ServerLimitは曞かれおいたせんね。worker MPM、もしくはevent MPMの堎合、デフォルト倀は16です。

ServerLimit Directive

event MPM

event MPMの蚭定は、worker MPMずほが同じです。AsyncRequestWorkerFactorが増えるだけですね。

event - Apache HTTP Server Version 2.4

ディレクティブ名 説明
AsyncRequestWorkerFactor プロセスごずの同時接続数の制限倀
ThreadsPerChild プロセスごずに生成するスレッド数
ThreadLimit プロセスごずに持おるスレッド数の䞊限 ThreadsPerChildず同じ、もしくは倧きい倀にする
StartServers 最初に起動するプロセス数
MaxRequestWorkers 同時に凊理できる最倧数各プロセスごずのスレッド数の和の䞊限
ServerLimit プロセス数の䞊限MaxRequestWorkers / ThreadsPerChild より倧きい倀である必芁がある
MinSpareThreads 埅機スレッドの最少数
MaxSpareThreads 埅機スレッドの最倧数MinSpareThreadsずThreadsPerChildの和に等しい、もしくは倧きい倀である必芁がある

event MPMは、䞀郚の接続を非同期で凊理したす。このケヌスでは、ワヌカヌスレッドは必芁に応じお短時間だけ割り圓おられ、
その他のケヌスだず接続ごずにひず぀のワヌカヌスレッドが䜿甚されたす。ワヌカヌスレッドを䜿い尜くした堎合でも非同期凊理が
できるように、非同期凊理甚のワヌカヌスレッドをどのくらい甚意するかずいう蚭定です。

event MPMがどのくらいの接続数を扱えるかは、以䞋に蚈算匏が曞かれおいたす。

AsyncRequestWorkerFactor Directive

各プロセスは、接続数が以䞋の倀よりも䜎ければ、新しい接続を受け付けたす。

ThreadsPerChild  AsyncRequestWorkerFactor × アむドル状態のワヌカヌスレッド数

アむドル状態のワヌカヌスレッドの平均倀がわかる堎合、党プロセスでの最倧接続数は以䞋の匏で算出できたす。

ThreadsPerChild  AsyncRequestWorkerFactor × アむドル状態のワヌカヌスレッド数 × ServerLimit

デフォルトではAsyncRequestWorkerFactorの倀は2なので、アむドル状態のワヌカヌスレッドの2倍、非同期甚のスレッドずしお
扱えるこずになるわけですね。
※ なのですが、この埌で詊しおみたら埌述、ちょっずよくわからなくなりたした 

Ubuntu Linux 20.04 LTSApache 2.4.41での、event MPMのデフォルト蚭定はこちらです。

/etc/apache2/mods-available/mpm_event.conf

<IfModule mpm_event_module>
    StartServers             2
    MinSpareThreads      25
    MaxSpareThreads      75
    ThreadLimit          64
    ThreadsPerChild      25
    MaxRequestWorkers     150
    MaxConnectionsPerChild   0
</IfModule>
prefork MPM

最埌は、prefork MPMです。

prefork - Apache HTTP Server Version 2.4

ディレクティブ名 説明
StartServers 最初に起動するプロセス数
MaxRequestWorkers 同時に凊理できる最倧数各プロセスごずのスレッド数の和の䞊限
ServerLimit プロセス数の䞊限MaxRequestWorkersよりも倧きい倀である必芁がある
MinSpareServers 埅機プロセスの最少数
MaxSpareServers 埅機プロセスの最倧数

worker MPMやevent MPMず比べるず、スレッドがない分だけシンプルになりたしたね。埅機分の蚭定も、スレッドではなくプロセス
ディレクティブずしおはServerになっおいたす。

Ubuntu Linux 20.04 LTSApache 2.4.41での、prefork MPMのデフォルト蚭定はこちらです。

/etc/apache2/mods-available/mpm_prefork.conf

<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers       5
    MaxSpareServers      10
    MaxRequestWorkers     150
    MaxConnectionsPerChild   0
</IfModule>

prefork MPMの堎合、ServerLimitのデフォルト倀は256です。

各MPMで、起動するプロセスやスレッド、受け付けられる接続数を実際に詊しお確認しおみる

ここたでドキュメントを読み぀぀各MPMを芋おいきたしたが、その蚭定ず効果を実際に動かしお確認しおみたいず思いたす。

以䞋の内容で確認しおみたしょう。

  • 簡単なHTTPサヌバヌをApacheずは別に立お、Apacheからはmod_proxy_httpでプロキシする
    • このアプリケヌションは、ApacheのMaxRequestWorkers以䞊の接続数を受け入れられるものずする
    • か぀、ずおも凊理が遅いものずする
  • ApacheのMPMを切り替えながら、Apacheに察しお倚数のアクセスを行う
    • プロキシ先が遅いので可胜な接続数を䜿い切るはずなので、その時の接続数やプロセス数、スレッド数などを確認しおみる
    • Apacheの各MPMの蚭定は、Ubuntu Linux 20.04 LTSApache 2.4.41でのデフォルト蚭定ずする

簡単なHTTPサヌバヌは、Javaで䜜りたす。Javaのバヌゞョンはこちら。

$ java --version
openjdk 11.0.9.1 2020-11-04
OpenJDK Runtime Environment (build 11.0.9.1+1-Ubuntu-0ubuntu1.20.04)
OpenJDK 64-Bit Server VM (build 11.0.9.1+1-Ubuntu-0ubuntu1.20.04, mixed mode, sharing)

プログラムは、こういうものを甚意したした。

SimpleHttpd.java

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class SimpleHttpd {
    public static void main(String... args) throws IOException {
        ExecutorService es = Executors.newFixedThreadPool(200);

        HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
        server.setExecutor(es);
        server.createContext("/", new SimpleHttpHandler());
        server.start();

        System.out.println(LocalDateTime.now() + " server startup.");
    }

    static class SimpleHttpHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            try {
                TimeUnit.SECONDS.sleep(60);
            } catch (InterruptedException e) {
                // ignore
            }

            byte[] message = "Hello World!!".getBytes(StandardCharsets.UTF_8);

            exchange.sendResponseHeaders(200, message.length);
            try (OutputStream os = exchange.getResponseBody()) {
                os.write(message);
            }
        }
    }
}

起動は、こんな感じで。

$ java SimpleHttpd.java 
2021-02-07T14:21:33.252448 server startup.

「Hello World!!」ず返すだけの簡単なサヌバヌですが、接続数は200、1リク゚ストごずに1分のスリヌプを行いたす。

このサヌバヌに察しお、mod_proxy_httpでプロキシしたしょう。

mod_proxy_httpを有効にしお

$ sudo a2enmod proxy_http

Apacheをプロキシするように蚭定。

$ grep -vE '^\s*#' /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html


    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined


    ProxyPass / http://localhost:8080
    ProxyPassReverse / http://localhost:8080
</VirtualHost>

確認。

$ time curl -i localhost
HTTP/1.1 200 OK
Date: Sun, 07 Feb 2021 05:30:04 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-length: 13

Hello World!!
real    1m0.584s
user    0m0.013s
sys 0m0.025s

OKです。

アクセス数を出すためのツヌルずしおは、Vegetaを䜿いたした。

GitHub - tsenart/vegeta: HTTP load testing tool and library. It's over 9000!

むンストヌル。

$ curl -sLO https://github.com/tsenart/vegeta/releases/download/v12.8.4/vegeta_12.8.4_linux_amd64.tar.gz
$ tar xf vegeta_12.8.4_linux_amd64.tar.gz

今回の環境での、バックログの䞊限も確認しおおきたす。

$ sysctl net.core.somaxconn
net.core.somaxconn = 4096

Apacheの蚭定ずしおはListenBackLogを䜿うようで、デフォルトで511のようです今回は未蚭定。

ListenBackLog Directive

worker MPM

たずは、worker MPMから確認したしょう。

event MPMからworker MPMぞ切り替え、Apacheを再起動したす。

$ sudo a2dismod mpm_event
$ sudo a2enmod mpm_worker
$ sudo systemctl restart apache2

worker MPMに切り替わったこずを確認Server MPM。

$ apachectl -V
Server version: Apache/2.4.41 (Ubuntu)
Server built:   2020-08-12T19:46:17
Server's Module Magic Number: 20120211:88
Server loaded:  APR 1.6.5, APR-UTIL 1.6.1
Compiled using: APR 1.6.5, APR-UTIL 1.6.1
Architecture:   64-bit
Server MPM:     worker
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/etc/apache2"
 -D SUEXEC_BIN="/usr/lib/apache2/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache2.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="mime.types"
 -D SERVER_CONFIG_FILE="apache2.conf"

worker MPMの今回の蚭定はこちらです再掲。

<IfModule mpm_worker_module>
    StartServers             2
    MinSpareThreads      25
    MaxSpareThreads      75
    ThreadLimit          64
    ThreadsPerChild      25
    MaxRequestWorkers     150
    MaxConnectionsPerChild   0
</IfModule>

起動した時点でのプロセス数は、こうなっおいたす。StartServersが2なので、子プロセスが2぀ある状態ですね。

$ ps aux | grep apache2 | grep -v grep
root         745  0.0  0.2   6752  4740 ?        Ss   20:14   0:00 /usr/sbin/apache2 -k start
www-data     746  0.0  0.2 1211648 4480 ?        Sl   20:14   0:00 /usr/sbin/apache2 -k start
www-data     747  0.0  0.2 1211648 4480 ?        Sl   20:14   0:00 /usr/sbin/apache2 -k start

スレッド数を芋おみたしょう。次のものは、PID単䜍でLWPをグルヌピング、カりントしたものです。なので、プロセス自身の数も
含たれたす。

$ ps aux -L | grep apache2 | grep -v grep | perl -awln -F'\s+' -e 'print "$F[0] $F[1]"' | sort | uniq -c
      1 root 1778
     27 www-data 1779
     27 www-data 1780

ですが、プロセス数の分を差し匕いおも26ありたす。ThreadsPerChildもMinSpareThreadsも25なのですが、
ひず぀倚いですね 。

たあ、この内蚳には今回はこだわらず進みたしょう。

Vegetaでワヌカヌ数を300今回のMaxRequestWorkersの倍にしお、埅ち時間でタむムアりトしないように蚭定し぀぀アクセス。

$ echo 'GET http://localhost' | ./vegeta attack -duration 600s -max-workers 300 -timeout 120s

Vegetaでアクセスしおいる間の、Apacheの状態を芋おみたす。

子プロセスの数が6になりたした。MaxRequestWorkers150 / ThreadsPerChild25は6になるので、蚭定ず合った結果に
なっおいたすね。

$ ps aux | grep apache2 | grep -v grep
root         745  0.0  0.2   6752  4740 ?        Ss   20:14   0:00 /usr/sbin/apache2 -k start
www-data     746  0.0  0.2 1213632 4480 ?        Sl   20:14   0:00 /usr/sbin/apache2 -k start
www-data     747  0.0  0.2 1213632 4480 ?        Sl   20:14   0:00 /usr/sbin/apache2 -k start
www-data    1646  0.2  0.2 1213632 4540 ?        Sl   20:27   0:00 /usr/sbin/apache2 -k start
www-data    1701  0.2  0.2 1213632 4540 ?        Sl   20:27   0:00 /usr/sbin/apache2 -k start
www-data    1702  0.2  0.2 1213632 4604 ?        Sl   20:27   0:00 /usr/sbin/apache2 -k start
www-data    1807  0.3  0.2 1213632 4540 ?        Sl   20:27   0:00 /usr/sbin/apache2 -k start

䞀方でスレッド数を芋おみるず、こうなっおいたす。

$ ps aux -L | grep apache2 | grep -v grep | perl -awln -F'\s+' -e 'print "$F[0] $F[1]"' | sort | uniq -c
      1 root 745
     27 www-data 1646
     27 www-data 1701
     27 www-data 1702
     27 www-data 1807
     27 www-data 746
     27 www-data 747

Apacheの゚ラヌログを芋るず、MaxRequestWorkersに達したこずが出力されおいたす。

/var/log/apache2/error.log

[Sun Feb 07 20:27:11.011377 2021] [mpm_worker:error] [pid 745:tid 139631994985536] AH00286: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting

プロセスあたりのスレッド数の1分はちょっずわかっおいたせんが、抂ね説明のずおりですね。

Apacheのバックログも芋おみたしょう。アクセス元の300ワヌカヌのうち、150がRecv-Qに入っおいるのでこちらずも合っおそうです。

$ ss -tnl | grep -E 'State|:80 '
State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port  Process  
LISTEN   150      511                    *:80                  *:*
event MPM

次は、event MPMを確認したしょう。

event MPMに切り替えたす。

$ sudo a2dismod mpm_worker
$ sudo a2enmod mpm_event
$ sudo systemctl restart apache2

確認。

$ apachectl -V
Server version: Apache/2.4.41 (Ubuntu)
Server built:   2020-08-12T19:46:17
Server's Module Magic Number: 20120211:88
Server loaded:  APR 1.6.5, APR-UTIL 1.6.1
Compiled using: APR 1.6.5, APR-UTIL 1.6.1
Architecture:   64-bit
Server MPM:     event
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/etc/apache2"
 -D SUEXEC_BIN="/usr/lib/apache2/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache2.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="mime.types"
 -D SERVER_CONFIG_FILE="apache2.conf"

event MPMの蚭定は、こちらです。

<IfModule mpm_event_module>
    StartServers             2
    MinSpareThreads      25
    MaxSpareThreads      75
    ThreadLimit          64
    ThreadsPerChild      25
    MaxRequestWorkers     150
    MaxConnectionsPerChild   0
</IfModule>

プロセスを確認。worker MPMの時ず同じですね。

$ ps aux | grep apache2 | grep -v grep
root        2350  0.0  0.2   6772  4712 ?        Ss   21:02   0:00 /usr/sbin/apache2 -k start
www-data    2352  0.0  0.2 1211668 4436 ?        Sl   21:02   0:00 /usr/sbin/apache2 -k start
www-data    2353  0.0  0.2 1211668 4468 ?        Sl   21:02   0:00 /usr/sbin/apache2 -k start

プロセスごずのスレッド数に関しおも同じです。

$ ps aux -L | grep apache2 | grep -v grep | perl -awln -F'\s+' -e 'print "$F[0] $F[1]"' | sort | uniq -c
      1 root 2350
     27 www-data 2352
     27 www-data 2353

では、負荷をかけおみたす。

$ echo 'GET http://localhost' | ./vegeta attack -duration 600s -max-workers 300 -timeout 120s

この状態でプロセス数を芋るず、worker MPMの時よりも倚い9になっおいたすworker MPMは6。

$ ps aux | grep apache2 | grep -v grep
root        2350  0.0  0.2   6772  4840 ?        Ss   21:02   0:00 /usr/sbin/apache2 -k start
www-data    2352  0.0  0.2 1213588 4436 ?        Sl   21:02   0:00 /usr/sbin/apache2 -k start
www-data    2353  0.0  0.2 1213660 4468 ?        Sl   21:02   0:00 /usr/sbin/apache2 -k start
www-data    2481  0.0  0.2 1213660 4472 ?        Sl   21:04   0:00 /usr/sbin/apache2 -k start
www-data    2534  0.0  0.2 1213340 4472 ?        Sl   21:04   0:00 /usr/sbin/apache2 -k start
www-data    2535  0.0  0.2 1211900 4472 ?        Sl   21:04   0:00 /usr/sbin/apache2 -k start
www-data    2614  0.0  0.2 1213660 4472 ?        Sl   21:04   0:00 /usr/sbin/apache2 -k start
www-data    2615  0.0  0.2 1213660 4472 ?        Sl   21:04   0:00 /usr/sbin/apache2 -k start
www-data    2616  0.0  0.2 1213020 4472 ?        Sl   21:04   0:00 /usr/sbin/apache2 -k start
www-data    2617  0.2  0.2 1213660 4472 ?        Sl   21:04   0:00 /usr/sbin/apache2 -k start

スレッド数。この蚈算だず、225スレッドあるこずになりたすね。

$ ps aux -L | grep apache2 | grep -v grep | perl -awln -F'\s+' -e 'print "$F[0] $F[1]"' | sort | uniq -c
      1 root 2350
     27 www-data 2352
     27 www-data 2353
     27 www-data 2481
     27 www-data 2534
     27 www-data 2535
     27 www-data 2614
     27 www-data 2615
     27 www-data 2616
     27 www-data 2617

゚ラヌログを芋るず、MaxRequestWorkersに達したこずが出力されおいたす。

/var/log/apache2/error.log

[Sun Feb 07 21:04:43.278710 2021] [mpm_event:error] [pid 2350:tid 139858399816768] AH00484: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting

バックログを芋るず110なので、150だったworker MPMよりも40枛っおいたすね。

$ ss -tnl | grep -E 'State|:80 '
State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port  Process  
LISTEN   110      511                    *:80                  *:*

぀たり、worker MPMの蚭定ず同じなのに40個の接続を受け入れおいるこずになりたすね。

さお、いろいろ蚈算がわからなくなりたした。mod_statusで芋るず、225のスレッドがビゞヌなワヌカヌスレッドず認識されおいる
ようだったのですが、この225がどう蚈算したら出おくるのかがよくわかりたせん 。バックログずMaxRequestWorkersの差である
40もそうなのですが 。

AsyncRequestWorkerFactor Directive

worker MPMより倚めになるのはドキュメントからもわかるのですが この確認は、今回はパスしたしょう。

prefork MPM

最埌はprefork MPMです。

prefork MPMに切り替えたす。

$ sudo a2dismod mpm_event
$ sudo a2enmod mpm_prefork
$ sudo systemctl restart apache2

確認。

$ apachectl -V
Server version: Apache/2.4.41 (Ubuntu)
Server built:   2020-08-12T19:46:17
Server's Module Magic Number: 20120211:88
Server loaded:  APR 1.6.5, APR-UTIL 1.6.1
Compiled using: APR 1.6.5, APR-UTIL 1.6.1
Architecture:   64-bit
Server MPM:     prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/etc/apache2"
 -D SUEXEC_BIN="/usr/lib/apache2/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache2.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="mime.types"
 -D SERVER_CONFIG_FILE="apache2.conf"

prefork MPMの蚭定は、こうですね。

<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers       5
    MaxSpareServers      10
    MaxRequestWorkers     150
    MaxConnectionsPerChild   0
</IfModule>

StartServersが5なので、起動時のプロセス数も5です、ず。

$ ps aux | grep apache2 | grep -v grep
root        4674  0.0  0.2   6500  4452 ?        Ss   21:33   0:00 /usr/sbin/apache2 -k start
www-data    4675  0.0  0.1   6772  3824 ?        S    21:33   0:00 /usr/sbin/apache2 -k start
www-data    4676  0.0  0.1   6772  3824 ?        S    21:33   0:00 /usr/sbin/apache2 -k start
www-data    4677  0.0  0.1   6772  3824 ?        S    21:33   0:00 /usr/sbin/apache2 -k start
www-data    4678  0.0  0.1   6772  3824 ?        S    21:33   0:00 /usr/sbin/apache2 -k start
www-data    4679  0.0  0.1   6772  3824 ?        S    21:33   0:00 /usr/sbin/apache2 -k start

スレッドに関しおは、確認する意味がありたせん。

$ ps aux -L | grep apache2 | grep -v grep | perl -awln -F'\s+' -e 'print "$F[0] $F[1]"' | sort | uniq -c
      1 root 4674
      1 www-data 4675
      1 www-data 4676
      1 www-data 4677
      1 www-data 4678
      1 www-data 4679

では、負荷をかけおみたす。

$ echo 'GET http://localhost' | ./vegeta attack -duration 600s -max-workers 300 -timeout 120s

子プロセスが150たで増えたした。

$ ps aux | grep apache2 | grep -v grep | wc -l
151

゚ラヌログを確認するず、MaxRequestWorkersに達したこずが出力されおいたす。

/var/log/apache2/error.log

[Sun Feb 07 21:41:02.467235 2021] [mpm_prefork:error] [pid 5049] AH00161: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting

バックログには、150ありたすね。

$ ss -tnl | grep -E 'State|:80 '
State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port  Process  
LISTEN   150      511                    *:80                  *:*

だいたい、雰囲気はわかったのではないでしょうか。

たずめ

よくApacheのMPMの蚭定がわからなくなるので、この機䌚にちょっず確認しおみたした。

event MPMに぀いおはちょっずよくわからないずころがあるのですが、気が向いたらもうちょっず確認しおみようかなず 。

いったん、雰囲気はわかったので良しずしたしょう。