尽管它在线程池中有足够的线程,但请求仍在Azure AppService中排队

Anu*_*nup 4 c# iis azure threadpool asp.net-web-api2

我已经使用asp.net webapi编写了一个api,并将其作为Appservice部署为Azure。我的控制器的名称为TestController,我的操作方法如下。

    [Route("Test/Get")]
    public string Get()
    {
        Thread.Sleep(10000);
        return "value";
    }
Run Code Online (Sandbox Code Playgroud)

因此,对于每个请求,它都应等待10秒钟,然后返回字符串“ value”。我还编写了另一个端点,以查看线程池中用于执行请求的线程数。这个动作就像是在吼叫。

    [Route("Test/ThreadInfo")]
    public ThreadPoolInfo Get()
    {
        int availableWorker, availableIO;
        int maxWorker, maxIO;

        ThreadPool.GetAvailableThreads(out availableWorker, out availableIO);
        ThreadPool.GetMaxThreads(out maxWorker, out maxIO);

        return new ThreadPoolInfo
        {
            AvailableWorkerThreads = availableWorker,
            MaxWorkerThreads = maxWorker,
            OccupiedThreads = maxWorker - availableWorker
        };
    }
Run Code Online (Sandbox Code Playgroud)

现在,当我们同时向Test / Get端点发出29个get调用时,几乎需要11秒钟才能成功获得所有请求。因此,服务器在11个线程中同时执行所有请求。要查看线程状态,请在调用Test / Get之后立即调用Test / ThreadInfo返回(无需等待){{“ AvailableWorkerThreads”:8161,“ MaxWorkerThreads”:8191,“ OccupiedThreads”:30}

似乎有29个线程正在执行测试/获取请求,有1个线程正在执行Test / ThreadInfo请求。

当我拨打60次Test / Get的get呼叫时,需要大约36秒钟才能成功。调用Test / ThreadInfo(花费一些时间)会返回{“” AvailableWorkerThreads“:8161,” MaxWorkerThreads“:8191,” OccupiedThreads“:30}

如果我们增加请求数量,则OccupiedThreads的值将增加。就像处理1000个请求一样,它需要2分22秒,而OccupiedThreads的值为129。

尽管在WorkerThread中有很多线程可用,但似乎在30个并发调用后请求和排队。逐渐地,它增加了用于并发执行的线程,但这还不够(对于1000个请求,为129个)。

由于我们的服务有很多IO调用(其中一些是外部api调用,有些是数据库查询),因此延迟也很高。由于我们使用所有IO调用异步方式,因此服务器可以同时处理大量请求,但是当处理器进行实际工作时,我们需要更多的并发性。我们正在将S2服务计划用于一个实例。增加实例将增加并发性,但是我们需要从单个实例中获得更多的并发性。

在阅读了IIS上的一些博客和文档后,我们看到有一个设置minFreeThreads。如果线程池中的可用线程数下降,则此设置的值IIS开始将请求排队。appservice中有这样的东西吗?而且是否真的有可能从azure应用服务中获得更多的并发性,或者我们在那里缺少一些配置?

Anu*_*nup 8

终于得到了我的问题的答案。事实是,ASP.NET线程池维护着一个线程池,这些线程池已经招致了线程初始化成本,并且易于重用。.NET线程池也可以自我调整。它监视CPU和其他资源的利用率,并根据需要添加新线程或调整线程池大小。当有大量请求且池中没有足够的线程可用时,线程池开始在池中添加新线程,然后线程池运行自己的算法以查看内存状态和系统的cpu使用情况,这需要花费大量时间。时间,这就是为什么我们看到池中工作线程的缓慢增加,并使很多请求排队的原因。但幸运的是,在线程池切换到添加新线程的算法之前,可以选择设置工作线程的数量。

    public string Settings()
    {
        int minWorker, minIOC;
        ThreadPool.GetMinThreads(out minWorker, out minIOC);

        if (ThreadPool.SetMinThreads(300, minIOC)){ 
            return "The minimum number of threads was set successfully.";
        }
        else
        {
            return "The minimum number of threads was not changed.";
        }

    }
Run Code Online (Sandbox Code Playgroud)

此处ThreadPool.SetMinThreads(300,minIOC)设置线程池在切换到用于添加或删除线程的算法之前将创建的最小线程的值。我已将此方法添加为我的webapi控制器的操作,然后在我向Test / Get端点发出300个并发请求时通过发出请求来运行此操作后,所有操作都在11秒内运行并完成,并且没有请求排队。