【发布时间】:2017-09-13 07:06:32
【问题描述】:
我使用 asp.net webapi 编写了一个 api,并将其部署在 azure 中作为 Appservice。我的控制器的名称是 TestController,我的操作方法如下所示。
[Route("Test/Get")]
public string Get()
{
Thread.Sleep(10000);
return "value";
}
因此对于每个请求,它应该等待 10 秒才能返回字符串“值”。我还编写了另一个端点来查看线程池中用于执行请求的线程数。该操作类似于以下内容。
[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 次获取调用时,几乎需要 11 秒才能使所有请求成功。因此服务器在 11 个线程中同时执行所有请求。要查看线程状态,在调用 Test/Get 后立即调用 Test/ThreadInfo 会立即返回(无需等待) { “AvailableWorkerThreads”:8161, “MaxWorkerThreads”:8191, “占用线程”:30 }
似乎有 29 个线程正在执行 Test/Get 请求,1 个线程正在执行 Test/ThreadInfo 请求。
当我对 Test/Get 进行 60 次调用时,几乎需要 36 秒才能获得成功。调用 Test/ThreadInfo(需要一些时间)返回 { “AvailableWorkerThreads”:8161, “MaxWorkerThreads”:8191, “占用线程”:30 }
如果我们增加请求数,OccupiedThreads 的值会增加。就像 1000 个请求一样,它需要 2 分 22 秒,OccupiedThreads 的值为 129。
虽然 WorkerThread 中有很多线程可用,但似乎请求并在 30 个并发调用后排队。它逐渐增加了并发执行的线程,但这还不够(129 个请求用于 1000 个请求)。
由于我们的服务有很多 IO 调用(其中一些是外部 api 调用,一些是数据库查询),因此延迟也很高。由于我们使用所有 IO 调用异步方式,因此服务器可以同时处理大量请求,但是当处理器进行实际工作时我们需要更多的并发性。我们在一个实例中使用 S2 服务计划。增加实例会增加并发,但我们需要单个实例的更多并发。
在阅读了一些关于 IIS 的博客和文档后,我们看到有一个设置 minFreeThreads。如果线程池中的可用线程数低于此设置的值,则 IIS 开始排队请求。 appservice中有这样的东西吗?是否真的可以从 azure 应用服务获得更多并发,或者我们在那里缺少一些配置?
【问题讨论】:
-
AFAIK,线程池会将创建的线程数限制为每 500 毫秒一个。您可以扩大您的价格层以获得更高的 CPU、内存等。另外,您可以尝试关注Optimizing IIS Performance 以改进并发请求。
-
因为我们已经在 Azure 中部署了应用程序,所以看不到任何进行 IIS 级别优化的选项。在 S1 中,我在并发方面得到了相同的行为,因此扩大价格层可能没有帮助。
标签: c# azure iis asp.net-web-api2 threadpool