Медленные ответы от MongoDb после одновременных запросов через ASP. NET Core REST API - PullRequest
1 голос
/ 18 января 2020

Я использую веб-сервис на основе 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 ();
    }
}

Ответы [ 2 ]

0 голосов
/ 18 января 2020

Я бы не рекомендовал использовать Singleton для контекста БД. Этот объект должен быть освобожден, как только он не нужен. Вместо этого используйте Scoped, оно будет разделено между вашими репозиториями в запросе, а затем будет выпущено:

services.AddScoped<IContext, MongoDbContext>(provider => new MongoDbContext(connectionString));
0 голосов
/ 18 января 2020

Вы когда-нибудь пытались использовать асин c методы для этих операций, может быть, это поможет вам улучшить ответы параллельной операции (в контексте БД)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...