MongoDB случайное исключение - PullRequest
1 голос
/ 15 января 2020

Мы используем MongoDB v4.2 в IBM Cloud поверх Реактивного драйвера MongoDB v1.11. В настоящее время мы случайно сталкиваемся со следующим исключением, обычно после некоторого периода бездействия приложения:

com.mongodb.MongoSocketWriteException: Exception sending message
    at com.mongodb.internal.connection.InternalStreamConnection.translateWriteException(InternalStreamConnection.java:541)
    at com.mongodb.internal.connection.InternalStreamConnection.access$1100(InternalStreamConnection.java:74)
    at com.mongodb.internal.connection.InternalStreamConnection$3.failed(InternalStreamConnection.java:470)
    at com.mongodb.internal.connection.AsynchronousChannelStream$1.failed(AsynchronousChannelStream.java:97)
    at com.mongodb.internal.connection.AsynchronousChannelStream$2.failed(AsynchronousChannelStream.java:173)
    at com.mongodb.internal.connection.AsynchronousChannelStream$AsyncWritableByteChannelAdapter$WriteCompletionHandler.failed(AsynchronousChannelStream.java:198)
    at com.mongodb.internal.connection.tlschannel.async.AsynchronousTlsChannel$10$1.run(AsynchronousTlsChannel.java:269)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: Connection reset by peer
    at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
    at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
    at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
    at sun.nio.ch.IOUtil.write(IOUtil.java:65)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
    at com.mongodb.internal.connection.tlschannel.impl.TlsChannelImpl.writeToChannel(TlsChannelImpl.java:479)
    at com.mongodb.internal.connection.tlschannel.impl.TlsChannelImpl.writeToChannel(TlsChannelImpl.java:464)
    at com.mongodb.internal.connection.tlschannel.impl.TlsChannelImpl.wrapAndWrite(TlsChannelImpl.java:403)
    at com.mongodb.internal.connection.tlschannel.impl.TlsChannelImpl.write(TlsChannelImpl.java:391)
    at com.mongodb.internal.connection.tlschannel.ClientTlsChannel.write(ClientTlsChannel.java:181)
    at com.mongodb.internal.connection.tlschannel.async.AsynchronousTlsChannelGroup.writeHandlingTasks(AsynchronousTlsChannelGroup.java:553)
    at com.mongodb.internal.connection.tlschannel.async.AsynchronousTlsChannelGroup.doWrite(AsynchronousTlsChannelGroup.java:501)
    at com.mongodb.internal.connection.tlschannel.async.AsynchronousTlsChannelGroup.access$400(AsynchronousTlsChannelGroup.java:67)
    at com.mongodb.internal.connection.tlschannel.async.AsynchronousTlsChannelGroup$6.run(AsynchronousTlsChannelGroup.java:459)
    ... 3 more

Из того, что я прочитал, и из того, что JavaDo c дает для драйвера - keepAlive параметр по умолчанию должен быть установлен на true. Но чтобы быть в безопасности - мы устанавливаем это явно:

MongoClientSettings settings = MongoClientSettings.builder()
    .applyConnectionString(new ConnectionString("xxx")))
    .applyToSocketSettings(builder -> builder.keepAlive(true))
    .build();
MongoClient client = MongoClients.create(settings);

Но это, похоже, не решает проблему. Это происходит случайно и редко. Любая помощь очень ценится

1 Ответ

0 голосов
/ 19 апреля 2020

Установка maxIdleTimeMS является ключевым моментом здесь.

Если вы используете AbstractMongoClientConfiguration, используйте приведенный ниже код, чтобы установить maxIdleTimeMS для MongoClientSettings

SSLContext.setDefault(sslContext);
String connectionTemplateString = "mongodb://%s:%s@%s/%s?maxIdleTimeMS=%s";
String clusterEndpoint = dbHost + ":" + port;
String maxIdleTimeInMs = "x";
String connectionString = String.format(connectionTemplateString, dbUser, dbPassword, clusterEndpoint,dbName, maxIdleTimeInMs);
ConnectionString connString = new ConnectionString(connectionString);
mongoClientSettings = MongoClientSettings.builder().applyConnectionString(connString)
                    .applyToSslSettings(builder -> {
                        builder.enabled(true);
                        builder.invalidHostNameAllowed(true);
                        builder.context(sslContext);
                    }).build();

Если вы используете сейчас неактивную AbstractMongoConfiguration, используйте приведенный ниже код для установки maxConnectionIdleTime для MongoClientOptions *

mongoClientOptions.maxConnectionIdleTime(x);

Эти изменения обеспечат, что после заданных вами x миллисекунд открытое соединение будет закрыто, а при поступлении нового запроса в вашу службу будет открыто новое соединение

Примеры журналов :

  1. Через x мс

Закрытое соединение [connectionId {localValue: 3}] с хостом: 27017, поскольку оно превышает максимально допустимое время простоя.

При поступлении нового запроса

Открытое соединение [connectionId {localValue: 4}] к хосту: 27017

...