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文档:传送门

posted @ 2020-10-21 21:34  蒲公英的狂想  阅读(2612)  评论(2编辑  收藏  举报