我对在 .net 中使用 http 客户端进行 RESTful 消费不太熟悉,并且在轮询外部 API 时无法理解如何使用 retry-after 标头。
这是我目前必须投票的内容:
HttpResponseMessage result = null;
var success = false;
var maxAttempts = 7;
var attempts = 0;
using (var client = new HttpClient())
{
do
{
var url = "https://xxxxxxxxxxxxxxx";
result = await client.GetAsync(url);
attempts++;
if(result.StatusCode == HttpStatusCode.OK || attempts == maxAttempts)
success = true;
}
while (!success);
}
return result;
如您所见,我不断轮询端点,直到得到 OK 响应或达到最大尝试次数(以停止连续循环)。
如何使用响应中的 retry-after 标头来指示循环中每个调用之间等待的时间?
我只是不知道如何将其应用到我的情况。
谢谢,
HttpClient
旨在每个应用程序实例化一次,而不是每次使用
private static HttpClient client = new HttpClient();
方法(更新了 HTTP 主机标头的用法)
private static async Task<string> GetDataWithPollingAsync(string url, int maxAttempts, string host = null)
{
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url))
{
if (host?.Length > 0) request.Headers.Host = host;
for (int attempt = 0; attempt < maxAttempts; attempt++)
{
TimeSpan delay = default;
using (HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
delay = response.Headers.RetryAfter.Delta ?? TimeSpan.FromSeconds(1);
}
await Task.Delay(delay);
}
}
throw new Exception("Failed to get data from server");
}
使用方法
try
{
string result = await GetDataWithPollingAsync("http://some.url", 7, "www.example.com");
// received
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
// failed
}
您不得为每个应用程序创建一个 HttpClient。您也不应该在每次要使用 HttpClient 时创建它。这是第一个问题。
那么如何使用HttpClient呢?只需使用 HttpClientFactory 即可。在这篇 MS 文章中,您将找到原因:https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
简单来说,HttpClient 和 DNS 服务器存在问题。每个应用程序拥有一个 HttpClient 可能会使您的应用程序不知道 DNS 更改。为每次使用创建 HttpClient 可能会使您的应用程序甚至系统不稳定。只是因为套接字耗尽问题。因此,请查看我链接的这篇文章。
就您的问题而言,您可以使用此处描述的 Polly 策略:https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-http-调用重试指数退避polly