Я использую веб-сервис на основе ASP. NET Core 2.2. Внешние клиенты вызывают API REST через регулярные интервалы. Таким образом, вполне возможно, что API получает около 50 почти одновременных запросов (каждые 10-40 минут).
Проблема: через несколько минут после одновременных запросов служба ответила слишком долго. Время отклика увеличилось с <1 с (для одиночных запросов) до 40 сек c. </p>
Примечания:
- Запрос извлекает элементы (всего <100) примерно с трех различные коллекции (фильтрация по одному свойству, включенному в индекс, некоторые по идентификатору; хранение <5000 записей). </li>
- Для обеспечения сохранности используются MongoDB.Driver 2.9.1 и одиночная установка MongoDB 4.0.12.
- Обновление до последней версии драйвера и MongoDB 4.0 не улучшило ситуацию.
- Профилировщик базы данных MongoDB не показывает медленных запросов.
- Вывод
mongostat
показывает около 90 открытые соединения. - Тесты были выполнены на более старой машине (некоторые Haswell Core i7, 32 ГБ ОЗУ), работающей Windows 10 (дБ и приложение на одной машине).
- MongoDB установка выполняется с настройками по умолчанию.
- Непрерывные нагрузочные тесты (например, 3000 x 50 одновременных запросов) показали, что после начальной фазы наращивания (с медленными запросами) время отклика падает до <5 se c, что я бы посчитал нормальный. <ul>
- Некоторые операции записи в эти коллекции выполняются (только с одного клиента, например, 10 в час).
Вопросы:
- Есть ли какие-либо рекомендации по настройке производительности?
- Есть ли какие-либо индикаторы производительности для проверки?
- Проблема с пулом соединений?
РЕДАКТИРОВАТЬ: Использование ClusterConfigurator MongoClientSettings можно получить из Пакет драйвера MongoDB для C# Я измерил увеличение продолжительности запроса до 00: 00: 04.5022352 секунд (с 00: 00: 00.0005432).
Я заметил, что чтение opLatencies увеличивается во время 50 почти одновременных запросов: opLatencies.reads.latency: с 68723 до 202886, opLatencies.reads.ops: с 449 до 1053
Справочная информация:
MongoClient
создается в следующем классе:
public class MongoDbContext : IContext {
private readonly MongoUrl _url;
private MongoClient _client;
private IMongoDatabase _db;
public MongoDbContext (string connectionString) {
_url = MongoUrl.Create (connectionString);
}
public IMongoDatabase GetDatabase () {
return _db ?? (_db = GetClient ().GetDatabase (_url.DatabaseName));
}
public MongoClient GetClient () {
return _client ?? (_client = new MongoClient (_url));
}
}
Контекст внедряется в Startup.cs и используется в нескольких хранилищах.
//... Startup.cs
var context = new MongoDbContext(connectionString);
services.AddSingleton<IContext>(context);
// Other services and repositories ...
services.AddTransient<IWeatherRepository, WeatherRepository>();
В хранилищах используется следующий базовый класс:
public abstract class MongoDbRepository<T> : IRepository<T> where T : Entity<long> {
private IMongoCollection<T> _collection { get; set; }
protected IContext Context { get; set; }
protected abstract IMongoCollection<T> GetCollection ();
protected IMongoCollection<T> Collection {
get { return _collection ?? (_collection = GetCollection ()); }
set { _collection = value; }
}
public MongoDbRepository (IContext context) {
Context = context;
}
/// ...
public async Task<IEnumerable<T>> Find (Expression<Func<T, bool>> filter) {
return await Collection.Find (filter).ToListAsync ();
}
}