Для демонстрации я собираюсь запустить тест, в котором я сравниваю .NET Core, работающий на Kestrel, и .NET Framework 4.6.1, работающий на IIS. Оба на локальной машине.
«Интернет» говорит, что Kestrel намного быстрее, но в моем собственном тесте нет заметного различия с IIS. И большую часть времени IIS еще быстрее. Как это?
У меня «тот же» код, работающий на .NET Framework (с использованием EF) и .NET Core (с использованием EFCore). controller
выглядит следующим образом. Он что-то записывает в БД, а затем извлекает и возвращает. Я закрываю DBContext
, чтобы убедиться, что кеша нет. Код для .NET Core ниже (код для .NET Framework аналогичен, кроме DI).
[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();
Когда я запускаю его на .NET Framework с IIS, я получаю больше запросов, чем на ядре с Kestrel.
Я пытался изменить options.Limits
в Kestrel безуспешно. Я предполагаю, что что-то не так с моим «приложением для тестирования» или что мое локальное устройство само является узким местом.
Почему IIS обрабатывает запросы намного быстрее, чем Kestrel?
UPDATE:
Если я уберу EF и верну только OK()
в контроллере, IIS все равно будет работать лучше.
Я пробуждаю серверы перед сравнительным тестированием.
Я строю это как Release
.
Когда я запускаю с 10 потоками в течение 30 секунд, IIS будет обрабатывать 600 запросов, а запросы Kestrel 300.
gcServer
установлено на true
.