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

发布于 2025-01-19 16:08:33 字数 4592 浏览 3 评论 0原文

ASP.NET核心Web API呼叫第三党API间歇性失败。

与Postman的负载测试时,以下例外会间歇性地提高。 “与状态代码500(内部服务器错误)的呼叫失败:post https://sample.com/apiendpoint。”

我尝试使用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 Type示例中给出的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;
        }
    }
}

我直接在服务层中尝试了

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()将连接保持在池中并避免创建新的。

我使用以下方法看到了其他一些示例,但是如何将其与ihttpclient -factory / flurl一起使用。

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

var client = new HttpClient(socketsHandler);

从Azure调用第三方API时,我如何确保它使用连接池并避免500错误。

ASP.Net Core Web API Call Thirds party API fails intermittently.

The following exception raises intermittently when load test with postman.
"Call failed with status code 500 (Internal Server Error): POST https://sample.com/apiendpoint."

I tried the Named/Typed with HttpClient/IHttpClientFactory approach and the problem continues.

How to make sure it uses connection pooling and not create new on one.
what is the right value for SetHandlerLifetime to keep the connection in the pool for future call to use.

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

The following code is in 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 = 
quot;{destinationUrl}";
            var authToken = Encoding.ASCII.GetBytes(
quot;{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;

        }
    }

I also tried HttpClient injection given in Microsoft type example.

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 = 
quot;{destinationUrl}";
        var authToken = Encoding.ASCII.GetBytes(
quot;{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;
        }
    }
}

I tried with Flurl directly in service layer

var endpoint = 
quot;{destinationUrl}";
var authToken = Encoding.ASCII.GetBytes(
quot;{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);

The above all 3 approach failed.

what is right value for .SetHandlerLifetime() to keep the connection in the pool and avoid creating new.

I saw some other example using the following approach but how to use this with IHttpClientFactory / Flurl.

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

var client = new HttpClient(socketsHandler);

How can I ensure it use connection pooling and avoid the 500 error when calling 3rd party API from Azure.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

转身以后 2025-01-26 16:08:33

当我使用httpclient时,我找到了解决方案。

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

这篇文章帮助我

尝试了几个值但最终选择此问题,因为没有错误。

I found solution when I use httpclient as given below.

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

This article helped me

Tried couple of value for SocketsHttpHandler but finally choose this since no error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文