MONGODB01 - Prematurely reached end of stream 錯誤定位及修復


最近項目在運行過程,當一段時間沒有操作mongo,再次訪問報錯,如下

 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:132)
	at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2607)
	at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:2474)
	at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:2282)
	at org.springframework.data.mongodb.core.ExecutableFindOperationSupport$ExecutableFindSupport.doFind(ExecutableFindOperationSupport.java:213)
	at org.springframework.data.mongodb.core.ExecutableFindOperationSupport$ExecutableFindSupport.all(ExecutableFindOperationSupport.java:169)
	at org.springframework.data.mongodb.repository.query.AbstractMongoQuery.lambda$getExecution$1(AbstractMongoQuery.java:113)
	at org.springframework.data.mongodb.repository.query.AbstractMongoQuery.execute(AbstractMongoQuery.java:97)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:602)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:590)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)

原因

mongo沒有配置空閑連接時間,而spring boot 默認的空閑連接時間為0,即永不超時。當連接閑置一段時間,由於防火牆或者負載均衡的原因,導致連接被關閉,而客戶端並不知道,當客戶端繼續使用這個關閉的連接進行讀寫時就會出錯。

解決方式

方式一:寫一個配置類設置空閑連接時間

@Configuration
public class MongoCongig {
 
    @Bean
    public MongoClientOptions mongoOptions() {
        //默認空置一個小時重置一次
        return MongoClientOptions.builder().maxConnectionIdleTime(3600000).build();
	}
}

方式二:如果使用mongo 3.x 配置

spring.data.mongodb.uri=mongodb://username:password@xx.mongodb.rds.aliyuncs.com:3717/test?maxIdleTimeMS=3600000

方式三:引入spring-boot-starter-mongodb-plus

POM文件

<dependency>
    <groupId>com.spring4all</groupId>
    <artifactId>mongodb-plus-spring-boot-starter</artifactId>
    <version>1.0.0.RELEASE</version>
</dependency>

配置

spring:
  data:
    mongodb:
      option:
        max-connection-idle-time: 3600000

在啟動類加上@EnableMongoPlus注解

@EnableMongoPlus
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

PS:此包是對官方spring boot starter對mongodb支持的擴展,提供更多配置屬性,比如:連接數的配置等,GITHUB地址

支持的配置屬性如下:

spring.data.mongodb.option.min-connection-per-host=0
spring.data.mongodb.option.max-connection-per-host=100
spring.data.mongodb.option.threads-allowed-to-block-for-connection-multiplier=5
spring.data.mongodb.option.server-selection-timeout=30000
spring.data.mongodb.option.max-wait-time=120000
spring.data.mongodb.option.max-connection-idle-time=0
spring.data.mongodb.option.max-connection-life-time=0
spring.data.mongodb.option.connect-timeout=10000
spring.data.mongodb.option.socket-timeout=0

spring.data.mongodb.option.socket-keep-alive=false
spring.data.mongodb.option.ssl-enabled=false
spring.data.mongodb.option.ssl-invalid-host-name-allowed=false
spring.data.mongodb.option.always-use-m-beans=false

spring.data.mongodb.option.heartbeat-socket-timeout=20000
spring.data.mongodb.option.heartbeat-connect-timeout=20000
spring.data.mongodb.option.min-heartbeat-frequency=500
spring.data.mongodb.option.heartbeat-frequency=10000
spring.data.mongodb.option.local-threshold=15

以上均為默認配置

補充MongoDB連接Options(3.6.X)

mongo 3.6.x 配置:

  • uri: mongodb://[username:password@]host1[:port1][,hostN[:portN]]][/[database[.collection]][?options]]

  • options屬性

常見配置整理如下:

屬性 說明
authSource 數據庫名 開啟認證的database
authMechanism SCRAM-SHA-1
MONGODB-CR (Deprecated in MongoDB 3.6)
MONGODB-X509
GSSAPI (Kerberos)
PLAIN (LDAP SASL)
認證方式
ssl true或false 是否采用ssl
connectTimeoutMS 任務毫秒數 連接超時時間
maxIdleTimeMS 毫秒數,默認0 最大空閑時間
maxLifeTimeMS 毫秒數,默認0 最大存活時間
maxPoolSize 數量,默認100 最大連接數
minPoolSize 數量,默認0 最小連接數
waitQueueMultiple 數量,默認5 每個連接的隊列等待數量
waitQueueTimeoutMS 毫秒數,默認以驅動為准 線程最長等待時間
slaveOk true或false 是否從slave讀取數據
readPreference primary (Default)
primaryPreferred
secondary
secondaryPreferred
nearest
讀取偏好,會覆蓋slaveOK

官方options文檔:傳送門


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM