最近項目在運行過程,當一段時間沒有操作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文檔:傳送門