1. 程式人生 > >記一次spring boot中MongoDB Prematurely reached end of stream的異常解決

記一次spring boot中MongoDB Prematurely reached end of stream的異常解決

  在spring boot專案中使用了mongodb,當一段時間沒有操作mongodb,下次操作mongodb時就會出現異常。異常如下:

org.springframework.data.mongodb.UncategorizedMongoDbException: Prematurely reached end of stream; nested exception is com.mongodb.MongoSocketReadException: Prematurely reached end of stream
        at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:
107) at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2146) at org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:1928) at org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:
1736) at org.springframework.data.mongodb.core.MongoTemplate.findOne(MongoTemplate.java:606) at org.springframework.data.mongodb.core.MongoTemplate.findOne(MongoTemplate.java:601) at com.lwli.service.impl.SessionServiceImpl.findOneSessionByCustomerIdAndStatus(SessionServiceImpl.java:
51) at java.lang.Thread.run(Thread.java:745) Caused by: com.mongodb.MongoSocketReadException: Prematurely reached end of stream at com.mongodb.connection.SocketStream.read(SocketStream.java:88) at com.mongodb.connection.InternalStreamConnection.receiveResponseBuffers(InternalStreamConnection.java:494) at com.mongodb.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:224) at com.mongodb.connection.UsageTrackingInternalConnection.receiveMessage(UsageTrackingInternalConnection.java:96) at com.mongodb.connection.DefaultConnectionPool$PooledConnection.receiveMessage(DefaultConnectionPool.java:440) at com.mongodb.connection.QueryProtocol.execute(QueryProtocol.java:289) at com.mongodb.connection.QueryProtocol.execute(QueryProtocol.java:54) at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:168) at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:289) at com.mongodb.connection.DefaultServerConnection.query(DefaultServerConnection.java:212) at com.mongodb.operation.FindOperation$1.call(FindOperation.java:525) at com.mongodb.operation.FindOperation$1.call(FindOperation.java:510) at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:435) at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:408) at com.mongodb.operation.FindOperation.execute(FindOperation.java:510) at com.mongodb.operation.FindOperation.execute(FindOperation.java:81) at com.mongodb.Mongo.execute(Mongo.java:836) at com.mongodb.Mongo$2.execute(Mongo.java:823) at com.mongodb.DBCursor.initializeCursor(DBCursor.java:870) at com.mongodb.DBCursor.hasNext(DBCursor.java:142) at com.mongodb.DBCursor.one(DBCursor.java:679) at com.mongodb.DBCollection.findOne(DBCollection.java:833) at com.mongodb.DBCollection.findOne(DBCollection.java:796) at com.mongodb.DBCollection.findOne(DBCollection.java:743) at org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2197) at org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2181) at org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:1925) ... 12 more

  網上搜了下,這個問題原因很多,主要的原因可能有連線超時,讀寫超時等,按照別人的提示,設定了

socketKeepAlive = true;
socketTimeout = 30000;

  然而並沒有效果,超過一段時間再次訪問mongdb時,任然出現異常。在google搜尋時,發現一篇文章https://studio3t.com/whats-new/how-to-prevent-your-connection-from-dropping-with-hosted-mongodb-instances/,上面提到了一點,當連線閒置一段時間,由於防火牆或者負載均衡的原因,導致連線被關閉,而客戶端並不知道,當客戶端繼續使用這個關閉的連線進行讀寫時就會出錯。

  解決辦法就是設定連線閒置時間,當超過這個閒置時間客戶端主動關閉連線,下次使用時重新建立連線,這樣可以有效避免連線失效的問題。

  在spring boot中配置MongoClientOptions的bean。例如將最大閒置時間設為6000ms。

@Configuration
public class WechatMpConfiguration {

    @Bean
    public MongoClientOptions mongoOptions() {
        return MongoClientOptions.builder().maxConnectionIdleTime(6000).build();
    }
}

  通過上面的設定後,後面沒有再出現Prematurely reached end of stream異常了。