2016-12-13 3 views
-1

私は、Tomcat 7.0.52サーブレットサーバとHibernate 4.3とJPA 2.1を介してpostgresqlデータベースを使用しています。Tomcat7が何らかの作業時間後にスタックする

Nginxは、サーバーへのすべての要求を、tomcatサーバーのポート8088からポート8888にプロキシします。

サーバーには、毎秒200リクエストがあります。数時間後、要求に対する応答が停止します。私はtomcat7のマネージャーページにアクセスすることができない、私はサーブレットのコンテキストにアクセスすることはできません。常に応答要求のタイムアウトエラーです。しかし、サーバーはまだ動作していますが、スケジュールされたサービスは引き続き動作し、データベースにアクセスできます。

スタックでは、私はtomcat7で0.04-0.08%のCPU使用率、postgresqlでは0.01~0.02%のCPU使用率を持っています。 tomcat7では3〜4%のCPU使用率が異なり、通常の作業ではpostgresqlで12〜14%のCPU使用率があります。

tomcat7サーバーを再起動した後、もう一度正常に動作します。

私はデータベースに問題はないと思うが、postgresql-9.3-main.logは空ですが、ロギングが有効です。 psqlで何か問題が起きたときに私はそれを見る。

Tomcat7 catalina.outとlocalhost.YYYY-MM-DD.logのすべてのログファイルに例外やエラーがないので、OutOfMemoryやその他の例外に問題はないと思います。

nginxに問題はないと思います。他のポートやサイトへのすべてのリクエストが正常に機能しているからです。

メモリリークに問題はないと思いますが、JAVAは常に約700-800MBのメモリを消費し、スタック時間にはピークがありません。

私は非常に似たような問題を抱えていましたが、これは何の助けにもなりませんでした。

acceptorThreadCountを1から2に変更すると、サーバーがはるかに高速に停止します。

tomcat7サーバーによる接続を受け入れるには何かのように見えます。 私には何も分からないアイディアはもうありません。

JVMオプション:

JAVA_OPTS="-Xms1024m -Xmx2048m -XX:MaxPermSize=256m" 

Tomcat7バージョン情報:

Server version: Apache Tomcat/7.0.52 (Ubuntu) 
Server built: Jul 24 2014 08:38:51 
Server number: 7.0.52.0 
OS Name:  Linux 
OS Version:  3.13.0-53-generic 
Architecture: amd64 
JVM Version: 1.7.0_79-b14 
JVM Vendor:  Oracle Corporation 

nginxの設定ファイル:

worker_rlimit_nofile 8192; 
worker_processes 4; 
timer_resolution 100ms; 
worker_priority -5; 

pid /run/nginx.pid; 

events { 
    worker_connections 2048; 
    use epoll; 
} 

