使用Web API的性能

Raf*_*ler 8 .net c# performance asp.net-web-api

我在使用WEB Api时遇到了一些性能问题.在我的真实/生产代码上,我将做一个SOAP WS调用,在这个示例中,我只是睡觉.我有400多个客户端向Web API发送请求.

我想这是web api的一个问题,因为如果我打开5个进程,我可以处理更多的请求,而不是只有一个进程.

我的控制器的测试异步版本看起来像这样

[HttpPost]
public Task<HttpResponseMessage> SampleRequest()
{
    return Request.Content.ReadAsStringAsync()
        .ContinueWith(content =>
        {
            Thread.Sleep(Timeout);
            return new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(content.Result, Encoding.UTF8, "text/plain")
            };
        });
}
Run Code Online (Sandbox Code Playgroud)

同步版本看起来像这样

[HttpPost]
public HttpResponseMessage SampleRequest()
{
    var content = Request.Content.ReadAsStringAsync().Result;
    Thread.Sleep(Timeout);
    return new HttpResponseMessage(HttpStatusCode.OK) 
    { 
        Content = new StringContent(content, Encoding.UTF8, "text/plain") 
    };
}
Run Code Online (Sandbox Code Playgroud)

我对此测试的客户端代码看起来像这样(它被配置为在30秒后超时)

for (int i = 0; i < numberOfRequests; i++)
{
    tasks.Add(new Task(() =>
    {
        MakeHttpPostRequest();
    }));
}
foreach (var task in tasks)
{
    task.Start();
}
Run Code Online (Sandbox Code Playgroud)

我无法以一种很好的方式将它放在这里,但结果表可以在github上找到

CPU,内存和磁盘IO很低.总有至少800个可用线程(工作线程和io线程)

public static void AvailableThreads()
{
    int workerThreads;
    int ioThreads;
    ThreadPool.GetAvailableThreads(out workerThreads, out ioThreads);
    Console.WriteLine("Available threads {0} ioThreads {1}", workerThreads, ioThreads);
}
Run Code Online (Sandbox Code Playgroud)

我已经配置了DefaultConnectionLimit

System.Net.ServicePointManager.DefaultConnectionLimit = Int32.MaxValue;
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么有一个队列来回答这些请求?在每次测试中,我的响应时间几乎与服务器Thread.Sleep()时间完全相同,但响应在新请求到达时变慢.

关于如何发现bootleneck的任何提示?

它是一个.net 4.0解决方案,使用自托管选项.

编辑:我还测试了.net 4.5和Web API 2.0,并得到了相同的行为.第一次请求几乎在睡眠过期后得到答案,之后需要4倍的睡眠时间才能得到答案.

EDIT2:网络API1实施的要点主旨的网站API2实施

Edit3:MakeHttpPost方法创建一个新的WebApiClient

Edit4:

如果我改变了

Thread.Sleep() 
Run Code Online (Sandbox Code Playgroud)

await Task.Delay(10000); 
Run Code Online (Sandbox Code Playgroud)

在.net 4.5版本中,它可以按预期处理所有请求.所以我不认为与任何网络问题有关的事情.由于Thread.Sleep()阻塞线程而Task.Delay没有,看起来webapi有一个问题是消耗更多的线程?但是线程池中有可用的线程......

编辑5:如果我打开5台服务器并将客户端数量增加一倍,则服务器可以响应所有请求.所以看起来对服务器的请求数量不是问题,因为我可以"扩展"这个解决方案在不同的端口运行大量进程.对同一进程的请求数量来说,这更是一个问题.

Joh*_*ers 2

如何检查 TCP/IP 堆栈是否过载

在有问题的服务器上运行 Netstat,查找任何 Time-Wait、Fin-Wait-1、Fin-Wait-2 和 RST-Wait、RST-Wait2。这些是半生不熟的会话,堆栈正在等待另一端清理......或者......另一端确实发送了一个数据包,但本地计算机尚无法处理它们,具体取决于堆栈' 能够完成这项工作。

更糟糕的是,即使显示“已建立”的会话也可能会遇到麻烦,因为暂停尚未触发。

上述症状让人想起网络或 TCP/IP 堆栈过载。当路由器过载时,会出现非常相似的行为。