ASP.NET Core 5.0 Web API 部署在 App 服务调用第三方 API 间歇性失败并引发 500(内部服务器错误)

ASP.NET Core 5.0 Web API deployed in App service call third party API fails intermittently and raise 500 (Internal Server Error)

ASP.Net Core Web API 调用第三方 API 间歇性失败。

使用邮递员进行负载测试时,间歇性地出现以下异常。 “调用失败,状态代码为 500(内部服务器错误):POST https://sample.com/apiendpoint."

我尝试了 Named/Typed 和 HttpClient/IHttpClientFactory 方法,但问题仍然存在。

如何确保它使用连接池而不是在一个上创建新的。 SetHandlerLifetime 的正确值是多少,以便将连接保留在池中以供将来调用使用。

    services.AddHttpClient<IRestService, RestServiceOne>()
    .SetHandlerLifetime(TimeSpan.FromMinutes(5))  //Set lifetime to five minutes
    .AddPolicyHandler(GetRetryPolicy());

以下代码在RestServiceOne.cs

   public class RestServiceOne : IRestService
    {
        private readonly IHttpClientFactory _httpClientFactory;
        public RestServiceOne(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }
        public async Task<HttpResponseMessage> GetDataAsync(string destinationUrl, string user,
            string password, string requestXml, string orderNumber, CancellationToken cancellationToken)
        {
            var endpoint = $"{destinationUrl}";
            var authToken = Encoding.ASCII.GetBytes($"{user}:{password}");
            var data = new StringContent(requestXml, Encoding.UTF8, "text/xml");
            var httpRequestMessage = new HttpRequestMessage(
                HttpMethod.Post,
                endpoint)
            {
                Headers =
            {
                { "Accept", "application/vnd.github.v3+json" },
                { "User-Agent", "HttpRequestsConsoleSample" }
            }
            };
            httpRequestMessage.Content = data;
            var httpClient = _httpClientFactory.CreateClient();

            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
                    Convert.ToBase64String(authToken));
            var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage);
            return httpResponseMessage;

        }
    }

我还尝试了 Microsoft 类型示例中给出的 HttpClient 注入。

public class RestService 
{
    private readonly HttpClient _httpClient;
    public RestService(HttpClient httpClient)
    {
        _httpClient = httpClient;
        try
        {
            _httpClient.BaseAddress = new Uri("https://testxx.com/test");
            // GitHub API versioning
            _httpClient.DefaultRequestHeaders.Add("Accept",
                "application/vnd.github.v3+json");
            // GitHub requires a user-agent
            _httpClient.DefaultRequestHeaders.Add("User-Agent",
                "HttpClientFactory-Sample");
        }
        catch(Exception ex)
        {

        }
    }

    public async Task<HttpResponseMessage> GetDataAsync(string destinationUrl, string user,
        string password, string requestXml, string orderNumber, CancellationToken cancellationToken)
    {
        var endpoint = $"{destinationUrl}";
        var authToken = Encoding.ASCII.GetBytes($"{user}:{password}");
        _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
                Convert.ToBase64String(authToken));
        var data = new StringContent(requestXml, Encoding.UTF8, "text/xml");
        try
        {
            var response = await _httpClient.PostAsync(endpoint, data);
            return response;
        }
        catch(Exception ex)
        {
            throw;
        }
    }
}

我直接在服务层尝试使用 Flurl

var endpoint = $"{destinationUrl}";
var authToken = Encoding.ASCII.GetBytes($"{user}:{password}");
var data = new StringContent(requestXml, Encoding.UTF8, "text/xml");
try
{

var response = await endpoint
    .WithHeader("Content-Type", "text/xml")
    .WithHeader("app-bu-id", "SANIDERMMEDICAL")
    .WithHeader("Authorization", new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken)))
    .PostAsync(data);

以上3种方法都失败了。

.SetHandlerLifetime() 的正确值是多少,以将连接保留在池中并避免创建新连接。

我看到了一些使用以下方法的其他示例,但如何将其与 IHttpClientFactory / Flurl 一起使用。

var socketsHandler = new SocketsHttpHandler
{
    PooledConnectionLifetime = TimeSpan.FromMinutes(10),
    PooledConnectionIdleTimeout = TimeSpan.FromMinutes(5),
    MaxConnectionsPerServer = 10
};

var client = new HttpClient(socketsHandler);

如何确保它使用连接池并避免在从 Azure 调用第 3 方 API 时出现 500 错误。

我在使用 httpclient 时找到了解决方案,如下所示。

    private static readonly HttpClient httpClient = new HttpClient(new SocketsHttpHandler
    {
        PooledConnectionLifetime = TimeSpan.FromSeconds(60),
        PooledConnectionIdleTimeout = TimeSpan.FromSeconds(20),
        MaxConnectionsPerServer = 10
    });

This article helped me

为 SocketsHttpHandler 尝试了几个值,但由于没有错误,最终选择了这个。