Spring Boot对接MongoDB时数据库宕机连接异常的处理方案咨询
方案1:基于MongoDB Java驱动的连接事件监听实现
MongoDB官方Java驱动本身会推送连接池的状态变更事件,不需要主动轮询,你可以直接监听对应异常事件触发应用关停,无额外数据库请求开销。
步骤如下:
- 自定义连接监听器,继承
ConnectionPoolListener,重写连接异常相关的回调方法:
public class MongoConnectionFailureListener implements ConnectionPoolListener { private final ConfigurableApplicationContext applicationContext; // 幂等控制,避免重复触发关停 private final AtomicBoolean isShuttingDown = new AtomicBoolean(false); public MongoConnectionFailureListener(ConfigurableApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Override public void onConnectionCheckOutFailed(ConnectionPoolCheckOutFailedEvent event) { if (isShuttingDown.get()) return; // 匹配你需要处理的三类异常 Throwable cause = event.getCause(); if (cause instanceof MongoSocketException || cause instanceof MongoTimeoutException || cause instanceof MongoConnectionException) { isShuttingDown.set(true); // 触发应用优雅关停 applicationContext.close(); } } // 可选:监听连接创建失败事件,覆盖启动阶段就连接失败的场景 @Override public void onConnectionCreatedFailed(ConnectionPoolCreatedFailedEvent event) { if (isShuttingDown.get()) return; Throwable cause = event.getCause(); if (cause instanceof MongoSocketException || cause instanceof MongoTimeoutException || cause instanceof MongoConnectionException) { isShuttingDown.set(true); applicationContext.close(); } } }
- 将监听器注册到MongoDB客户端配置中:
@Configuration public class MongoConfig { @Bean public MongoClientSettingsBuilderCustomizer mongoClientSettingsBuilderCustomizer(ConfigurableApplicationContext applicationContext) { return builder -> builder.applyConnectionPoolSettings( poolBuilder -> poolBuilder.addConnectionPoolListener(new MongoConnectionFailureListener(applicationContext)) ); } }
这个方案完全依赖驱动的被动事件推送,不会产生任何主动查询请求,多实例部署也不会给MongoDB带来额外负载。
方案2:基于Spring Data MongoDB的异常切面拦截
如果你的业务逻辑本身就会有MongoDB操作,你可以通过切面拦截所有MongoTemplate方法调用,捕获到指定异常后触发关停,只有当业务实际调用MongoDB时才会触发检测,无额外主动请求:
@Aspect @Component public class MongoExceptionInterceptor { private final ConfigurableApplicationContext applicationContext; private final AtomicBoolean isShuttingDown = new AtomicBoolean(false); public MongoExceptionInterceptor(ConfigurableApplicationContext applicationContext) { this.applicationContext = applicationContext; } @AfterThrowing(pointcut = "execution(* org.springframework.data.mongodb.core.MongoTemplate.*(..))", throwing = "ex") public void handleMongoException(Exception ex) { if (isShuttingDown.get()) return; // 递归判断异常根因是否为目标异常 Throwable rootCause = NestedExceptionUtils.getRootCause(ex); if (rootCause instanceof MongoSocketException || rootCause instanceof MongoTimeoutException || rootCause instanceof MongoConnectionException) { isShuttingDown.set(true); applicationContext.close(); } } }
提示:你可以根据自己的业务场景选择方案,如果要覆盖所有连接异常场景优先选方案1,如果只需要处理业务请求阶段的连接异常可以选方案2。
内容的提问来源于stack exchange,提问作者prostý člověk
相关产品推荐
相关产品推荐

