Refit 结合 Polly 访问 ASP.NET Core Web API

前言

.NET Core 应用中访问 ASP.NET Core Web API 接口,常用的方式是使用 IHttpClientFactory 生成 HttpClient 实例,并通过结合 Polly 策略,以实现重试,熔断等机制。

Refit 介绍

Refit 是一个类型安全的 REST 开源库,可通过 Refit 更加简单安全地访问 Web API 接口。

首先,需要将 Web API 接口形式转换成 Interface 形式:

1
2
3
4
5
public interface IWeatherAPI
{
    [Get("/WeatherForecast")]
    Task<WeatherForecast[]> Get();
}

然后,通过 RestService 类生成 IWeatherAPI 的代理实现,通过代理直接调用 Web API 接口:

1
2
3
var weatherAPI = RestService.For<IWeatherAPI>("http://localhost:5000");

var weatherForeCasts = await weatherAPI.Get();

结合 Polly

1. 手工执行

可以通过 Policy.ExecuteAsync 方法执行 Web API 调用代码。下列代码实现了重试机制:

1
2
3
4
5
6
7
8
9
var weatherAPI = RestService.For<IWeatherAPI>("http://localhost:5000");

var weatherForeCasts = await Policy
    .Handle<HttpRequestException>(
        ex => ex.InnerException.Message.Any())
    .RetryAsync(10, async (exception, retryCount) =>
    {
        await Console.Out.WriteLineAsync(exception.Message);
    }).ExecuteAsync(async () => await weatherAPI.Get());

2. 依赖注入(推荐)

更加方便的方式是使用依赖注入的方式,自动将 Refit 和 Polly 结合起来。

首先,引用 Nuget 包:

1
2
3
Refit.HttpClientFactory

Microsoft.Extensions.Http.Polly

然后,修改 Startup.cs,注册 RefitClient,并增加了超时和重试策略:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
AsyncRetryPolicy<HttpResponseMessage> retryPolicy = HttpPolicyExtensions
    .HandleTransientHttpError()
    .Or<TimeoutRejectedException>() 
    .WaitAndRetryAsync(10, _ => TimeSpan.FromMilliseconds(5000));

AsyncTimeoutPolicy<HttpResponseMessage> timeoutPolicy = Policy
    .TimeoutAsync<HttpResponseMessage>(TimeSpan.FromMilliseconds(30000));

services.AddRefitClient<IWeatherAPI>()
        .ConfigureHttpClient(c => c.BaseAddress = new Uri("http://localhost:5000"))
    .AddPolicyHandler(retryPolicy)
    .AddPolicyHandler(timeoutPolicy); 

最后,直接使用 IWeatherAPI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
private readonly IWeatherAPI _weatherAPI;

public WeatherForecastController(IWeatherAPI weatherAPI)
{
    _weatherAPI = weatherAPI;
}

[HttpGet]
public async Task<IEnumerable<WeatherForecast>> Get()
{
    var weatherForeCasts = await _weatherAPI.Get();

    return weatherForeCasts;
}

结论

推荐使用依赖注入方式,简化 Refit 集成 Polly 的操作。

相关链接

https://mp.weixin.qq.com/s/h4LqyLx1VDdwlfS-46NAvg

0%