7

Jetty で実行している Java サーブレットで非常に厄介な問題が発生しています。負荷が低から中程度の場合は完全に機能しますが、負荷が特定のレベルに達すると、約 10 ~ 20 分後に要求への応答が停止します。

curl を使用して接続しているときにメインの Java プロセスをトレースすると、接続を確立し、リクエストを受信し、それを解析して、通常の処理 (Solr サーバーへのクエリ、MySQL クエリの実行など) を行うことがわかりますが、結果がクライアントに返されることはありません。

ハングすると、無期限にハングします。「スナップアウト」する時間はありませんが、メインの java/jetty プロセスでランダムなスレッドを強制終了すると、スレッドの数が減少し、リクエストへの応答が再開されます。

外観は次のとおりです。

# curl http://localhost:8080/some-servlet-url

(Does not respond at this point)

# ps -efL | grep qserv | wc -l
243
# ps -efL | grep qserv | wc -l
243
# ps -efL | grep qserv | wc -l
243

(Number of threads remain seemingly constant)

# kill 29760   <--- random thread under the main java/jetty process
# ps -efL | grep qserv | wc -l
26

(Number of threads immediately decreases sharply)

# curl http://localhost:8080/some-servlet-url
... HTTP response ...

(Responds to connections again)

サーバーは、Ubuntu 12.04.1 LTS および Jetty 8.1.7.v20120910 を実行する m2.2xlarge Amazon EC2 インスタンスです。

$ java -version
java version "1.7.0_07"
OpenJDK Runtime Environment (IcedTea7 2.3.2) (7u7-2.3.2-1ubuntu0.12.04.1)
OpenJDK 64-Bit Server VM (build 23.2-b09, mixed mode)

いくつかの異なる Java と Jetty のバージョンを試しました。また、Jetty の代わりに Tomcat を使用してみました - 同じ問題。

YourKit を使用してアプリをプロファイリングすると、明らかなスレッド ロックや過剰な CPU 使用率は示されません。

何か案は?

編集:ハングしている Java プロセスのスタック トレースを取得できました。すべての http スレッドが次の状態にあるようです。

"http-bio-8080-exec-5" daemon prio=10 tid=0x00007fe518007800 nid=0x1fc5 in Object.wait() [0x00007fe57934f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076ee9d230> (a org.apache.commons.pool.impl.GenericObjectPool)
        at java.lang.Object.wait(Object.java:503)
        at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:810)
        - locked <0x000000076ee9d230> (a org.apache.commons.pool.impl.GenericObjectPool)
        at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:95)
        at net.acmecorp.active.QueryResultXMLFormatter.selectBestHitsAndRunDocumentCompletion(QueryResultXMLFormatter.java:362)
        at net.acmecorp.active.QueryResultXMLFormatter.queryResultToXMLRootElement(QueryResultXMLFormatter.java:167)
        at net.acmecorp.active.QueryPrepareAndExecuter.prepareParametersAndExecuteQuery_AndInvokeFormatter(QueryPrepareAndExecuter.java:239)
        at net.acmecorp.servlets.MultiQueryServlet.handle(MultiQueryServlet.java:470)
        at net.acmecorp.servlets.MultiQueryServlet.doGet(MultiQueryServlet.java:85)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
        - locked <0x0000000700dd70d0> (a org.apache.tomcat.util.net.SocketWrapper)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)

   Locked ownable synchronizers:
        - <0x000000076ed40990> (a java.util.concurrent.ThreadPoolExecutor$Worker)

私自身は Java の専門家ではないので、何が問題なのか正確にはわかりませんが、何かを待っているように見えます...

4

1 に答える 1

5

データベースプーリングの問題があり、httpスレッドはすべてデータベースリソースが解放されるのを待っています。これは一般的な問題です。プール内のデータベース接続の数を増やして問題がなくなるか、jettyのQoSFilterなどのQoSサービスを使用して、受信するリクエストの数を制限する必要があります。小さなデータベースプールを保護するプロセス。

データベースプールが消費された理由はいくつかあります。アプリケーションでそれらをリークしている(プールから取得し、使用し、決して返さない)か、要求が多すぎる可能性があります。同時に。または、データベースプーリングライブラリ自体の問題が発生します。

いずれにせよ、これは突堤やTomcatの問題ではなく、アプリケーションとデータベース間のリソース競合の問題です。リクエストはjettyまたはtomcatに入り、サーブレットランドに入り、サーブレットなどでデータベース接続を待機します。これは単純なことです。

于 2012-09-20T19:58:33.513 に答える