Производительность ASP.NET Core: Kestrel, пулы соединений, потоковые ответы
↑ 7.1 Производительность .NET и кэширование · ← Предыдущая
Зачем это на собесе
Какие рычаги есть у ASP.NET Core-приложения при высокой нагрузке.
Объяснение
Основные рычаги:
| Область | Что делать |
|---|---|
| Асинхронность | никакого .Result; async I/O по всей цепочке (см. Антипаттерны: async void, .Result, sync over async) |
| ThreadPool | не блокировать потоки; при starvation — диагностика, а не SetMinThreads вслепую |
| Kestrel | HTTP/2/3, лимиты (MaxConcurrentConnections, MaxRequestBodySize), keep-alive |
| Соединения | IHttpClientFactory, пул БД (Maximum Pool Size), Redis multiplexer |
| Сериализация | System.Text.Json + source generators, стриминг больших ответов |
| Ответы | сжатие (Brotli), ETag/кэш, IAsyncEnumerable |
| EF/данные | проекции, AsNoTracking, пагинация, индексы |
| GC | Server GC в контейнерах, лимиты памяти, TieredPGO, ReadyToRun/NativeAOT для старта |
| Логирование | LoggerMessage, уровни, асинхронные sinks |
// Потоковая выдача больших списков
app.MapGet("/export", async (AppDbContext db, HttpResponse res, CancellationToken ct) =>
{
res.ContentType = "application/x-ndjson";
await foreach (var o in db.Orders.AsNoTracking().AsAsyncEnumerable().WithCancellation(ct))
await res.WriteAsync(JsonSerializer.Serialize(o) + "\n", ct);
});
// Source generator для JSON
[JsonSerializable(typeof(OrderDto))] partial class AppJsonContext : JsonSerializerContext;
builder.Services.ConfigureHttpJsonOptions(o => o.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonContext.Default));Метод: измерить (нагрузочный тест, метрики) → найти узкое место (обычно БД, внешние вызовы, а не код фреймворка) → исправить.
Нюансы и подводные камни
- Kestrel не узкое место в типичных приложениях: чаще БД и блокировки.
- Лимиты CPU в контейнере влияют на число потоков и GC: задавайте
DOTNET_переменные осознанно. - Слишком большие пулы соединений перегружают БД.
- Буферизация всего ответа перед отправкой увеличивает память и задержку.
- Профилирование нужно на реалистичных данных.
Практика
- Проведите нагрузочный тест эндпоинта и найдите узкое место.
- Включите JSON source generator и сравните аллокации.
- Настройте потоковую выдачу экспорта на 1 млн записей.
Вопросы с ответами
Что чаще всего тормозит ASP.NET Core-сервис?
Блокирующий код, обращения к БД и внешним сервисам (N+1, отсутствие индексов), сериализация больших объектов.
Зачем потоковые ответы?
Чтобы не держать весь ответ в памяти и начать отдачу раньше.