与IIS相比,Kestrel的性能下降

时间:2018-05-17 08:10:04

标签: c# asp.net-core .net-core benchmarking kestrel-http-server

对于演示,我打算运行一个基准测试,我将运行在Kestrel上的.NET Core与运行在IIS上的.NET Framework 4.6.1进行比较。两者都在本地机器上。

"The Internet"说Kestrel要快得多,但在我自己的基准测试中,IIS没有明显的区别。而且大多数时候IIS更快。那怎么样?

我在.NET Framework(使用EF)和.NET Core(使用EFCore)上运行“相同”代码。 controller看起来像这样。它会向DB写一些东西,然后获取它并返回它。我关闭DBContext以确保没有缓存。下面的.NET Core代码(除了没有DI,.NET Framework的代码类似)。

[Route("api/[controller]")]
public class ValuesController : Controller
{
    private readonly DbContextOptions<DemoContext> options;

    public ValuesController(DbContextOptionsBuilder<DemoContext> builder)
    {
        this.options = builder.Options;
    }

    // GET api/values
    [HttpGet]
    public async Task<IActionResult> Get()
    {
        var id = Guid.NewGuid();
        using (var context = new DemoContext(options))
        {

            var newItem = new DemoTable()
            {
                Id = id,
                Stamp = DateTime.Now,
                System = "Core"
            };
            context.DemoTable.Add(newItem);
            await context.SaveChangesAsync();
        }

        using (var context = new DemoContext(options))
        {
            var item = await context.DemoTable.SingleAsync(x => x.Id == id);
            return Ok(item);

        }
    }
}

我的Program.cs看起来像这样:

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseKestrel(options =>
        {
            options.Limits.MaxConcurrentConnections = 1000;
            options.Listen(IPAddress.Loopback, 5050);
        })
        .ConfigureLogging((context, logging) =>
        {
            logging.ClearProviders();
        })
        .UseStartup<Startup>()
        .Build();

我使用dotnet dotnet demoApp.dll运行它。

我使用提出大量请求的应用程序对其进行测试。

    var cts = new CancellationTokenSource();
    int processed = 0;
    int seconds = 30;

    var url = new Uri($"http://localhost:{port}");
    var tasks = new Task[20];
    for (int i = 0; i < tasks.Length; i++)
    {
        tasks[i] = Task.Factory.StartNew(() =>
        {
            while (!token.IsCancellationRequested)
            {
                var client = new RestClient(url);
                var request = new RestRequest("/api/values");
                client.ExecuteAsyncGet(request, (response, handle) =>
                {
                    if(!token.IsCancellationRequested)
                        Interlocked.Add(ref processed, 1);
                }, "GET");
            }
        });
    }
    Thread.Sleep(seconds * 1000);
    cts.Cancel();

当我使用IIS运行.NET Framework时,我收到的请求多于我使用Kestrel运行Core时的请求。

我尝试在Kestrel中更改options.Limits但没有成功。我的假设是我的“基准测试应用程序”出了问题,或者我的本地机器本身就是瓶颈。

为什么IIS比Kestrel更快地处理请求?

更新

如果我删除EF并且仅在控制器中返回OK(),则IIS仍然表现更好。

在基准测试之前我将服务器唤醒。

我将其构建为Release

当我使用10个线程运行30秒时,IIS将处理600个请求和Kestrel 300请求。

gcServer设置为true

1 个答案:

答案 0 :(得分:1)

您无法通过将虚拟主机连接到数据库来测试其性能。数据库或您的业务逻辑将成为瓶颈。

从一个干净的项目开始,或者做得更好,但只要抓住基准。为了获得高端性能,很多事情都在起作用。

您正在处理300或600个请求(可怜)的事实暗示了管道中还有其他内容。请注意,您的控制器也在每个请求+您所拥有的任何中间件上注入db上下文。