0

ネットワークの問題が原因で失敗したクエリを C3P0 (または DBCP) に自動的に再試行させる方法はありますか。コードは正常に動作しますが、次の例外が発生することがあります (特定のクエリはなく、さまざまなクエリで発生し、数秒ごとに発生する単純な行カウントでも発生するため、確実に機能しますが、突然失敗します:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
at sun.reflect.GeneratedConstructorAccessor89.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1117)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3567)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3456)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3997)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2468)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2629)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2719)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1379)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.execute(NewProxyPreparedStatement.java:989)
at com.outboundengine.database.ClickstreamIdentityDbo.insertIgnore(ClickstreamIdentityDbo.java:65)
... 22 more
Caused by: java.net.SocketException: Connection timed out

at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:150)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114)
at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161)
at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189)
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3014)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3467)
... 31 more

アプリ サーバーと DB サーバーの間で毎秒 traceroute の実行を開始し、次のような一連のトレースを取得しました。

Wed Apr 17 15:52:41 UTC 2013
traceroute to XXX.XXXXXXXXXX.com (XXX.XXX.XXX.XXX), 30 hops max, 60 byte packets
 1  ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  0.352 ms  0.443 ms  0.418 ms
 2  ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  0.588 ms ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  0.625 ms ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  0.543 ms
 3  ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  0.867 ms ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  33.166 ms  33.505 ms
 4  ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  1.554 ms ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  0.435 ms ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  0.756 ms
 5  ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  0.830 ms ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  0.803 ms ip-XXX-XXX-XXX-202.ec2.internal (XXX.XXX.XXX.XXX)  1.107 ms
 6  * ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  1.449 ms *
 7  ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  0.715 ms ip-XXX-XXX-XXX-202.ec2.internal (XXX.XXX.XXX.XXX)  0.973 ms  1.240 ms
 8  * * *
 9  * * *
10  * * *
11  * * *
12  * * ip-XXX-XXX-XXX-XXX.ec2.internal (XXX.XXX.XXX.XXX)  0.445 ms

... (これらの多くは、10 ~ 60 秒続く「停止」期間中に発生しますが、接続がタイムアウトするまでに 10 分かかります)。

C3P0 の設定は次のとおりです。

<Resource name="jdbc/somename"
    auth="Container"
    factory="org.apache.naming.factory.BeanFactory"
    type="com.mchange.v2.c3p0.ComboPooledDataSource"
    driverClass="com.mysql.jdbc.Driver"
    maxPoolSize="100"
    minPoolSize="10"
    acquireIncrement="10"

    automaticTestTable="testtable"
    testConnectionOnCheckin="true"
    idleConnectionTestPeriod="600"

    user="XXX"
    password="XXX"
    jdbcUrl="jdbc:mysql://XXXXXXXXXX:3306/dbname?autoReconnect=true"
  />

例外が発生している間、さまざまな場所で * が設定された各 traceroute。
これは Amazon EC2 で実行されています (これらのタイムアウトにつながる高いパケット損失で悪名高いバージニア州の場所で)。コードは、C3P0 db 接続プールに基づく単純な JDBC クエリです (ネットワークの問題なしで完璧に動作します)。C3P0 は再接続され、タイムアウト後にすべての接続が行われましたが、タイムアウトが発生するまでに約 10 分かかり、ネットワークが安定するとすべてが正常に戻りますが、少なくとも 1 日に 1 回はこれらの停止が発生し、クエリが失われ、再試行する必要があります。

コード内のすべてのクエリを変更するのを防ぐ DB 接続プールの設定はありますか? または、あきらめる前に再試行が数回失敗する単純なループを作成する必要がありますか? 他の誰かが EC2 でこれらの問題を抱えていて、解決策を見つけましたか?

4

0 に答える 0