Код: Выделить всё
services.AddDbContext(options =>
options.UseSqlServer(connectionString,
providerOptions => providerOptions.CommandTimeout(60)));
Код: Выделить всё
Pooling=true;Max Pool Size=100;Connection Timeout=300
Все работало бы хорошо, если бы количество одновременных пользователей меньше 500 во время нагрузочного тестирования. Однако за пределами этого числа я начинаю видеть множество ошибок с истекшим тайм-аутом. Когда я проверил базу данных, тупиковой ситуации не было, но я увидел более 100 подключений в спящем режиме (API размещен на двух модулях Kubernetes). Я отслеживал эти соединения во время тестирования, и оказалось, что вместо повторного использования текущих спящих соединений в пул добавлялись новые. Насколько я понимаю, ядро Entity Framework управляет открытием и закрытием соединений, но, похоже, это не так. Или я что-то упускаю?
Ошибка выглядит так:
Код: Выделить всё
{ "StatusCode":500,"Message":"Error:Timeout expired.
The timeout period elapsed prior to obtaining a connection from the pool.c
This may have occurred because all pooled connections were in use and max pool size was reached.
Stack Trace:
at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
at Microsoft.Data.SqlClient.SqlConnection.Open()
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.BeginTransaction(IsolationLevel isolationLevel)
...
контроллер вызывает метод в классе обслуживания:
Код: Выделить всё
var result = await _myservice.SaveUserStatusAsync(userId, status);
Код: Выделить всё
var user = await _userRepo.GetUserAsync(userId);
Код: Выделить всё
return await _userRepo.UpdateUserAsync(user);
Код: Выделить всё
_context.user.Update(user);
var updated = await _context.SaveChangesAsync();
return updated > 0;
Большое спасибо Ивану Янгу, который щедро предложил награду. Хотя я все еще занимаюсь расследованием, я многому научился, прочитав все комментарии и ответы ниже. Вот что я пробовал до сих пор: я увеличил размер пула до 200 (я знаю, что это неправильный способ решения проблемы), увеличил количество модулей, чтобы API теперь работал на 4 модулях, и выделил больше памяти. к каждому поду. Конечный результат до сих пор был хорошим: 500 ошибок полностью исчезли при одновременном использовании до 2000 пользователей. Я обновлю этот вопрос своими выводами после того, как попробую другие варианты.
Подробнее здесь: https://stackoverflow.com/questions/687 ... ing-status