http { 
    sendfile on; 
    tcp_nopush on; 
    tcp_nodelay on; 
    output_buffers 2 512k; 
    client_max_body_size 150M; 

    gzip on; 
    gzip_min_length 1100; 
    gzip_buffers 64 8k; 
    gzip_comp_level 3; 
    gzip_disable "msie6"; 
    gzip_http_version 1.1; 
    gzip_proxied any; 
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; 

    keepalive_timeout 30; 
    server_tokens off; 
    reset_timedout_connection on; 
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; 

    types_hash_max_size 2048; 
    server_names_hash_bucket_size 64; 
    server_names_hash_max_size 2056; 

    include /etc/nginx/mime.types; 
    default_type application/octet-stream; 

    include /etc/nginx/conf.d/*.conf; 
    include /etc/nginx/sites-enabled/*; 
    include blockips.conf; 
} 

nginxのサーバ設定:

server { 
    listen 8080; 
    server_name <my_ip>; 

    proxy_headers_hash_max_size 512; 
    proxy_headers_hash_bucket_size 64; 

    location/{ 
     proxy_set_header X-Forwarded-For $http_x_real_ip; 
     #proxy_set_header X-NginX-Proxy true; 

     proxy_pass   http://127.0.0.1:8888/; 
     proxy_redirect  off; 
    } 
} 

コネクタの設定:

port="8888" 
protocol="org.apache.coyote.http11.Http11NioProtocol" 
connectionTimeout="20000" 
acceptorThreadCount="1" 
maxThreads="500" 
URIEncoding="UTF-8" 
redirectPort="8443" 

は、事前にありがとうございます。問題が解決した

を更新。ここで適切な解決策が見つかりましたhttps://stackoverflow.com/a/3731978/7289901

idle_test_periodsがtimeoutよりも高いため、休止状態が正しく設定されていませんでした。これらの変数を正しい値に固定した後、サーバーは非常に安定した状態になりました。

更新私は、問題の原因を見つけるために許さ休止の2

全cofig:

<property name="hibernate.c3p0.acquire_increment">3</property> 
<property name="hibernate.c3p0.acquireRetryAttempts">3</property> 
<property name="hibernate.c3p0.acquireRetryDelay">250</property> 
<property name="hibernate.c3p0.idle_test_period">10</property> 
<property name="hibernate.c3p0.min_size">0</property> 
<property name="hibernate.c3p0.max_size">50</property> 
<property name="hibernate.c3p0.max_statements">50</property> 
<property name="hibernate.c3p0.timeout">30</property> 
<property name="hibernate.c3p0.checkoutTimeout">500</property> 
<property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces">true</property> 
<property name="hibernate.c3p0.unreturnedConnectionTimeout">30</property> 
<property name="hibernate.c3p0.numHelperThreads">5</property> 
+0

実稼働環境以外で複製が可能である必要があります。最初にコードを見てください。 Tomcatは動作します。プロファイラを接続する。 –

+0

私はコードで間違える可能性があることを認めます。しかし、私はdoGetとdoPostメソッドの始めにすべての着信要求を記録し、要求はロギングを停止します。私は、CPU使用率が最大100%にまで上昇するかどうかは分かりますが、サーバーはプロセス要求を試みたりログに記録したりしません。そして、CPU使用率が最小限に抑えられます。そして私が言ったように、tomcat7管理者も応答しない。それは私のために奇妙です。 – Vladimir

+0

Tomcatの前でNginxを実行している特定の理由はありますか? –

答えて

0

私の最初の推測では、何かがあなたのJPAのコードで間違っているということです。 TomcatとDBの両方で低CPUから始め、Tomcatでは3-4%、DBサーバーでは12-14%で終了します。

Tomcatアプリケーションがステートレスである場合、スケーリングは実質的に線形であり、HttpSessionにデータを保存しても、Tomcatのクラスタリングを開始するまでオーバーヘッドはほとんどありません。

データベースの規模もかなり大きいですが、フル・テーブル・スキャンは実行しませんが、適切な索引を持っている場合に限ります。おそらく、長いランタイムを持つ個々のクエリがあるかどうかを調べるために、postgresql(log_min_duration_statementプロパティ)での低速クエリのログを有効にする必要があります。

Tomcatマネージャで接続できない場合は、おそらくすべてのhttpアクセプタが使用されているためです。しかし、JVisualVMに接続することはできます。 JViaualVMにはCPUサンプラーがあります。起動すると、どこで時間が費やされているかを確認できるはずです。ここで問題となるのは、ほとんどのCPUがDB上で使用されているのでCPU時間を見ることができず、自己時間を見ると、コールスタックの前のすべてのステップがコードよりも高くなる(風袋と春は通常、20ミリスタックフレームを追加します)。

スレッドダンプを実行して、httpスレッドが何をしているのかを確認することができます(これはCPUサンプラーが基本的に行っていることです)。

CPUサンプリングとスレッドダンプは、どこに作業を集中するかについてのアイディアを提供します。私の推測では、それはJPAに関連しているということです。

非常に悪い方法でデータベースを使用するJPAでコードを記述することは可能です。多くの場合、遅延ロードされたコレクションは、開始するのに適しています。 Company> -Employee> -phone(1-N、1-N)のERモデルを持ち、会社内の従業員のすべての電話番号を印刷する場合は、会社から開始して従業員コレクションをループすることができます電話番号を介して各従業員のループごとに表示されます。従業員を読​​み込むためのクエリと電話番号を読み込むための各従業員のクエリが必要なので、これは1 + Nのクエリになります。より良い解決策は、フェッチ結合クエリを使用してデータを選択することです。データベースは、単一の操作ですべての従業員と電話番号を読み込む単一のクエリのみを実行します。

もう1つのよくある間違いは、遅延ロードされたコレクションにデータを追加することです。これは、JPAがコレクションのすべてのデータを最初にロードするためです。

あなたはSpringを使用しているので、あなたのエンティティマネージャはたぶん管理されている(そしてトランザクションスコープがある)ので、永続コンテキストのデータ蓄積に問題はないでしょう。

読み込み専用のクエリがある場合は、JPAプロバイダにチェックをして、最適化できる@QueryHintがあるかどうかを確認する必要があります。デフォルトでは、JPAは永続コンテキストにロードされたすべてのオブジェクトのコピーを保持する必要があるため、トランザクションがコミットされたときに変更が加えられたかどうかを確認できます。このプロセスには時間がかかります(読み取り専用クエリの目的はありません)。

JPAに対してクエリログを有効にできますが、多くの出力が生成される傾向があります。

あなたがソースを見つけることを望みます。

+0

ここで私の問題の解決策が見つかりました:http://stackoverflow.com/a/3731978/7289901 idle_test_periodsがタイムアウトよりも高いため、休止状態が正しく設定されていません。これらの変数を正しい値に固定した後、サーバーは非常に安定した状態になりました。 ありがとうございました!あなたは正しい方向に私を導く! – Vladimir

関連する問題