ネットワークの問題が原因で失敗したクエリを 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 でこれらの問題を抱えていて、解決策を見つけましたか?