EC2でホストされているTomcatの前にApacheウェブサーバーがあり、インスタンスタイプは34GBのメモリで非常に大きいです。
私たちのアプリケーションは多くの外部Webサービスを扱っており、ピーク時にリクエストに応答するのに約300秒かかる非常に粗末な外部Webサービスがあります。
ピーク時に、サーバーは約300のhttpdプロセスで窒息します。 ps -ef | grep httpd | wc -l = 300
私はグーグルし、多数の提案を見つけましたが、何も動作しないようです。以下は、オンラインリソースから直接取得した、私が行ったいくつかの構成です。
ApacheとTomcatの両方で、最大接続数と最大クライアント数の制限を増やしました。設定の詳細は次のとおりです。
// Apache
<IfModule prefork.c>
StartServers 100
MinSpareServers 10
MaxSpareServers 10
ServerLimit 50000
MaxClients 50000
MaxRequestsPerChild 2000
</IfModule>
// Tomcat
<Connector port="8080" protocol="org.Apache.coyote.http11.Http11NioProtocol"
connectionTimeout="600000"
redirectPort="8443"
enableLookups="false" maxThreads="1500"
compressableMimeType="text/html,text/xml,text/plain,text/css,application/x-javascript,text/vnd.wap.wml,text/vnd.wap.wmlscript,application/xhtml+xml,application/xml-dtd,application/xslt+xml"
compression="on"/>
//Sysctl.conf
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
fs.file-max = 5049800
vm.min_free_kbytes = 204800
vm.page-cluster = 20
vm.swappiness = 90
net.ipv4.tcp_rfc1337=1
net.ipv4.tcp_max_orphans = 65536
net.ipv4.ip_local_port_range = 5000 65000
net.core.somaxconn = 1024
私は多くの提案を試みてきましたが、無駄です。これを修正する方法は? m2xlargeサーバーは300を超えるリクエストを処理するはずです。おそらく、設定が間違っている可能性があります。
サーバーは、ピーク時と[300秒の遅延] Webサービスが応答するのを待っている300の同時リクエストがある場合にのみチョークします。
Netstatでtcp接続を監視していた
私はTIME_WAIT状態で約1000の接続を見つけました。パフォーマンスの点でそれが何を意味するのかわからないので、問題に追加しているはずです。
TOPの出力
8902 root 25 0 19.6g 3.0g 12m S 3.3 8.8 13:35.77 Java
24907 membase 25 0 753m 634m 2528 S 2.7 1.8 285:18.88 beam.smp
24999 membase 15 0 266m 121m 3160 S 0.7 0.3 51:30.37 memcached
27578 Apache 15 0 230m 6300 1536 S 0.7 0.0 0:00.03 httpd
28551 root 15 0 11124 1492 892 R 0.3 0.0 0:00.25 top
Output of free -m
total used free shared buffers cached
35007 8470 26536 0 1 61
8407 26599
15999 15 15984
output of iostat
avg-cpu: %user %Nice %system %iowait %steal %idle
26.21 0.00 0.48 0.13 0.02 73.15
Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
sda1 14.36 4.77 329.37 9005402 622367592
sdb 0.00 0.00 0.00 1210 48
また、ピーク時にはmembaseサーバー[ローカル]への約10-15kのtcp接続があります。
MODJK LOGにエラーが発生しました。これにより、問題が明らかになります。
[Wed Jul 11 14:39:10.853 2012] [8365:46912560456400] [error] ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:18.627 2012] [8322:46912560456400] [error] ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:21.358 2012] [8351:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)
[Wed Jul 11 14:39:22.640 2012] [8348:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)
〜
Worker.properties
workers.Tomcat_home=/usr/local/Tomcat/
worker.list=loadbalancer
worker.tom1.port=8009
worker.tom1.Host=localhost
worker.tom1.type=ajp13
worker.tom1.socket_keepalive=True
worker.tom1.connection_pool_timeout=600
worker.tom2.port=8109
worker.tom2.Host=localhost
worker.tom2.type=ajp13
worker.tom2.socket_keepalive=True
worker.tom2.connection_pool_timeout=600
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tom1,tom2
worker.loadbalancer.sticky_session=True
worker.tom1.lbfactor=1
worker.tom1.socket_timeout=600
worker.tom2.lbfactor=1
worker.tom2.socket_timeout=600
//解決
すべての貴重な提案に感謝します。AJP1.3コネクタのmaxThreads設定を逃してしまいました。
Nginxのようなベースのサーバーも検討し始めます。
ポート8009のAJP 1.3コネクターでmaxThreadsを増やしましたか?
Apacheの前にnginx
やlighttpd
のような非同期プロキシWebサーバーを設定することを検討してください。 Apacheはコンテンツを同期的に提供するため、クライアントが生成されたコンテンツを完全にダウンロードするまでワーカーはブロックされます(詳細 こちら )。非同期(非ブロッキング)プロキシを設定すると、通常、状況が劇的に改善されます(以前は、nginx
をフロントエンドプロキシとして使用して、同時に実行するApacheワーカーの数を30から3-5に減らしました)。
とにかくあなたが示したログから、あなたの問題はApacheではなくTomcatにあると思います。 Tomcatに接続しようとして「エラー110」が発生した場合、それは、Tomcatのリスニングソケットのリスニングバックログセットアップにこれ以上適合できない、処理待ちの接続のキューがあることを示しています。
From the listen manpage:
The backlog parameter defines the maximum length the queue of pending
connections may grow to. If a connection request arrives with
the queue full the client may receive an error with an indication
of ECONNREFUSED or, if the underlying protocol supports
retransmission, the request may be ignored so that retries succeed.
推測しなければならないのであれば、サーバーが「窒息」しているときのHTTPリクエストの大部分は、Tomcatから何かが返ってくるのを待ってブロックされているのではないかと思います。 (Tomcatにプロキシされるのではなく)Apacheによって直接提供されるいくつかの静的コンテンツをフェッチしようとした場合、これは通常は「窒息」している場合でも機能すると思います。
残念ながら私はTomcatに詳しくありませんが、代わりにこれの同時実行設定を操作する方法はありますか?
そして、外部ネットワークサービスがitが実行している接続数を制限している可能性についても考慮する必要があるかもしれませんitが300にダウンしているため、実行するすべての接続が外部Webサービスの応答に依存している場合、フロントサイドで実行している並行性の操作量に違いはありません。
あなたのコメントの1つで、データが2分後に古くなると述べました。このサービスから取得した応答を2分間キャッシュして、外部Webサービスへの同時接続数を減らすことをお勧めします。
これをトラブルシューティングするための最初のステップは、Apacheの mod_status を有効にし、そのレポートを調査することです。これが完了するまで、実際には盲目的に歩いています。それは正しくありません。 ;-)
2番目に言及すること(私は自分が尋ねていなかった質問に対する答えを私に言われるのが嫌いですが...)は、nginx
のようなより効率的で特別なフロントエンドサーバーを使用しています。
また、Apacheはrestart
だけですか、それともgraceful
ly reloaded それだけですか? :)
どのようなエンタープライズyの展開でも、prefork MPMはあなたができる最悪の選択肢です。他のMPMと比較して、スレッドを再起動すると他のMPMよりもずっと時間がかかります。
少なくともworker MPM(Apache 2.2以降)に切り替えるか、または-より良い方法として、デフォルトのevent MPMで現在の安定バージョン2.4.2にアップグレードします。
これらはどちらも、オーバーヘッドがほとんどない状態で数千の同時接続を簡単に処理します。
それは古い話だと知っていますが、2つの発言があります。
ServerLimitディレクティブには、ハードコードされた制限があります。 http://httpd.Apache.org/docs/2.2/mod/mpm_common.html#serverlimit 最大20000/200Kであることがわかります。
サーバーにコンパイルされたServerLimit 20000のハード制限があります(prefork MPM 200000の場合)。これは、タイプミスによる厄介な影響を回避するためのものです。
2ndどうやらnodyboは、これらの2を1に設定することは非常に悪い考えだと述べました:
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
それはあなたがタイムウェイトを早く再利用することを意味します、どう思いますか?サーバーは、高負荷時に間違ったクライアントと通信する可能性があります。
私はそれを説明する非常に良い記事を見つけましたが、それはフランス語です;-) http://vincent.bernat.im/fr/blog/2014-tcp-time-wait-state-linux.html
たぶん、Apacheユーザーは許可されたファイルハンドルを使い果たしていますか?あなたは投稿でそれらについてまったく言及しませんでした。 Apacheが現在持つことができるファイルハンドルはいくつありますか?
これはコメントのようなものですが、私は評判が低いので、そうすることはできません。 @john titusとまったく同じ問題が発生しました。
この問題を解決するために、AJPコネクタMaxThreads
をApacheスレッドの制限に近づけました。
これを監視するために、SYN_SENT
netstatポートステータスヘルプ AJPポートでnetstatコマンドを使用。
netstat -an | grep :8102 | grep SYN_SENT | wc -l
これは0になりました。これは常に、AJPコネクターに設定されたMaxThread制限の前にいくらか大きな数でした。
34GBのメモリを備えた超大容量。
ビッグアイアンは、ボトルネックを回避するだけのWebサービスをスケーリングする方法ではありません。しかし、これだけのメモリがあっても、特に次のような場合、50000の接続がシステムの能力を押し上げていると思います。
ピーク時にサーバーは約300のhttpdプロセスでチョークを鳴らします
「サーバーのチョーク」によってあなたが何を意味するのかを説明すると役立つでしょう。
接続にこのような高い制限があるのに非常に奇妙ですが、ヒステリシスには非常に低い制限があります(スペアサーバーの最小/最大)。
あなたが提供したエラーの抜粋には「オープンファイルが多すぎる」という明確な説明はありませんが、オープンファイル記述子の数とulimit設定を確認することから始めます。