Spring Boot 2.0.6.RELEASE连接MongoDB频繁出现套接字异常求解
Spring Boot 2.0.6.RELEASE 下MongoDB套接字异常导致请求挂起的问题分析与解决
错误日志
2025-01-29 09:43:19.509 WARN 110974 --- [io-8081-exec-13] org.mongodb.driver.connection : 与4.213.70.7:27017的连接[connectionId{localValue:45, serverValue:1893}]发生套接字异常。所有到4.213.70.7:27017的连接将被关闭。 2025-01-29 09:43:19.510 INFO 110974 --- [io-8081-exec-13] org.mongodb.driver.connection : 关闭与4.213.70.7:27017的连接[connectionId{localValue:45, serverValue:1893}],原因是该连接引发了套接字异常。 org.springframework.data.mongodb.UncategorizedMongoDbException: 接收消息时发生异常;嵌套异常为com.mongodb.MongoSocketReadException: 接收消息时发生异常 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.execute(MongoTemplate.java:527) at org.springframework.data.mongodb.core.MongoTemplate.count(MongoTemplate.java:962) at org.springframework.data.mongodb.core.MongoTemplate.count(MongoTemplate.java:942) at com.cmcp.mongorepository.implementation.WhatsAppTemplateCustomRepositoryImpl.findByCriteria(WhatsAppTemplateCustomRepositoryImpl.java:58) at com.cmcp.mongorepository.implementation.WhatsAppTemplateCustomRepositoryImpl$$FastClassBySpringCGLIB$$327a5469.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) at com.cmcp.mongorepository.implementation.WhatsAppTemplateCustomRepositoryImpl$$EnhancerBySpringCGLIB$$c4a866df.findByCriteria(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:377) at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200) at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:641) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605) 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) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy156.findByCriteria(Unknown Source) at sun.reflect.GeneratedMethodAccessor456.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498)
问题原因分析
- 网络不稳定:应用服务器与MongoDB服务器之间存在网络丢包、延迟波动,或者防火墙/安全组拦截了连接,导致读取MongoDB响应时套接字中断。
- 连接池配置不合理:默认的连接池参数未设置超时时间,导致请求在等待MongoDB响应时无限挂起;或者闲置连接被MongoDB服务器主动关闭,但客户端未及时回收,使用失效连接时触发异常。
- MongoDB服务器负载过高:MongoDB实例CPU、内存占用过高,无法及时处理请求,或者连接数达到上限,主动关闭新连接/闲置连接。
- 驱动与MongoDB版本不兼容:Spring Boot 2.0.6默认依赖的MongoDB Java Driver(3.8.2)与目标MongoDB服务器版本存在兼容性问题,引发通信异常。
解决办法
1. 排查网络连通性
- 使用
ping、traceroute(Linux)或tracert(Windows)工具检测应用服务器到MongoDB服务器的网络状态,确认是否存在丢包、高延迟问题。 - 检查双方防火墙、安全组规则,确保应用服务器IP能正常访问MongoDB的27017端口,且无超时拦截策略。
2. 调整MongoDB连接池参数
在application.yml或application.properties中添加以下配置,避免连接挂起和失效连接问题:
spring: data: mongodb: uri: mongodb://4.213.70.7:27017/your_db socket-timeout: 30000 # 套接字读超时,单位毫秒 connect-timeout: 10000 # 连接超时,单位毫秒 max-connection-idle-time: 60000 # 闲置连接回收时间 max-connection-life-time: 3600000 # 连接最大存活时间 max-connections: 50 # 连接池最大连接数,根据业务量调整
如果是自定义MongoClient配置,需在配置类中通过SocketSettings和ConnectionPoolSettings设置对应参数。
3. 检查MongoDB服务器状态
- 登录MongoDB服务器,执行
db.serverStatus()查看CPU、内存、当前连接数等指标,确认是否存在负载过高情况。 - 查看MongoDB日志,检查是否有主动关闭连接的记录,必要时调整MongoDB的
net.socketTimeoutMS等参数。
4. 验证版本兼容性
Spring Boot 2.0.6.RELEASE默认依赖的spring-data-mongodb为2.0.11.RELEASE,对应MongoDB Java Driver 3.8.2。该驱动兼容MongoDB 3.2~4.0版本,如果你的MongoDB服务器是4.2及以上版本,建议:
- 升级Spring Boot到2.2.x及以上版本(对应驱动支持更高版本MongoDB);
- 或单独升级MongoDB Java Driver版本至3.12.x(需注意兼容性,避免API变更)。
5. 添加异常重试机制
使用Spring Retry框架对网络类异常进行重试,避免单次异常导致请求失败:
- 引入依赖:
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
- 在启动类添加
@EnableRetry注解; - 在Repository方法上添加重试注解:
@Retryable(value = {MongoSocketReadException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000)) public List<WhatsAppTemplate> findByCriteria(...) { // 业务逻辑 }
内容的提问来源于stack exchange,提问作者Vijay
相关产品推荐
相关产品推荐

