Polly .Net配合IHostApplicationLifetime实现应用优雅关停的异常问题
问题根因
IHostApplicationLifetime.Stop()是异步触发应用关停流程的方法,调用后不会立即终止当前线程的执行逻辑,关停信号需要传递到各个执行链路才会生效- 你把关停逻辑放到了Polly的异常过滤器
Handle<DatabaseException>(ex => ...)中,且方法返回了true,Polly会判定该异常需要执行重试策略,会直接进入重试等待流程,不会响应尚未完成的关停信号
修复方案
1. 不要在Polly的异常过滤器中编写业务逻辑
异常过滤器仅用来判断异常是否需要被策略处理,关停逻辑移到重试回调或单独的异常捕获分支,同时绑定应用关停的CancellationToken中断执行流:
private IHostApplicationLifetime _applicationLifetime; // 取IHostApplicationLifetime自带的关停信号Token private CancellationToken _stoppingToken => _applicationLifetime.ApplicationStopping; public void CreatePolicy() { var policy = Policy // 过滤器仅做异常类型判断 .Handle<DatabaseException>() .WaitAndRetryForever( retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (exception, timespan) => { // 遇到DatabaseException直接触发关停 if (exception is DatabaseException) { _applicationLifetime.Stop(); } HandleRetry(exception, timespan, _stoppingToken); }) // 绑定关停token,token触发后会直接终止重试等待和策略执行 .WithCancellation(_stoppingToken); }
2. 主动中断当前执行流
如果需要完全避免后续任何逻辑执行,可在触发关停后主动抛出取消异常,直接终止当前执行链路:
public bool HandleDatabaseException(Exception ex) { _applicationLifetime.Stop(); // 抛出取消异常,直接中断所有后续执行,不会再进入Polly重试逻辑 throw new OperationCanceledException("数据库异常触发应用关停", ex, _stoppingToken); }
3. 执行策略时传入关停token
所有通过该Polly策略执行业务代码的位置,都要传入应用关停的CancellationToken,确保正在运行的业务逻辑可以响应关停信号:
// 示例执行逻辑 policy.Execute(token => { // 你的数据库操作等业务逻辑 }, _stoppingToken);
内容的提问来源于stack exchange,提问作者DrExpresso
相关产品推荐
相关产品推荐

