NServiceBus中如何拦截MSSQL Server不可用导致的应用故障并在退出前操作?
NServiceBus 故障拦截与退出前自定义操作实现方案
基于你对接远程MSSQL的NServiceBus应用频繁故障、需要在退出前触发自定义操作的需求,完全可以通过NServiceBus内置的扩展钩子实现,不需要额外引入全局异常拦截逻辑,核心实现点如下:
核心匹配场景的钩子:临界错误处理
当NServiceBus检测到自身依赖(包括对接的MSSQL持久化、传输连接)持续故障到无法维持正常运行时,会自动触发内置的临界错误流程——也就是你遇到的“应用运行一段时间后非预期终止”对应的流程,这个流程提供了公开的回调入口,会在endpoint正式停止、进程退出前执行自定义逻辑。
你可以在端点初始化配置阶段注册这个回调,示例代码如下:
// 在EndpointConfiguration初始化阶段配置临界错误处理 endpointConfig.DefineCriticalErrorAction(async (criticalErrorContext, ct) => { // 这里直接写入退出前要执行的逻辑:发送告警邮件、采集故障快照、写本地故障日志 await SendAlertMail( title: "NServiceBus端点因数据库连接故障即将退出", content: $"故障详情:{criticalErrorContext.Error},发生UTC时间:{DateTime.UtcNow}", ct: ct ); // 自定义逻辑执行完成后,必须显式触发端点停止,否则进程会进入挂起状态 await criticalErrorContext.Stop(ct); });
前置告警:普通消息处理的异常拦截
针对还没到临界错误等级、仅单条消息处理时出现MSSQL连接异常的场景,可以注册NServiceBus的错误通知,提前统计异常频率触发预警,不用等到进程退出再告警:
- 首先在端点配置阶段开启错误通知能力,该能力为核心库内置能力,无需额外安装第三方包:
endpointConfig.EnableErrorNotifications(); - 在端点启动完成后订阅错误事件,做异常统计与阈值告警:
var busNotifications = endpointInstance.Notifications(); busNotifications.Errors.MessageFailed += async (_, errorArgs) => { // 识别连接类的SQL异常,累计故障次数 if (errorArgs.Exception is SqlException sqlEx && IsRemoteDatabaseConnectionIssue(sqlEx)) { _dbConnectionFailureCounter.Increment(); // 累计故障达到阈值时提前触发告警 if (_dbConnectionFailureCounter.CurrentValue >= 5) { await SendWarningMail("远程MSSQL连接异常率过高,端点即将触发自动退出"); } } };
上述判断SQL连接异常的逻辑,可直接匹配
SqlException中对应的连接类错误码(比如超时类的-2错误、无法建立连接的53错误),精准识别远程数据库不可达的场景。
落地注意事项
- 所有在退出前执行的自定义逻辑必须设置严格的超时限制,比如给发送邮件的逻辑设置10秒超时,避免因为邮件服务本身故障导致进程无法正常退出,进入僵死状态。
- 临界错误回调中不要尝试重新恢复数据库连接,NServiceBus的临界错误触发本身已经是多次内置恢复失败后的结果,重复重试只会拉长故障等待时间,没有实际价值。
- 自托管的Worker Service/控制台应用可以补充
AppDomain.CurrentDomain.ProcessExit事件作为兜底,万一NServiceBus的钩子因为未捕获的异常没触发,也能在进程最终退出的窗口期完成一次极简告警,注意这个事件的执行窗口极短,不要在里面执行长耗时IO操作。
内容的提问来源于stack exchange,提问作者user306080
相关产品推荐
相关产品推荐

