2

私のアプリケーションは、毎分単一の http リクエストによってクエリされています。c3p0 が CullExpired およびその他のバックグラウンド スレッドを実行すると、アプリケーションは一時的にタイムアウトし、応答しなくなります。この問題はランダムに発生し、まれな間隔で発生します。アプリケーションがタイムアウトしたときのすべてのインスタンスで、c3p0 バックグラウンド スレッドが実行され、クリーンアップまたはアイドル接続の削除を試みていることがわかります。これは非常にランダムに発生し、ログには他の例外はありません。しばらくすると、アプリケーションは自動的に回復し、処理を再開します。このような問題を経験した人はいますか。

   c3p0 version is <version>0.9.1.2</version>
    hibernate version is <version>3.3.2.GA</version>

私のc3p0構成は次のとおりです。

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close" 
        p:driverClass="#{['app.jdbc.driverClassName']}"
        p:jdbcUrl="#{['app.jdbc.url']}" 
        p:user="#{['app.jdbc.username']}" 
        p:password="#{['app.jdbc.password']}"
        p:acquireIncrement="5" 
        p:idleConnectionTestPeriod="80"
        p:maxAdministrativeTaskTime="600" 
        p:numHelperThreads="10"
        p:maxIdleTime="60" 
        p:maxPoolSize="20" 
        p:maxStatements="30"
        p:minPoolSize="10" />
4

1 に答える 1

2

c3p0 のバックグラウンド スレッドは常に存在します。それらはスレッドプールで実行されます。そのプールのサイズを 10 スレッド (c3p0.numHelperThreads) に設定しました。スタック ダンプを調べると、設定の下に CullExpired などの c3p0 タスクが頻繁に実行されていることがわかります。これらの頻度は、リソースが期限切れになる構成設定と同じ桁数です。あなたの場合、 maxIdleTime は 60 秒なので、カルタスクはおそらく 20 秒ごとに実行されています。c3p0 の管理タスクは、IO 中にロックを保持しないように慎重に設計されており、一般的に軽量で、他の作業とできるだけ競合しないようになっています。したがって、ハングの原因がこれらの管理タスクである場合は、奇妙なことが起こっています。しかし、ここで原因と偶然の違いを見分けるのは難しいです: c3p0'

maxIdleTime は、問題の考えられる説明の 1 つです。あなたが使用している構成はそれほど素晴らしいものではありません。1 分あたり 1 つのクライアント接続は、c3p0 にとって非常に小さな負荷ですが、minPoolSize は 10 接続です。そのため、c3p0 は 10 個の接続を取得し、それらを約 1 分間保持してから期限切れになり、それらすべてを再取得します。これは同時に多くのオーバーヘッドになります。80 秒の idleConnectionTestPeriod は役に立ちません。テスト期間が経過する前に、60 秒のアイドル状態の後、アイドル状態の接続が期限切れになるため、アイドル状態の接続はテストされません。また、 acquireIncrement をデフォルトの 3 に戻します。

より良い構成を試して、問題が解決するかどうかを確認します。あなたが説明した負荷を考えると、minPoolSize をデフォルトの 3 のままにし、numHelperThreads を 3 に設定します。最初のパスとして、maxIdleTime をデフォルトのゼロに設定しますが、testConnectionOnCheckout を true に設定します。これは、接続テストの最も単純で信頼性の高い形式ですが、クライアントに目に見えるパフォーマンス コストがかかります。そのコストを最小限に抑えるには、遅いデフォルトの接続テストに頼るのではなく、preferredTestQuery を設定する必要があります。多くの場合、「SELECT 1」が機能しますが、データベース/JDBC ドライバーに依存する場合があります。うまくいっている場合は、より大胆に、ややパフォーマンスが高く、堅牢性がやや劣る接続テスト戦略を試すことができます。idleConnectionTestPeriod を比較的小さな値 (たとえば 30) に設定します。そして、testConnectionOnCheckin を true に設定します (また、testConnectionOnCheckout をデフォルトの false に戻します)。見る [http://www.mchange.com/projects/c3p0/#configuring_connection_testing ]

また、ステートメントのキャッシュを今のところオフ (maxStatements を 0 に設定) にしておき、後で安定したときに再びオンにして、アプリケーションのパフォーマンスが向上するかどうかをテストします。[これは if -- http://www.mchange.com/projects/c3p0/#known_shortcomingsを参照]

c3p0 [c3p0-0.9.2-pre5] の最新バージョンに更新することもお勧めします。接続の取得は 0.9.2 ではもう少し軽量化されており、問題の一部は 1 分ごとのフラッシュと再取得のサイクルに関係している可能性があります。一般的に、0.9.2-pre シリーズはかなり安定しており、使用する価値があると思います。

これが役立つことを願っています!

于 2012-11-04T16:50:22.190 に答える