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