首页 > 解决方案 > 使用 await Task.WhenAll(tasks) 运行并行 Web 服务调用,对某些请求返回 202

问题描述

这是我的测试方法

    public async Task<string> Test(int counter)
    {
        var token = "xxxx";
        var requestData = new HttpRequestMessage(HttpMethod.Get, "URL"); 
        requestData.Headers.TryAddWithoutValidation("Authorization", String.Format("Bearer {0}", token));
        var client = _clientFactory.CreateClient();
        var results = await client.SendAsync(requestData);
        var json = await results.Content.ReadAsStringAsync();
        return $"Task {counter} {results.StatusCode};";

    }

在这里,我将计数器作为输入来跟踪任务编号并返回与任务编号关联的状态代码。

_clientFactory

来自像这样在 Startup.cs 中的依赖注入

services.AddHttpClient();

在我的课上

    IHttpClientFactory _clientFactory;
    public TestController(IHttpClientFactory clientFactory, IHttpContextAccessor httpContextAccessor)
    {
        _clientFactory = clientFactory;
        _httpContextAccessor = httpContextAccessor;
    }

现在我像这样调用测试方法 x 次

            List<Task<string>> tasks = new List<Task<string>>();
            int i = 0;
            while (i < 40)
            {
                var task = Test(i);
                tasks.Add(task);
                i++;
            }
            await Task.WhenAll(tasks);
            var ret = String.Empty;
            foreach (var task in tasks)
            {

                ret += task.Result;
            }

            return Ok(ret);

我正在并行运行测试方法 40 次并将所有任务的返回连接起来。这运行良好,这意味着当我从 Visual Studio 本地运行时,所有任务的状态都是 200 Ok,这是预期的结果。问题是当我部署在 IIS 上托管的服务器上时,50% 的任务我得到 200 OK,而其他 50% 的任务我得到 202 Accepted。这个问题是间歇性的,当并行次数变大时似乎会变得更糟。对于 10 次并行调用,它始终在服务器中成功运行。我在具有 40 个并行线程的不同工具 JMeter 中运行了相同的 api,每个请求都是 200 好的,这让我相信它不是发送 202 的被调用 api。我是否做错了每次都没有得到 200 好的?这是 await Task.Whenall 的正常行为吗?我使用 DotNet Core 2.2 作为 SDK。

 public class TestsController : ControllerBase
{
    private readonly IUnitOfWork<ResponseModel> _uow;
    private IConfiguration _configuration;

    IHttpClientFactory _clientFactory;
    IHttpContextAccessor _httpContextAccessor;



    public TestsController(IUnitOfWork<ResponseModel> uow, IConfiguration configuration, IHttpClientFactory clientFactory, IHttpContextAccessor httpContextAccessor)
    {
        _uow = uow;
        _clientFactory = clientFactory;
        _httpContextAccessor = httpContextAccessor;
        _configuration = configuration;
    }

    [HttpGet()]
    [TypeFilter(typeof(TrackPerformanceFilter))]
    public async Task<IActionResult> Get()
    {
        //List<Task<object>> tasks = new List<Task<object>>();
        List<Task<string>> tasks = new List<Task<string>>();
        int i = 0;
        while (i < 40)
        {
            var task = Test(i);
            tasks.Add(task);
            i++;
        }
        await Task.WhenAll(tasks);
        var ret = String.Empty;
        foreach (var task in tasks)
        {

            ret += task.Result;
        }

        return Ok(ret);

    }
    public async Task<string> Test(int counter)
    {
       
        var token = "";
        var requestData = new HttpRequestMessage(HttpMethod.Get, "");
        if (!string.IsNullOrWhiteSpace(token))
        {
            requestData.Headers.TryAddWithoutValidation("Authorization", String.Format("Bearer {0}", token));
        }
        var client = _clientFactory.CreateClient();
        var results = await client.SendAsync(requestData);
        var json = await results.Content.ReadAsStringAsync();
        return $"Task {counter} {results.StatusCode};";

    }

}

标签: c#.net-coreparallel-processingiis-10

解决方案


推荐阅读