私はJava MongoDBでいくつかの集約を実行するアプリケーションですが、時々ハングアップしてSocketTimeout例外をスローします。例外の後、アプリは正常に実行されます(少しの間、おそらく例外を再度発生させます)。
たった今発見した この説明 これは考えられる原因のようですが、よくわかりません。
MongoClientを初期化し、DBへの接続を開いたままにします。これが問題になるかどうかはわかりません。データベースを毎回取得し、データベースをガベージコレクション(および接続を閉じる)するだけです。
別のアプローチとして、Mongoに定期的にpingして、接続プールを「最新の状態」に保つことができます。
使用されるクライアントは次のようなものです:
public class DbClient {
private static MongoClient mongoClient;
private static MongoDatabase db;
private DbClient() {}
public static void init() throws Exception {
mongoClient = new MongoClient();
}
public static MongoDatabase getDB() {
if(mongoClient == null)
throw new IllegalStateException("Client not initialized!");
if(db == null) {
db = mongoClient.getDatabase("my_db");
}
return db;
}
}
これがSocketTimeoutの考えられる原因ですか?
これはスローされる例外です:
09:20:45.742 [qtp605535417-46] INFO org.mongodb.driver.connection - Closed connection [connectionId{localValue:16, serverValue:6562}] to myapp.com:27017 because there was a socket exception raised by this connection.
09:20:45.743 [qtp605535417-46] ERROR myapp.service.Api - Error processing request
com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving message
at com.mongodb.connection.InternalStreamConnection.translateReadException(InternalStreamConnection.Java:474) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.Java:225) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.connection.UsageTrackingInternalConnection.receiveMessage(UsageTrackingInternalConnection.Java:102) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.connection.DefaultConnectionPool$PooledConnection.receiveMessage(DefaultConnectionPool.Java:435) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.connection.CommandProtocol.execute(CommandProtocol.Java:112) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.Java:159) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.Java:286) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.connection.DefaultServerConnection.command(DefaultServerConnection.Java:173) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.Java:215) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.Java:206) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.Java:112) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.operation.FindOperation$1.call(FindOperation.Java:487) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.operation.FindOperation$1.call(FindOperation.Java:482) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.Java:239) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.Java:212) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.operation.FindOperation.execute(FindOperation.Java:482) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.operation.FindOperation.execute(FindOperation.Java:79) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.Mongo.execute(Mongo.Java:772) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.Mongo$2.execute(Mongo.Java:759) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.OperationIterable.iterator(OperationIterable.Java:47) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.FindIterableImpl.iterator(FindIterableImpl.Java:143) ~[mongo-Java-driver-3.2.2.jar!/:na]
at myapp.common.db.service.dao.AnalysisMongoImpl.getAnalysis(AnalysisMongoImpl.Java:66) ~[common-0.2.0-SNAPSHOT.jar!/:na]
at myapp.common.db.service.AnalysisServiceImpl.getAnalysis(AnalysisServiceImpl.Java:31) ~[common-0.2.0-SNAPSHOT.jar!/:na]
at myapp.aggregator.service.Api$1.handle(Api.Java:88) ~[aggregator-0.2.0-SNAPSHOT.jar!/:na]
at spark.webserver.MatcherFilter.doFilter(MatcherFilter.Java:139) [spark-core-1.1.1.jar!/:na]
at spark.webserver.JettyHandler.doHandle(JettyHandler.Java:54) [spark-core-1.1.1.jar!/:na]
at org.Eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.Java:179) [jetty-server-9.0.2.v20130417.jar!/:9.0.2.v20130417]
at org.Eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.Java:136) [jetty-server-9.0.2.v20130417.jar!/:9.0.2.v20130417]
at org.Eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.Java:97) [jetty-server-9.0.2.v20130417.jar!/:9.0.2.v20130417]
at org.Eclipse.jetty.server.Server.handle(Server.Java:451) [jetty-server-9.0.2.v20130417.jar!/:9.0.2.v20130417]
at org.Eclipse.jetty.server.HttpChannel.run(HttpChannel.Java:252) [jetty-server-9.0.2.v20130417.jar!/:9.0.2.v20130417]
at org.Eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.Java:266) [jetty-server-9.0.2.v20130417.jar!/:9.0.2.v20130417]
at org.Eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.Java:240) [jetty-io-9.0.2.v20130417.jar!/:9.0.2.v20130417]
at org.Eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.Java:596) [jetty-util-9.0.2.v20130417.jar!/:9.0.2.v20130417]
at org.Eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.Java:527) [jetty-util-9.0.2.v20130417.jar!/:9.0.2.v20130417]
at Java.lang.Thread.run(Thread.Java:745) [na:1.7.0_95]
Caused by: Java.net.SocketTimeoutException: Read timed out
at Java.net.SocketInputStream.socketRead0(Native Method) ~[na:1.7.0_95]
at Java.net.SocketInputStream.read(SocketInputStream.Java:152) ~[na:1.7.0_95]
at Java.net.SocketInputStream.read(SocketInputStream.Java:122) ~[na:1.7.0_95]
at com.mongodb.connection.SocketStream.read(SocketStream.Java:85) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.connection.InternalStreamConnection.receiveResponseBuffers(InternalStreamConnection.Java:491) ~[mongo-Java-driver-3.2.2.jar!/:na]
at com.mongodb.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.Java:221) ~[mongo-Java-driver-3.2.2.jar!/:na]
... 34 common frames omitted
何度か試した後、 Azureのロードバランサー の問題であることがわかりました。
60秒間何も操作しないと、保留中のすべての接続が切断されますTCP接続。
さらに掘り下げた後、 MongoDB診断に関するFAQ のこの投稿を見つけ、tcpキープアライブを120秒に設定しました。
Sudo sysctl -w net.ipv4.tcp_keepalive_time=<value>
また、MongoClientの socketKeepAlive をtrueに設定しました。
MongoClientOptions.Builder options = MongoClientOptions.builder();
options.socketKeepAlive(true);
mongoClient = new MongoClient(mongoAddress, options.build());
これらの修正後、問題はなくなったようです!
クライアントとサーバー間、またはシャードクラスターのメンバー間でソケットエラーが発生するか、他の合理的な原因がないレプリカセットの場合は、TCPキープアライブ値(たとえば、tcp_keepalive_time
Linuxシステムでの値)。一般的なキープアライブ期間は7200秒(2時間)です。ただし、ディストリビューションやmacOSによって設定が異なる場合があります。
MongoDBの場合、キープアライブ期間が短く、120秒(2分)程度の結果が得られます。
Mongodbをインストールした場合は、Linuxでこのコマンドを実行するだけです。
Sudo sysctl -w net.ipv4.tcp_keepalive_time=120