はじめに
FastAPIでOpenAI APIやClaude APIのような、レスポンス待ち(I/O待ち)が長い処理を実装した際、「非同期にしているはずなのに、なぜかリクエストが詰まってしまう」という現象に直面しました。
調査を進めていく中で、プロセス・スレッド・イベントループという概念を理解する必要があることが分かりました。
その際に、Apacheのプロセス・スレッドのアーキテクチャの限界(C10K問題)をNginxが解決したという話を思い出したため、
ApacheからNginxへのアーキテクチャの変遷を紐解いた上で、FastAPIにおける正しい非同期処理の実装についてまとめます。
対象読者
- FastAPIでasync/awaitを書いているのに、処理が詰まって困っている人
- プロセス、スレッド、イベントループの違いを、具体的な実機検証(psコマンドなど)で理解したい人
- ApacheとNginxのアーキテクチャの違い、C10K問題について理解したい人
検証内容
前提・参考
-
以下の検証手順で実施していく
- Dockerコンテナによる環境構築: 各Webサーバー(Apache / Nginx / FastAPI)をコンテナ上で起動する。(※アプリ側の負荷を排除し、サーバーの並行処理能力のみを比較するため、処理は単純なHTML返却とする)
- ベースラインの確認: 負荷をかける前のプロセス数・スレッド数の初期状態を ps コマンドで記録する。
- 負荷試験の実施: Locustを用い、最大300並列(10ユーザー/秒ずつ増加)の負荷を注入する。
- 負荷時の挙動観測: 負荷ピーク時におけるプロセス・スレッドの変化を ps コマンドで再確認し、初期状態と比較する。
-
psコマンドの見方
略称 正式名称 (英語) 意味 PID Process ID プロセスID。実行中のプログラムに割り振られる固有の識別番号です。 PPID Parent Process ID 親プロセスID。そのプロセスを起動した「親」のPIDです。 LWP Light Weight Process スレッドID。Linuxではスレッドのことを「軽量プロセス」と呼ぶため、この名称になっています。 C CPU Utilization CPU使用率(の指標)。プロセスの生存期間中にどれくらいCPUを使ったかを示す整数値です。 NLWP Number of Light Weight Processes スレッドの総数。そのプロセスの中にスレッドがいくつ存在するかを示します。 -
[参考記事]ApacheとNginxの違い
- [参考記事]Apacheの方式の違い
→ Apacheについては複数のMPMがあるようで、preforkとeventで試しました。
- [参考記事]C10K問題について
1. Webサーバーの進化に見る「並行処理」の変遷
まず、Apache(マルチプロセス & マルチスレッド)とNginx(シングルスレッド / イベントループ方式)の挙動を実機で検証しました。
Apache(prefork)(マルチプロセス)
Dokcerfile
```
# 1. 公式のApacheイメージをベースにする
FROM httpd:latest
# 2. 確認用の ps コマンドをインストール
RUN apt-get update && \\
apt-get install -y procps && \\
rm -rf /var/lib/apt/lists/*
# 3. 設定ファイルを書き換えて「Preforkモード」にする
RUN sed -i \\
-e 's/^LoadModule mpm_event_module/#LoadModule mpm_event_module/' \\
-e 's/^#LoadModule mpm_prefork_module/LoadModule mpm_prefork_module/' \\
conf/httpd.conf
EXPOSE 80
```
初期状態のプロセス・スレッド状況(psコマンド)
```
$ docker exec demo-prefork ps -efL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 06:51 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 8 0 1 06:51 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 9 0 1 06:51 ? 00:00:00 httpd -DFOREGROUND
www-data 10 1 10 0 1 06:51 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 11 0 1 06:51 ? 00:00:00 httpd -DFOREGROUND
www-data 12 1 12 0 1 06:51 ? 00:00:00 httpd -DFOREGROUND
root 13 0 13 0 1 06:51 ? 00:00:00 ps -efL
```
300並列負荷時のプロセス・スレッド状況(psコマンド)
```
$ docker exec demo-prefork ps -efL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 7 1 7 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 8 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 9 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 10 1 10 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 11 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 18 1 18 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 19 1 19 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 20 1 20 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 21 1 21 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 22 1 22 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 23 1 23 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 24 1 24 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 25 1 25 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 26 1 26 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 27 1 27 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 28 1 28 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 29 1 29 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 30 1 30 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 31 1 31 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 32 1 32 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 33 1 33 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 34 1 34 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 35 1 35 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 36 1 36 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 37 1 37 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 38 1 38 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 39 1 39 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 40 1 40 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 41 1 41 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 42 1 42 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 43 1 43 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 44 1 44 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 45 1 45 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 46 1 46 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 47 1 47 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 48 1 48 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 49 1 49 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 50 1 50 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 51 1 51 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 52 1 52 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 53 1 53 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 54 1 54 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 55 1 55 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 56 1 56 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 57 1 57 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 58 1 58 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 59 1 59 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 60 1 60 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 61 1 61 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 62 1 62 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 63 1 63 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 64 1 64 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 65 1 65 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 66 1 66 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 67 1 67 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 68 1 68 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 69 1 69 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 70 1 70 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 71 1 71 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 72 1 72 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 73 1 73 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 74 1 74 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 75 1 75 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 76 1 76 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 77 1 77 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 78 1 78 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 79 1 79 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 80 1 80 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 81 1 81 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 82 1 82 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 83 1 83 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 84 1 84 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 85 1 85 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 86 1 86 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 87 1 87 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 88 1 88 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 89 1 89 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 90 1 90 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 91 1 91 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 92 1 92 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 93 1 93 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 95 1 95 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 96 1 96 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 97 1 97 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 98 1 98 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 99 1 99 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 100 1 100 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 101 1 101 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 102 1 102 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 103 1 103 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 104 1 104 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 105 1 105 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 106 1 106 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 107 1 107 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 108 1 108 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 109 1 109 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 110 1 110 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 111 1 111 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 112 1 112 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 113 1 113 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 114 1 114 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 115 1 115 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 116 1 116 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 117 1 117 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 118 1 118 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 119 1 119 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 120 1 120 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 121 1 121 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 122 1 122 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 123 1 123 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 124 1 124 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 125 1 125 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 126 1 126 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 127 1 127 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 128 1 128 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 129 1 129 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 130 1 130 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 131 1 131 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 132 1 132 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 133 1 133 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 134 1 134 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 135 1 135 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 136 1 136 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 137 1 137 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 138 1 138 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 139 1 139 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 140 1 140 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 141 1 141 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 142 1 142 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 143 1 143 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 144 1 144 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 145 1 145 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 146 1 146 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 147 1 147 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 148 1 148 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 149 1 149 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 150 1 150 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 151 1 151 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 152 1 152 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 153 1 153 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 154 1 154 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 155 1 155 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 156 1 156 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 157 1 157 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 158 1 158 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 159 1 159 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 160 1 160 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 161 1 161 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 162 1 162 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 163 1 163 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 164 1 164 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 165 1 165 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 166 1 166 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 167 1 167 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 168 1 168 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 169 1 169 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 170 1 170 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 171 1 171 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 172 1 172 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 173 1 173 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 174 1 174 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 175 1 175 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 182 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 183 1 183 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 184 1 184 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 185 1 185 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 186 1 186 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 188 1 188 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 189 1 189 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 190 1 190 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 191 1 191 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 192 1 192 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 193 1 193 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 194 1 194 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 195 1 195 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 196 1 196 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 197 1 197 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 198 1 198 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 199 1 199 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 200 1 200 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 201 1 201 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 203 1 203 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 204 1 204 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 205 1 205 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 206 1 206 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 207 1 207 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 208 1 208 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 209 1 209 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 210 1 210 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 211 1 211 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 212 1 212 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 213 1 213 0 1 07:02 ? 00:00:00 httpd -DFOREGROUND
www-data 238 1 238 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 245 1 245 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 246 1 246 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 259 1 259 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 260 1 260 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 261 1 261 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 262 1 262 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 275 1 275 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 276 1 276 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 277 1 277 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 278 1 278 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 279 1 279 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 280 1 280 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 281 1 281 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 282 1 282 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 295 1 295 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 296 1 296 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 297 1 297 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 298 1 298 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 299 1 299 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 300 1 300 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 301 1 301 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 302 1 302 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 303 1 303 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 304 1 304 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 305 1 305 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 306 1 306 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 307 1 307 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 308 1 308 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 309 1 309 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 310 1 310 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 322 1 322 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 323 1 323 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 324 1 324 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 325 1 325 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 326 1 326 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 327 1 327 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 328 1 328 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 329 1 329 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 330 1 330 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 331 1 331 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 332 1 332 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 333 1 333 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 334 1 334 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 335 1 335 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 336 1 336 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 337 1 337 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 338 1 338 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 339 1 339 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 340 1 340 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 341 1 341 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 342 1 342 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 343 1 343 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 344 1 344 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 345 1 345 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 346 1 346 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 347 1 347 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 348 1 348 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 349 1 349 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 350 1 350 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 351 1 351 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 352 1 352 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 353 1 353 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
www-data 377 1 377 0 1 07:03 ? 00:00:00 httpd -DFOREGROUND
root 532 0 532 20 1 07:03 ? 00:00:00 ps -efL
```
Apache(event)(マルチスレッド)
Dokcerfile
```
# 1. 公式のApacheイメージをベースにする
FROM httpd:latest
# 2. 確認用の ps コマンドをインストール
RUN apt-get update && \\
apt-get install -y procps && \\
rm -rf /var/lib/apt/lists/*
# 3. デフォルトの「Eventモード」とするため、モード変更は実施しない
EXPOSE 80
```
初期状態のプロセス・スレッド状況(psコマンド)
```
$ docker exec demo-multi-apache ps -efL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 8 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 12 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 13 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 14 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 15 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 16 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 17 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 18 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 19 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 20 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 21 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 23 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 24 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 25 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 27 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 28 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 30 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 32 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 34 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 36 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 38 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 39 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 41 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 43 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 45 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 47 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 49 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 9 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 29 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 31 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 33 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 35 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 37 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 40 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 42 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 44 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 46 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 48 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 50 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 51 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 52 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 53 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 54 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 55 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 56 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 57 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 58 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 59 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 60 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 61 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 79 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 80 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 81 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 82 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 11 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 62 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 63 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 64 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 65 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 66 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 67 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 68 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 69 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 70 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 71 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 72 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 73 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 74 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 75 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 76 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 77 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 78 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 83 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 84 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 85 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 86 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 87 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 88 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 89 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 90 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 91 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
root 92 0 92 16 1 06:58 ? 00:00:00 ps -efL
```
300並列負荷時のプロセス・スレッド状況(psコマンド)
```
$ docker exec demo-multi-apache ps -efL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 8 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 12 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 13 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 14 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 15 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 16 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 17 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 18 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 19 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 20 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 21 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 23 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 24 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 25 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 27 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 28 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 30 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 32 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 34 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 36 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 38 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 39 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 41 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 43 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 45 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 47 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 8 1 49 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 9 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 29 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 31 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 33 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 35 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 37 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 40 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 42 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 44 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 46 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 48 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 50 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 51 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 52 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 53 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 54 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 55 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 56 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 57 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 58 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 59 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 60 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 61 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 79 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 80 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 81 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 9 1 82 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 11 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 62 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 63 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 64 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 65 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 66 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 67 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 68 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 69 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 70 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 71 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 72 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 73 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 74 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 75 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 76 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 77 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 78 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 83 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 84 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 85 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 86 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 87 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 88 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 89 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 90 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 11 1 91 0 27 06:58 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 182 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 184 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 185 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 186 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 187 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 188 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 189 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 190 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 191 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 192 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 193 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 194 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 195 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 196 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 197 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 198 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 199 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 200 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 201 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 202 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 203 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 204 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 205 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 206 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 207 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 208 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 182 1 209 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 222 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 224 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 225 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 226 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 227 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 228 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 229 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 230 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 231 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 232 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 233 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 234 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 235 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 236 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 237 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 238 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 239 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 240 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 241 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 242 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 243 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 244 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 245 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 246 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 247 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 248 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 222 1 249 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 263 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 266 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 268 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 269 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 270 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 274 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 276 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 283 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 284 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 285 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 286 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 287 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 288 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 289 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 290 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 291 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 292 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 294 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 296 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 298 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 299 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 300 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 302 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 303 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 305 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 306 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 263 1 308 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 264 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 271 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 272 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 273 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 275 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 277 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 278 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 279 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 280 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 281 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 282 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 293 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 295 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 297 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 301 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 304 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 307 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 309 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 310 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 311 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 312 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 313 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 314 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 315 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 316 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 317 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
www-data 264 1 318 0 27 07:00 ? 00:00:00 httpd -DFOREGROUND
root 498 0 498 0 1 07:00 ? 00:00:00 ps -efL
```
- パフォーマンス
- 結果
負荷に応じてPID(プロセスID)とそれに紐づく27スレッドが発行される=リクエストのたびにプロセスを作るのではなく、捌ききれなくなったタイミングでスレッドの束(1プロセス単位)をまとめて追加することが分かりました。また、スレッドが一気に増える分、パフォーマンスもpreforkよりも改善されました。
Nginx(シングルスレッド / イベントループ方式)
Dokcerfile
```
# 1. 公式のNginxイメージをベースにする
FROM nginx:latest
# 2. 確認用の ps コマンドをインストール
RUN apt-get update && \\
apt-get install -y procps && \\
rm -rf /var/lib/apt/lists/*
EXPOSE 80
```
初期状態のプロセス・スレッド状況(psコマンド)
```
$ docker exec demo-nginx ps -efL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 07:08 ? 00:00:00 nginx: master process nginx -g daemon off;
nginx 29 1 29 0 1 07:08 ? 00:00:00 nginx: worker process
nginx 30 1 30 0 1 07:08 ? 00:00:00 nginx: worker process
root 31 0 31 20 1 07:08 ? 00:00:00 ps -efL
```
300並列負荷時のプロセス・スレッド状況(psコマンド)
```
$ docker exec demo-nginx ps -efL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 07:08 ? 00:00:00 nginx: master process nginx -g daemon off;
nginx 29 1 29 0 1 07:08 ? 00:00:00 nginx: worker process
nginx 30 1 30 0 1 07:08 ? 00:00:00 nginx: worker process
root 218 0 218 16 1 07:10 ? 00:00:00 ps -efL
```
- パフォーマンス
- 結果
300多重の状態でも、起動時の2プロセスから増えることはなかった=今回の単純なHTML返却の処理では、少数の固定プロセスで捌き切れることが分かりました。パフォーマンスについても、Apacheのマルチスレッドとほぼ同等のパフォーマンスとなりました。
ApacheとNginxのまとめ
| 比較項目 | Apache (prefork) 【マルチプロセス】 |
Apache (event) 【マルチスレッド】 |
Nginx 【シングルスレッド / イベントループ】 |
|---|---|---|---|
| プロセス・スレッドの動き |
リクエストごとにプロセスが増加。 1つのプロセスが1つの接続を専有する(プロセス=メインスレッド)。 |
プロセスごとに複数のスレッドを保持。 初期状態で3プロセス(各27スレッド、計81スレッド)が起動。不足するとプロセス単位で増える。 |
少数の固定プロセスで動作。 1プロセス1スレッドで動作し、今回の300多重負荷でもプロセス・スレッド数に変化なし。 |
| 今回の検証結果 | 負荷に応じてPID(プロセスID)が次々と発行された。 | 負荷に応じてNLWP(スレッド数)がプロセス内で管理された。 | 300多重の状態でも、起動時の2プロセスから増えることはなかった。 |
2. FastAPI(シングルスレッド)で同期処理、非同期処理の動きを試す
ApacheとNginxの比較を通じて、少数の固定リソースで効率的にリクエストを捌く「イベントループ方式(Nginx)」の優位性が確認できました。FastAPI(Uvicorn)も、このNginxと同様のアーキテクチャを採用しています。
しかし、イベントループ方式には「1つの処理がスレッドを占有(ブロッキング)してしまうと、後続のすべての処理が止まる」という弱点があります。
ここでは、FastAPIにおいて「同期処理(time.sleep)」と「非同期処理(await asyncio.sleep)」を実行した際、イベントループの並行処理能力にどのような差が出るかを、実機ログとあわせて検証します。
fastapi(同期処理)
コード
```
app = FastAPI()
@app.get("/")
async def read_root():
print("リクエストを受け付けました。3秒待機します...")
time.sleep(3)
print("3秒待機が完了しました。レスポンスを返します。")
return {"message": "hello"}
```
Dokcerfile
```
FROM python:3.11-slim
WORKDIR /app
RUN apt-get update && \\
apt-get install -y procps && \\
rm -rf /var/lib/apt/lists/*
# 最小限のライブラリをインストール
RUN pip install --no-cache-dir fastapi uvicorn
# ソースコードをコピー
COPY main.py .
# ワーカー数を「1」にして起動
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80", "--workers", "1"]
```
初期状態のプロセス・スレッド状況(psコマンド)
```
$ docker exec demo-fastapi ps -efL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 7 1 01:25 ? 00:00:00 /usr/local/bin/python3.11 /usr/local/bin/uvicorn main:app --host 0.0.0.0 --port 80 --workers 1
root 7 0 7 0 1 01:25 ? 00:00:00 ps -efL
```
10並列負荷時のプロセス・スレッド状況(psコマンド)
```
$ docker exec demo-fastapi ps -efL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 01:25 ? 00:00:00 /usr/local/bin/python3.11 /usr/local/bin/uvicorn main:app --host 0.0.0.0 --port 80 --workers 1
root 18 0 18 0 1 01:29 ? 00:00:00 ps -efL
```
- パフォーマンス(10多重10users/second)
ログ
```
$ docker logs -f demo-fastapi
INFO: Started server process [1]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on <http://0.0.0.0:80> (Press CTRL+C to quit)
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:60970 - "GET / HTTP/1.1" 200 OK
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:60980 - "GET / HTTP/1.1" 200 OK
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:60988 - "GET / HTTP/1.1" 200 OK
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:60990 - "GET / HTTP/1.1" 200 OK
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:60994 - "GET / HTTP/1.1" 200 OK
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:32776 - "GET / HTTP/1.1" 200 OK
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:32784 - "GET / HTTP/1.1" 200 OK
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:32796 - "GET / HTTP/1.1" 200 OK
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:32808 - "GET / HTTP/1.1" 200 OK
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:32810 - "GET / HTTP/1.1" 200 OK
...
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:32810 - "GET / HTTP/1.1" 200 OK
```
- 結果
ログが「3秒に1回」しか出力されていない=1人が待っている間、サーバー全体がフリーズしている状態ということが分かりました。
fastapi(非同期処理)
コード
```
@app.get("/")
async def read_root():
print("リクエストを受け付けました。3秒待機します...")
await asyncio.sleep(3)
print("3秒待機が完了しました。レスポンスを返します。")
return {"message": "hello"}
```
Dokcerfile
```
FROM python:3.11-slim
WORKDIR /app
RUN apt-get update && \\
apt-get install -y procps && \\
rm -rf /var/lib/apt/lists/*
# 最小限のライブラリをインストール
RUN pip install --no-cache-dir fastapi uvicorn
# ソースコードをコピー
COPY main.py .
# ワーカー数を「1」にして起動
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80", "--workers", "1"]
```
初期状態のプロセス・スレッド状況(psコマンド)
```
$ docker exec demo-fastapi ps -efL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 5 1 01:29 ? 00:00:00 /usr/local/bin/python3.11 /usr/local/bin/uvicorn main:app --host 0.0.0.0 --port 80 --workers 1
root 7 0 7 0 1 01:29 ? 00:00:00 ps -efL
```
10並列負荷時のプロセス・スレッド状況(psコマンド)
```
$ docker exec demo-fastapi ps -efL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 01:29 ? 00:00:00 /usr/local/bin/python3.11 /usr/local/bin/uvicorn main:app --host 0.0.0.0 --port 80 --workers 1
root 19 0 19 0 1 01:31 ? 00:00:00 ps -efL
```
- パフォーマンス(10多重10users/second)
ログ
```
$ docker logs -f demo-fastapi
INFO: Started server process [1]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on <http://0.0.0.0:80> (Press CTRL+C to quit)
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49646 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49658 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49672 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49680 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49688 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49702 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49704 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49718 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49720 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49724 - "GET / HTTP/1.1" 200 OK
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
リクエストを受け付けました。3秒待機します...
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49658 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49720 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49672 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49646 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49704 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49702 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49688 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49680 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49724 - "GET / HTTP/1.1" 200 OK
3秒待機が完了しました。レスポンスを返します。
INFO: 172.17.0.1:49718 - "GET / HTTP/1.1" 200 OK
...
```
- 結果
ログに「リクエスト受付」が一気に表示される=3秒待っている間に、次のリクエストをどんどん受け付けられている状態ということが分かりました。
まとめ:並行処理モデルの比較
今回の結果を元に、マルチプロセス、マルチスレッド、非同期 (イベントループ)の違いをAIにまとめてもらいました。また、FastAPIでは実装時にasync/awaitの記載が必須でしたが、Goroutine等ではその辺の実装も改善されているらしく、それらの軽量スレッドについても表に追加してもらいました。
| 特徴 | マルチプロセス (Fork) | マルチスレッド | 非同期 (イベントループ) | 軽量スレッド (現代) |
|---|---|---|---|---|
| 基本単位 | プロセス (Process) | スレッド (Thread) | イベント / タスク | 仮想スレッド / Goroutine |
| コードの書き味 |
直感的 普通の逐次処理 |
直感的 ただし排他制御が必要 |
技巧的 async/awaitが必須 |
理想的 同期の書き味+非同期の性能 |
| 特長 |
最強の隔離性 1つのクラッシュが他に影響せず、メモリも完全独立。 |
高速なデータ共有 メモリ空間を共有し、大量データのコピーが不要。 |
圧倒的な並行数 1スレッドで数万の接続を管理。メモリ消費が最小。 |
開発効率と性能の融合 可読性を保ったまま限界性能を引き出す。 |
| リソース消費 |
非常に大きい OSがプロセスごとに大量のメモリを確保。 |
中程度 スレッドごとにスタック(約1MB)を確保。 |
極めて小さい 接続情報のみ保存。オーバーヘッドがほぼ無い。 |
極めて小さい スタックを動的に変えるため数KBから動作。 |
| CPUの動き | 切替時にOSの重い介入(コンテキストスイッチ)が入る。 | OSが切り替えるが、プロセスよりは軽快。 | 1人が「待ち」の間に次々仕事。CPUの空きを無くす。 | ランタイムが裏で効率的に「待ち」をスキップする。 |
| 主な課題 | 大量のリクエストでメモリ不足に陥りやすい。 |
競合状態 (Race) 変数の書き換え順序でバグが出やすい。 |
CPUヘビーな処理 1人が重い計算を始めると全員の足が止まる。 |
デバッグ時に裏側のスケジューリングが見えにくい。 |
| 代表的な採用例 | PHP (Apache/FPM), PostgreSQL | Java (Platform Thread), C++, Ruby (Parallel) | Node.js (JavaScript), Python (asyncio), Nginx | Go (Goroutine), Java 21+ (Virtual Threads), Elixir (Process) |
結論
ApacheとNginxの並行処理モデルを比較したことで、Webサーバーが大量のリクエストを効率的に捌くために、どのような歴史を辿り、アーキテクチャが変遷してきたのかを深く理解することができました。
この学習を通じて、FastAPIの非同期処理のポテンシャルを引き出すには、実装側でイベントループを意識した適切な制御を行うことが不可欠であると痛感しました。
今後はライブラリの表面的な使い方だけでなく、OSのプロセスやスレッドといった低レイヤーの挙動も意識した、一歩踏み込んだ実装を心がけていきたいと思います。
補足
WSGIとASGI
FastAPIでは非同期のみ取り上げましたが、PythonにもWebサーバーとWebアプリケーション(プログラム)を繋ぐためのインターフェース(NginxやUvicornといったサーバーの違いを意識せずにプログラムを書くためのもの)として、同期と非同期のどちらの処理方法もあるようで、フレームワークによって採用している規格が異なるようでした。
| 特徴 | WSGI (Web Server Gateway Interface) | ASGI (Asynchronous Server Gateway Interface) |
|---|---|---|
| 設計思想 | 同期・ブロッキング | 非同期・ノンブロッキング |
| 対応モデル | Apache (prefork/worker) に近い | Nginx (イベントループ) に近い |
| 並行処理 | 1リクエスト = 1プロセス/スレッド | 1スレッドで大量のリクエストを多重化 |
| 得意分野 | 伝統的なCRUD操作、安定性重視 | API呼び出し、WebSocket、チャット |
| 代表的なFW | Django, Flask | FastAPI, Starlette, Sanic |




