我使用 asp.net webapi 编写了一个 api,并将其作为应用服务部署在 Azure 中。我的控制器的名称是测试控制器,我的操作方法类似于波纹管。
[Route("Test/Get")]
public string Get()
{
Thread.Sleep(10000);
return "value";
}
因此,对于每个请求,它应该在返回字符串“值”之前等待10秒。我还编写了另一个endpoint来查看threadpool中执行请求的线程数量。那个动作有点像贝娄。
[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
};
}
现在,当我们同时对 Test/Get 终结点进行 29 次 get 调用时,需要将近 11 秒才能成功所有请求。因此,服务器在 11 个线程中同时执行所有请求。要查看线程状态,请在调用测试/获取后立即调用测试/线程信息返回立即(无需等待){“可用工作线程”:8161,“最大工作线程”:8191,“占用线程”:30 }
似乎有 29 个线程正在执行测试/获取请求,1 个线程正在执行测试/线程信息请求。
当我对Test/Get进行60次get调用时,几乎需要36秒才能成功。调用Test/ThreadInfo(需要一些时间)会返回{“可用性工作线程”:8161,“MaxWorkerThread”:8191,“占领线程”:30}
如果我们增加请求数,占用线程的值就会增加。与1000个请求一样,它需要2分22秒,占用线程的值为129。
虽然WorkerThread中有许多线程可用,但似乎请求并在30个并发调用后排队。它逐渐增加了并发执行的线程,但这还不够(1000个请求129个线程)。
因为我们的服务有很多IO调用(其中一些是外部api调用,一些是数据库查询),所以延迟也很高。因为我们使用所有的IO调用异步方式,所以服务器可以同时处理很多请求,但是当处理器在做实际工作时,我们需要更多的并发。我们将S2服务计划用于一个实例。增加实例将增加并发性,但我们需要单个实例的更多并发性。
在阅读了一些关于IIS的博客和文档后,我们看到了一个设置minFreeThreads。如果线程池中的可用线程数低于此设置的值,IIS将开始对请求进行排队。appservice中有类似的东西吗?真的有可能从azure应用程序服务获得更多并发性吗?或者我们缺少一些配置吗?
根据我的理解,您需要通过ThreadPool.GetMinThreads代码检查MinWorkerThreads,这可以检索ThreadPool在预期新请求时维护的空闲线程数。我建议您在执行操作后返回当前线程池信息(Tetst/Get
),而不是向Test/ThreadInfo
发出新请求。根据您的代码,我在我的Web应用程序上使用B1定价层进行了测试,如下所示:
1000个并发请求,每个操作睡眠15秒,总时间为3分钟20秒。
线程池创建和销毁工作线程以优化吞吐量,如果当前线程可以处理请求,则不会再创建线程。一旦这些线程完成执行其活动,它们就会返回到线程池。
然后,我使用异步编程,将操作更改如下:
public async Task<ActionResult> DoJob(int id)
{
await Task.Delay(TimeSpan.FromSeconds(15));
return ThreadInfo();
}
结果:
近3000个并发请求:
一般来说,AvailableWorkerThreads只是表示可以启动的额外工作线程的数量,而不是已经为您创建的工作线程的数量。我建议你使用异步编程,并在azure web app上部署你的实际工作,然后检查实际性能,并找到相关的方法,如果有任何瓶颈的话。
终于得到了我问题的答案。问题是,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.";
}
}
这里ThreadPool.SetMinThreads(300,minIOC)是设置线程池在切换到添加或删除线程的算法之前将创建的最小线程值。我已经将此方法添加为我的webapi控制器的一个操作,然后在运行此操作后,当我向Test/Getendpoint发出300个并发请求时,通过发出请求,所有这些都在11秒内运行并完成,并且没有请求排队。
我知道PHP支持处理多个并发连接,并且根据服务器的不同,它可以像这个答案中提到的那样进行配置 服务器是如何管理多个连接的?它是为每个请求派生一个子进程,还是使用线程处理,还是使用线程池处理? 链接的答案说一个进程是分叉的,然后作者在评论中说是线程还是进程,这让人很困惑,如果请求是使用子进程、线程还是线程池提供的?
我正在使用固定大小的Java线程池(ExecutorService)。假设我向线程池提交了一个作业,并且该作业处于空闲状态。 是否有可能从线程池中删除空闲作业,以便可以处理队列中的其他作业,然后再添加空闲作业?
如何从线程池中找到60%(或N%)的线程可用性?这背后的逻辑是什么? 父线程使用线程池线程生成多个网址,并等待所有子线程完成。 代码如下所示 父线程 子线程 用于跨线程通信的对象数据 在上述代码中,所需的线程硬编码为: 这种硬编码会导致线程池不足吗?如果线程池中没有可用的线程,会发生什么?如何在托管服务器的线程池中查找可用线程的总数? 谢谢。
使用 时,线程池中最初创建了多少线程,Javadoc 没有指定任何数字,是否有一个保证的数字,我们最初总是会得到 10 个或其他什么。文档如下: newCachedThreadPool public static ExecutorService newCachedThreadPool()创建一个线程池,该线程池根据需要创建新的线程,但会在以前构建的线程可用时重用它们。这些池通常会提高执行许多短期异
本文向大家介绍详解python中的线程与线程池,包括了详解python中的线程与线程池的使用技巧和注意事项,需要的朋友参考一下 线程 进程和线程 什么是进程? 进程就是正在运行的程序, 一个任务就是一个进程, 进程的主要工作是管理资源, 而不是实现功能 什么是线程? 线程的主要工作是去实现功能, 比如执行计算. 线程和进程的关系就像员工与老板的关系, 老板(进程) 提供资源 和 工作空间, 员工(
如果我有一个固定大小的线程池,它什么时候真正调用启动线程?(它会在创建时启动它们吗?还是等到我开始提交任务时再启动?)