ASP.NET Core HttpClient 在连续多次请求后没有响应

问题描述 投票:0回答:1

在我的 ASP.NET Core Web API 托管服务中,我正在发出连续的 HTTP 客户端请求并使用任务同时执行 10 个请求。我遇到的问题是,一段时间后,服务挂起并停止记录任何消息。它甚至没有点击

StopAsync()
或在我记录步骤的服务的
executeAsync
方法中捕获异常。我在这里基本上一无所知。我觉得我确实在代码中处理了 http 客户端和 http 响应。

我的代码可能出了什么问题?

var users = GetUsersFromDB.ToList();

userBatches = users.Chunk(10).ToList(); 
        
var clientUserFacades = new List<ClientUserFacade>();

foreach (var UserBatch in UserBatches)
{
    logger.LogMessage(LogLevel.Information, hostedServiceType, "User batch index {UserBatchNo} - Processing started", UserBatches.IndexOf(UserBatch));

    try
    {
        var tasks = UserBatch.Select(User => clientUserSendHandler.SendUserInfoToClient(hostedServiceType, client, User, false));

        var results = await Task.WhenAll(tasks);

        clientUserFacades.AddRange(results.Where(p => p.IsResponseValid));
    }
    catch (Exception ex)
    {
        logger.LogMessage(LogLevel.Error, hostedServiceType, ex, "Batch processing task cancelled. Skipping the current batch. Trying after 10 seconds!");
        await Task.Delay(TimeSpan.FromSeconds(10), CancellationToken.None);
        continue;
    }

    logger.LogMessage(LogLevel.Information, hostedServiceType, "User batch index {UserBatchNo} client send completed", UserBatches.IndexOf(UserBatch));

    if (UserBatches.IndexOf(UserBatch) % 50 == 0 || UserBatches.ToList().IndexOf(UserBatch) == (UserBatches.Count - 1))
    {
        await clientUserWriteHandler.BulkUpdateClientUserAsync(hostedServiceType, client, clientUserFacades); // database update

        clientUserFacades.Clear();

        logger.LogMessage(LogLevel.Information, hostedServiceType, "User batches updated to database at batch index {UserBatchNo}", UserBatches.IndexOf(UserBatch));
    }
}

public async Task<ClientUserFacade> SendUserInfoToClient(HostedServiceType hostedServiceType, ClientFacade client, User User, bool includeResponseContent=false)
{
    var UserName = CommonHelper.RemoveWhiteSpaceAndSpecialCharacters(User.Name);
    var UserMobileNo = CommonHelper.RemoveNonNumericCharacters(User.MobileNo);
    
    var clientUser = new ClientUserFacade
           {
               ClientId = client.Id,
               UserId = User.Id
           };

    var param = new Dictionary<string, string>
               {
                   { "name", UserName },
                   { "phone", UserMobileNo }
               };
    
    try
    {
        var requestUrl = new Uri(QueryHelpers.AddQueryString(client.ApiUrl, param!));
    
        clientUser.LastRequestTimestamp = DateTime.Now.ToUniversalTime();

        using var httpClient = httpClientFactory.CreateClient();
        using var response = await httpClient.GetAsync(requestUrl);
    
        if (response.IsSuccessStatusCode)
        {
            var data = await response.Content.ReadAsStringAsync();
    
            if (includeResponseContent)
            {
                clientUser.ResponseContent = data;
            }
    
            var responseObject = JObject.Parse(data);
    
            ProcessClientReponse(clientUser, responseObject);
        }
        else
        {
            var logMessage = $"Request unsuccessful with response Code {(int)response.StatusCode} for client api request of User [{UserName} | {UserMobileNo}]";
    
            LogMessage(LogLevel.Error, hostedServiceType, null, logMessage);
    
            if (includeResponseContent && response is { })
            {
                clientUser.LastResponseCode = (int)response.StatusCode;
    
                var data = await response.Content.ReadAsStringAsync();
    
                clientUser.ResponseContent = data;
            }
        }
    }
    catch (Exception ex)
    {
        var logMessage = $"Unexpected error during client api request of User [{UserName} | {UserMobileNo}]";
    
        LogMessage(LogLevel.Critical, hostedServiceType, ex, logMessage);
    }
    
    return clientUser;
}
            

我确实尝试为下面的任务设置超时 - 但没有运气

var tasks = userBatch.Select(async User =>
                {
                    var sendTask = clientUserSendHandler.SendUserInfoToClient(hostedServiceType, client, User);
                    var timeoutTask = Task.Delay(TimeSpan.FromMinutes(5));

                    var completedTask = await Task.WhenAny(sendTask, timeoutTask);

                    if (completedTask == timeoutTask)
                    {
                        logger.LogMessage(LogLevel.Warning, hostedServiceType, $"Task for User [{User.Name} | {User.MobileNo}] cancelled after waiting for 5 mins");
                        return new ClientUserFacade { ClientId = client.Id, UserId = User.Id, IsResponseValid = false };
                    }

                    return await sendTask;
                });             
c# asp.net-core-webapi
1个回答
0
投票

你的

var results = await Task.WhenAll(tasks);

线等待所有任务结束。但如果任务太长而无法结束怎么办?您要么需要为

tasks
中的每个任务提供超时机制,要么不要等待所有任务完成。相反,等待
WhenAny
,查看
tasks
的大小,并添加您的设置/期望认为正确的尽可能多的新任务。

您还可以有一个单独的任务,它了解您执行的任务并定期检查超时。如果您选择这样,那么您可以使用

WhenAll

© www.soinside.com 2019 - 2024. All rights reserved.