web-dev-qa-db-ja.com

Apache Tomcatが300接続後にチョークする

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のようなベースのサーバーも検討し始めます。

16
john titus

ポート8009のAJP 1.3コネクターでmaxThreadsを増やしましたか?

13
HTTP500

Apacheの前にnginxlighttpdのような非同期プロキシWebサーバーを設定することを検討してください。 Apacheはコンテンツを同期的に提供するため、クライアントが生成されたコンテンツを完全にダウンロードするまでワーカーはブロックされます(詳細 こちら )。非同期(非ブロッキング)プロキシを設定すると、通常、状況が劇的に改善されます(以前は、nginxをフロントエンドプロキシとして使用して、同時に実行するApacheワーカーの数を30から3-5に減らしました)。

6
Alex

とにかくあなたが示したログから、あなたの問題は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サービスへの同時接続数を減らすことをお勧めします。

5
Matthew Ife

これをトラブルシューティングするための最初のステップは、Apacheの mod_status を有効にし、そのレポートを調査することです。これが完了するまで、実際には盲目的に歩いています。それは正しくありません。 ;-)

2番目に言及すること(私は自分が尋ねていなかった質問に対する答えを私に言われるのが嫌いですが...)は、nginxのようなより効率的で特別なフロントエンドサーバーを使用しています。

また、Apacheはrestartだけですか、それともgracefully reloaded それだけですか? :)

2
poige

どのようなエンタープライズyの展開でも、prefork MPMはあなたができる最悪の選択肢です。他のMPMと比較して、スレッドを再起動すると他のMPMよりもずっと時間がかかります。

少なくともworker MPM(Apache 2.2以降)に切り替えるか、または-より良い方法として、デフォルトのevent MPMで現在の安定バージョン2.4.2にアップグレードします。

これらはどちらも、オーバーヘッドがほとんどない状態で数千の同時接続を簡単に処理します。

1
adaptr

それは古い話だと知っていますが、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

1
Nadir

たぶん、Apacheユーザーは許可されたファイルハンドルを使い果たしていますか?あなたは投稿でそれらについてまったく言及しませんでした。 Apacheが現在持つことができるファイルハンドルはいくつありますか?

0

これはコメントのようなものですが、私は評判が低いので、そうすることはできません。 @john titusとまったく同じ問題が発生しました。

この問題を解決するために、AJPコネクタMaxThreadsをApacheスレッドの制限に近づけました。

これを監視するために、SYN_SENTnetstatポートステータスヘルプ AJPポートでnetstatコマンドを使用。

netstat -an | grep :8102 | grep SYN_SENT | wc -l

これは0になりました。これは常に、AJPコネクターに設定されたMaxThread制限の前にいくらか大きな数でした。

0
Vineeth

34GBのメモリを備えた超大容量。

ビッグアイアンは、ボトルネックを回避するだけのWebサービスをスケーリングする方法ではありません。しかし、これだけのメモリがあっても、特に次のような場合、50000の接続がシステムの能力を押し上げていると思います。

ピーク時にサーバーは約300のhttpdプロセスでチョークを鳴らします

「サーバーのチョーク」によってあなたが何を意味するのかを説明すると役立つでしょう。

接続にこのような高い制限があるのに非常に奇妙ですが、ヒステリシスには非常に低い制限があります(スペアサーバーの最小/最大)。

あなたが提供したエラーの抜粋には「オープンファイルが多すぎる」という明確な説明はありませんが、オープンファイル記述子の数とulimit設定を確認することから始めます。

0
symcbean