iis 当客户端挂起时,Asp.NetCoreWebAPI返回结果

vkc1a9a2  于 2022-11-12  发布在  .NET
关注(0)|答案(1)|浏览(145)

我有一个简单的ASP.NET核心Web API,运行在IIS 10和Windows 10上。Web API调用另一个API并返回结果。下面是它的代码的简化版本,但我尽量保留最重要的部分。

[ApiController]
[Produces("application/json")]
public class SomeController
{
     private async Task<ApiOutput> RunApiForClientAsync(ApiInput input)
    {
        try
        {
            //create a httpclient with a lot of configuration
            var response = await client.SendAsync(request);
            var content = await response.Content.ReadAsStringAsync();

            return new ApiOutput
            {
                Data = content,
                Error = null,
                StatusCode = 200,
                Input = input,
            };
        }
        catch(Exception ex)
        {
            return new ApiOutput
            {
                Data = null,
                Error = new ApiError("Error Getting the Result from the Server", ex.Message),
                StatusCode = 400,
                Input = input,
            };
        }
    }

    private async Task<List<ApiOutput>> RunApiCallsAsync(string requestId, IEnumerable<ApiInput> items)
    {
        var result = new List<ApiOutput>();
        var tasks = new List<Task<ApiOutput>>();

        foreach(var item in items)
        {
            tasks.Add(RunApiForAsync(item));
        }

        var taskResults = await Task.WhenAll(tasks);
        result.AddRange(taskResults);
        return result;
    }

    [HttpPost]
    [Route("rest/multiple")]
    public async Task<IActionResult> PostMultiple(ApiInput[] models, string? requestId)
    {
        _logger.LogInformation(ApiLoggingEvents.PostMultiple, "Request received with ID {requestId}", requestId);
        var result = await RunApiCallsAsync(requestId, models);

        try
        {
            _logger.LogDebug(ApiLoggingEvents.PostMultiple, "Request ID {requestId} Generating JSONs.", requestId);

            var resultJson = GetJson(result);
            await SaveResultAsync(resultJson, requestId);

            _logger.LogDebug(ApiLoggingEvents.PostMultiple, "Request ID {requestId} Everything is finished. Returning....", requestId);
            return Content(resultJson, "application/json");
        }
        catch (Exception ex)
        {
            _logger.LogDebug(ApiLoggingEvents.PostMultiple, "Exception while returning {requestId}, message {msg}", requestId, ex.Message);
            throw new Exception("Try again");
        }
    }
}

每隔一段时间,调用者都会向API发送请求,但永远不会得到结果。但是,当我阅读日志时,我看到请求的最后一行包含文本“Everything is finished. Returning”,这意味着一切都成功了。此外,输出的JSON保存在服务器的本地驱动器上(await SaveResultAsync(resultJson, requestId);调用也成功了)。
我应该提到的是,这些类型的请求需要很长时间才能响应。通常大约10分钟。是否需要在应用程序或IIS上更改某个设置?
我尝试使用以下方法,但它不适用于进程内模型:

builder.WebHost.UseKestrel(o =>
{
    o.Limits.MaxConcurrentConnections = 100;
    o.Limits.KeepAliveTimeout = TimeSpan.FromMilliseconds(timeout);
    o.Limits.MaxRequestBodySize = int.MaxValue;
    o.Limits.MaxResponseBufferSize = int.MaxValue;
});

注:

requestId是每个请求的唯一GUID,它帮助我跟踪日志文件中的每个请求,并查看它是否成功,以及它是否创建了输出文件。

更新:

经过进一步的调查,运行时间超过5分钟的请求似乎失败了。你知道与这个数字有关的是什么吗?

更新2:

我创建了一个非常简单的端点,它等待指定的秒数,然后返回一个简单的消息:

[HttpPost]
[Route("rest/testpost")]
public IActionResult TestPost(int delay)
{
    _logger.LogInformation(1, "Delay for {delay} started.", delay);
    Thread.Sleep(delay * 1000);
    _logger.LogInformation(1, "Delay for {delay} ended.", delay);
    return Ok($"Delay for {delay} worked.");
}

然后,我将requestTimeout="00:20:00"添加到web.config文件中,只是为了确认一下。
有趣的是,对于像310秒这样的值,有时我得到了结果,但有时我没有。(Postman仍然挂起)

rqqzpn5f

rqqzpn5f1#

在您的web.config中添加以下内容(该值以秒为单位--因此这将允许运行时间最长为20分钟):

<system.web>
    <httpRuntime executionTimeout="1200" />
</system.web>

以下是该文档的链接:https://learn.microsoft.com/en-us/dotnet/api/system.web.configuration.httpruntimesection.executiontimeout?view=netframework-4.8

相关问题