私は比較的トラフィックの少ないサイトを運営しており、サイトの更新後、週に1回訪問者が急増しています。この急増の間、サイトのパフォーマンスは他の週と比較して非常に低くなります。サーバーの実際の負荷は非常に低く、確実に10%CPUおよび30%未満RAM(ハードウェアは実際に行っていることに対して完全に過剰である必要があります)ですが、何らかの理由でApacheリクエストの量に対応できないようです。RHEL5.7、カーネル2.6.18-274.7.1.el5、x86_64でApache2.2.3を実行しています。
Abを使用して営業時間外にこの動作を再現しようとすると、約256ユーザーを超えると、パフォーマンスが大幅に低下することがわかりました。私が思いついた最小のユースケース(静的テキストファイルが取得され、合計223バイト)でテストを実行すると、245の同時リクエストで一貫して正常なパフォーマンスになります。
Connection Times (ms)
min mean[+/-sd] median max
Connect: 15 25 5.8 24 37
Processing: 15 65 22.9 76 96
Waiting: 15 64 23.0 76 96
Total: 30 90 27.4 100 125
Percentage of the requests served within a certain time (ms)
50% 100
66% 108
75% 111
80% 113
90% 118
95% 120
98% 122
99% 123
100% 125 (longest request)
しかし、最大265の同時リクエストをラチェットするとすぐに、それらのサブセットが完了するのに途方もない時間がかかり始めます。
Connection Times (ms)
min mean[+/-sd] median max
Connect: 13 195 692.6 26 3028
Processing: 15 65 21.3 72 100
Waiting: 15 65 21.3 71 99
Total: 32 260 681.7 101 3058
Percentage of the requests served within a certain time (ms)
50% 101
66% 108
75% 112
80% 116
90% 121
95% 3028
98% 3040
99% 3044
100% 3058 (longest request)
これらの結果は、複数の実行にわたって非常に一貫しています。そのボックスに向かう他のトラフィックがあるので、ハードカットオフがどこにあるかは正確にはわかりませんが、疑わしいことに256に近いようです。
当然、これはプリフォークのスレッド制限が原因であると想定したため、使用可能なスレッドの数を2倍にし、スレッドのプールが不必要に拡大および縮小しないように構成を調整しました。
<IfModule prefork.c>
StartServers 512
MinSpareServers 512
MaxSpareServers 512
ServerLimit 512
MaxClients 512
MaxRequestsPerChild 5000
</IfModule>
mod_statusは、512の利用可能なスレッドで実行していることを確認します
8 requests currently being processed, 504 idle workers
ただし、265の同時リクエストを試行しても、以前とほぼ同じ結果が得られます。
Connection Times (ms)
min mean[+/-sd] median max
Connect: 25 211 714.7 31 3034
Processing: 17 94 28.6 103 138
Waiting: 17 93 28.5 103 138
Total: 57 306 700.8 138 3071
Percentage of the requests served within a certain time (ms)
50% 138
66% 145
75% 150
80% 161
90% 167
95% 3066
98% 3068
99% 3068
100% 3071 (longest request)
ドキュメント(およびStack Exchange)を精査した後、このボトルネックに対処するための構成設定をさらに行うことができません。足りないものはありますか?私はapacheの外で答えを探し始めるべきですか?他の誰かがこの行動を見たことがありますか?どんな助けでも大歓迎です。
編集:
Ladadadadaのアドバイスに従って、Apacheに対してstraceを実行しました。 -ttと-Tを数回試しましたが、異常なことは何も見つかりませんでした。次に、現在実行中のすべてのApacheプロセスに対してstrace -cを実行してみたところ、次のようになりました。
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
22.09 0.317836 5 62128 4833 open
19.91 0.286388 4 65374 1896 lstat
13.06 0.187854 0 407433 pread
10.70 0.153862 6 27076 semop
7.88 0.113343 3 38598 poll
6.86 0.098694 1 100954 14380 read
(... abdridged)
私がこの権利を読んでいる場合(そして私はstraceをあまり使用しないので我慢してください)、これらの要求にかかる時間を説明できるシステムコールはありません。リクエストがワーカースレッドに到達する前に、ボトルネックが発生しているように見えます。
編集2:
何人かの人々が示唆したように、私はWebサーバー自体でテストを再度実行しました(以前は、テストは中立的なインターネットの場所から実行されていました)。結果は驚くべきものでした:
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 11 6.6 12 21
Processing: 5 247 971.0 10 4204
Waiting: 3 245 971.3 7 4204
Total: 16 259 973.3 21 4225
Percentage of the requests served within a certain time (ms)
50% 21
66% 23
75% 24
80% 24
90% 26
95% 4225
98% 4225
99% 4225
100% 4225 (longest request)
収益の時間はインターネットベースのテストに似ていますが、ローカルで実行すると一貫して少し悪いのように見えます。さらに興味深いことに、プロファイルは劇的に変化しました。長時間実行されるリクエストの時間の大部分が「接続」に費やされる前は、ボトルネックは処理中または待機中のように見えます。これは、以前はネットワークの制限によって隠されていた別の問題である可能性があるのではないかと疑っています。
Apacheホストと同じローカルネットワーク上の別のマシンからテストを再度実行すると、はるかに合理的な結果が得られます。
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 2 0.8 2 4
Processing: 13 118 99.8 205 222
Waiting: 13 118 99.7 204 222
Total: 15 121 99.7 207 225
Percentage of the requests served within a certain time (ms)
50% 207
66% 219
75% 220
80% 221
90% 222
95% 224
98% 224
99% 225
100% 225 (longest request)
これらの2つのテストを合わせると、いくつかの疑問が生じますが、それとは別に、特定の負荷の下で発生するある種の深刻なネットワークボトルネックに対して行われる説得力のあるケースがあります。次のステップは、ネットワーク層を個別に調査することだと思います。
この状況で私がすることは実行されます
_strace -f -p <PID> -tt -T -s 500 -o trace.txt
_
遅い応答の1つをキャプチャするまで、abテスト中にApacheプロセスの1つで。次に、_trace.txt
_を確認します。
_-tt
_および_-T
_オプションは、各システムコールの開始と期間のタイムスタンプを提供し、遅いものを識別するのに役立ちます。
open()
やstat()
などの単一の低速システムコールが見つかる場合や、直後に(場合によっては複数の)poll()
呼び出しがあるクイックコールが見つかる場合があります。ファイルまたはネットワーク接続で動作しているものを見つけた場合(おそらく)、そのファイルまたは接続ハンドルが見つかるまでトレースを逆方向に調べます。同じハンドルでの以前の呼び出しにより、poll()
が何を待っていたかがわかります。
_-c
_オプションを確認することをお勧めします。トレースしていたApacheの子が、その間に少なくとも1つの遅いリクエストを処理したことを確認しましたか? (すべての子で同時にstrace
を実行する以外に、これをどのように行うかさえわかりません。)
残念ながら、strace
は、実行中のプログラムが実行していることの全体像を示していません。システムコールのみを追跡します。カーネルに何も要求する必要のないプログラム内では、多くのことが発生する可能性があります。これが発生しているかどうかを確認するには、各システムコールの開始のタイムスタンプを確認します。大きなギャップが見られる場合は、それが時間の流れです。これは簡単に把握することはできず、とにかくシステムコールの間には常に小さなギャップがあります。
CPU使用率が低いままであるとおっしゃっていたので、それはおそらくシステムコールの間に過度のことが起こっているわけではありませんが、チェックする価値があります。
ab
からの出力を詳しく見てみましょう。
応答時間の突然の急増(150msから3000msの間のどこにも応答時間がないように見えます)は、約256の同時接続を超えてトリガーされる特定のタイムアウトがどこかで発生していることを示しています。 RAMまたはCPUサイクルの通常のIOが不足している場合は、よりスムーズな劣化が予想されます。
次に、遅いab
応答は、3000msがconnect
フェーズで費やされたことを示しています。ほぼすべてが約30ミリ秒かかりましたが、5%は3000ミリ秒かかりました。これは、ネットワークに問題があることを示しています。
どこからab
を実行していますか? Apacheマシンと同じネットワークから試すことができますか?
さらにデータが必要な場合は、接続の両端でtcpdump
を実行してみて(できれば、2つのキャプチャを同期できるように両端でntp
を実行してください)、tcpの再送信を探します。 Wiresharkは、tcpの再送信を異なる色で強調表示し、見つけやすくするため、ダンプの分析に特に適しています。
また、アクセスできるネットワークデバイスのログを確認する価値があるかもしれません。最近、ファイアウォールの1つで問題が発生し、kb/sで帯域幅を処理できましたが、受信した1秒あたりのパケット数を処理できませんでした。毎秒140,000パケットでトップになりました。 ab
の実行に関する簡単な計算により、1秒あたり約13,000パケットが表示されていると思います(遅い要求の5%を無視します)。多分これはあなたが到達したボトルネックです。これが約256で発生するという事実は、まったくの偶然かもしれません。