Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Azure Cosmos DB — быстрая и гибкая распределенная база данных, которая легко масштабируется с гарантированной задержкой и пропускной способностью. Для масштабирования базы данных с помощью Azure Cosmos DB не нужно вносить в архитектуру существенные изменения или писать сложный код. Для увеличения или уменьшения масштаба достаточно выполнить один вызов API. Дополнительные сведения см. в статье о подготовке пропускной способности контейнера или подготовке пропускной способности базы данных. Но так как Доступ к Azure Cosmos DB осуществляется через сетевые вызовы, существуют клиентские оптимизации, которые можно сделать для достижения пиковой производительности при использовании пакета SDK для SQL .NET.
Таким образом, если вы пытаетесь повысить производительность базы данных, рассмотрите следующие варианты:
Обновление до пакета SDK для .NET версии 3
Выпущен пакет SDK для .NET версии 3 . Если вы используете пакет SDK для .NET версии 3, ознакомьтесь с руководством по производительности .NET версии 3 , чтобы получить следующие сведения:
- По умолчанию используется режим Direct TCP
- Поддержка API потоковой передачи
- Поддержка пользовательского сериализатора для разрешения использования System.Text.JSON
- Встроенная пакетная и массовая поддержка
Рекомендации по размещению
Включение сборки мусора на стороне сервера (GC)
В некоторых случаях для оптимизации можно уменьшить частоту сборки мусора. В .NET установите для параметра gcServer значение true.
Масштабирование клиентской рабочей нагрузки
Если вы тестируете на высоком уровне пропускной способности (более 50 000 ЕЗ/с), клиентское приложение может стать ограничивающим фактором из-за предельной загрузки на центральный процессор или сеть. Если вы достигли этой точки, то можете повысить производительность Azure Cosmos DB, развернув клиентские приложения на нескольких серверах.
Замечание
Высокая загрузка ЦП может привести к увеличению задержки и исключений времени ожидания запроса.
Операции с метаданными
Не проверяйте наличие базы данных и/или коллекции, вызывая Create...IfNotExistsAsync и/или Read...Async в горячем потоке или перед выполнением операции с элементом. Проверка должна выполняться только при запуске приложения, если требуется их удаление (в противном случае это не требуется). Эти операции с метаданными создают дополнительную сквозную задержку, не имеют соглашения об уровне обслуживания и обладают своими отдельными ограничениями, которые не масштабируются так же, как операции с данными.
Логирование и трассировка
В некоторых средах включено средство .NET DefaultTraceListener. DefaultTraceListener создает проблемы с производительностью в рабочих средах, что приводит к возникновению узких мест из-за высокой загрузки ЦП и большого числа операций ввода-вывода. Убедитесь, что средство DefaultTraceListener отключено для вашего приложения, удалив его из TraceListeners в продуктивных средах.
Последние версии пакета SDK (версия выше 2.16.2) автоматически удаляют его при обнаружении, а в более старых версиях вы можете удалить его вручную следующими способами:
if (!Debugger.IsAttached)
{
Type defaultTrace = Type.GetType("Microsoft.Azure.Documents.DefaultTrace,Microsoft.Azure.DocumentDB.Core");
TraceSource traceSource = (TraceSource)defaultTrace.GetProperty("TraceSource").GetValue(null);
traceSource.Listeners.Remove("Default");
// Add your own trace listeners
}
Нетворкинг
Политика подключения: использование режима прямого подключения
Режим подключения пакета SDK для .NET версии 2 по умолчанию — это шлюз. Режим подключения настраивается во время создания экземпляра DocumentClient с помощью ConnectionPolicy параметра. Если вы используете прямой режим, необходимо также задать Protocol с помощью параметра ConnectionPolicy. Дополнительные сведения о различных вариантах подключения см. в статье Режимы подключения.
Uri serviceEndpoint = new Uri("https://contoso.documents.net");
string authKey = "your authKey from the Azure portal";
DocumentClient client = new DocumentClient(serviceEndpoint, authKey,
new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct, // ConnectionMode.Gateway is the default
ConnectionProtocol = Protocol.Tcp
});
Временная нехватка портов
При большом числе подключений или высокой интенсивности использования портов на ваших экземплярах необходимо сначала убедиться, что клиентские экземпляры являются одиночными. Иными словами, экземпляры клиента должны быть уникальными в течение всего времени существования приложения.
При выполнении протокола TCP клиент оптимизирует задержку с помощью длительных подключений в отличие от протокола HTTPS, который завершает подключения через 2 минуты бездействия.
В сценариях, когда у вас есть разреженный доступ, и если вы заметите более высокое число подключений по сравнению с доступом в режиме шлюза, вы можете:
- Настройте свойство ConnectionPolicy.PortReuseMode (активно начиная с версии платформы
PrivatePortPool4.6.1 и версии .NET core> 2.0): это свойство позволяет компоненту SDK использовать небольшой пул временных портов для различных конечных точек назначения Azure Cosmos DB. - Свойство ConnectionPolicy.IdleConnectionTimeout должно быть настроено на значение не менее 10 минут. Рекомендуемые значения : от 20 минут до 24 часов.
Вызов OpenAsync, чтобы избежать задержки запуска при первом запросе
По умолчанию первый запрос имеет более высокую задержку, так как он должен получить таблицу маршрутизации адресов. При использовании пакета SDK версии 2 вызовите OpenAsync() один раз во время инициализации, чтобы избежать этой задержки запуска при первом запросе. Вызов выглядит следующим образом: await client.OpenAsync();
Замечание
OpenAsync будет создавать запросы для получения таблицы маршрутизации адресов для всех контейнеров в учетной записи. Для учетных записей с большим количеством контейнеров, но для которых приложение обращается только к их части, OpenAsync создаст ненужный объем трафика, что приведет к замедлению инициализации. Поэтому использование OpenAsync может оказаться не полезным в этом сценарии, так как оно замедляет запуск приложения.
Для повышения производительности размещайте клиентов в одной области Azure
Если это возможно, размещайте приложения, выполняющие вызовы к Azure Cosmos DB, в том же регионе, в котором находится база данных Azure Cosmos DB. Ниже приведено приблизительное сравнение: вызовы Azure Cosmos DB в одном регионе выполняются в пределах 1 мс до 2 мс, но задержка между западным и восточным побережьем США составляет более 50 мс. Значение задержки может отличаться в зависимости от выбранного маршрута при передаче запроса от клиента к границе центра обработки данных Azure. Вы можете получить наименьшую возможную задержку, гарантируя, что вызывающее приложение находится в том же регионе Azure, что и подготовленная конечная точка Azure Cosmos DB. Список доступных регионов см. на странице с регионами Azure.
Увеличение количества потоков и задач
Так как вызовы Azure Cosmos DB выполняются по сети, возможно, потребуется изменить степень параллелизма запросов, чтобы клиентское приложение потратило минимальное время ожидания между запросами. Например, если вы используете библиотеку параллельных задач .NET, создайте около нескольких сотен задач считывания или записи в Azure Cosmos DB.
Включение ускоренной сети
Чтобы уменьшить задержку и дрожание ЦП, рекомендуется включить ускоренную сетевую функцию на клиентских виртуальных машинах. См. статью "Создание виртуальной машины Windows с ускорением сети " или "Создание виртуальной машины Linux с ускорением сети".
Использование пакета SDK
Установка последней версии пакета SDK
Пакеты SDK для Azure Cosmos DB постоянно улучшаются, чтобы обеспечивать самую высокую производительность. Ознакомьтесь со страницами пакета SDK для Azure Cosmos DB, чтобы определить самую последнюю версию SDK и просмотреть улучшения.
Использование одного и того же клиента Azure Cosmos DB в течение всего жизненного цикла приложения
Каждый DocumentClient экземпляр является потокобезопасной и выполняет эффективное управление подключениями и кэширование адресов при работе в прямом режиме. Чтобы обеспечить эффективное управление подключениями и повысить производительность клиента SDK, рекомендуется использовать один экземпляр на AppDomain на протяжении всего времени работы приложения.
Избегайте блокирующих вызовов
Пакет SDK Для Azure Cosmos DB должен быть разработан для одновременной обработки множества запросов. Асинхронные API позволяют небольшому пулу потоков работать с тысячами одновременных запросов, не дожидаясь блокировки вызовов. Вместо ожидания завершения длительной синхронной задачи поток может работать с другим запросом.
Распространенная проблема с производительностью в приложениях с помощью пакета SDK Azure Cosmos DB блокирует вызовы, которые могут быть асинхронными. Множество синхронных блокирующих вызовов ведут к истощению ресурсов пула потоков и увеличению времени отклика.
Не рекомендуется:
- Блокировать асинхронное выполнение путем вызова Task.Wait или Task.Result.
- Использовать метод Task.Run, чтобы сделать синхронный API асинхронным.
- Получать блокировки в общих участках кода. .NET SDK для Azure Cosmos DB обеспечивает наивысшую производительность при выполнении кода параллельно.
- Вызовите Task.Run и сразу ожидайте его. ASP.NET Core уже запускает код приложения в стандартных потоках пула, поэтому вызов Task.Run приводит только к дополнительному и избыточному планированию пула потоков. Даже если запланированный код блокирует поток, Task.Run не предотвращает это.
- Используйте ToList() на
DocumentClient.CreateDocumentQuery(...), который использует блокирующие вызовы для синхронной очистки запроса. Используйте AsDocumentQuery() для асинхронного очистки запроса.
Сделайте следующее:
- Асинхронно вызовите API .NET для Azure Cosmos DB.
- Весь стек вызовов является асинхронным, чтобы использовать преимущества шаблонов async/await.
Можно использовать профилировщик, например PerfView, чтобы находить потоки, часто добавляемые в пул потоков. Событие Microsoft-Windows-DotNETRuntime/ThreadPoolWorkerThread/Start указывает поток, добавленный в пул потоков.
Увеличение System.Net MaxConnections на каждый хост при использовании режима шлюза
Запросы Azure Cosmos DB выполняются по протоколу HTTPS/REST при использовании режима шлюза. Они подвергаются ограничению подключения по умолчанию на имя узла или IP-адрес. Возможно, потребуется установить MaxConnections более высокое значение (от 100 до 1000), чтобы клиентская библиотека могла использовать несколько одновременных подключений к Azure Cosmos DB. В пакете SDK для .NET 1.8.0 и более поздних версиях значение по умолчанию для ServicePointManager.DefaultConnectionLimit равно 50. Чтобы изменить значение, можно задать для Documents.Client.ConnectionPolicy.MaxConnectionLimit значение выше.
Реализация обратного выхода через интервалы RetryAfter
Во время тестирования производительности следует увеличивать нагрузку до тех пор, пока небольшое количество запросов не начнёт ограничиваться. Если запросы ограничиваются, клиентское приложение должно уменьшить активность на заданный сервером интервал повторных попыток. Соблюдение интервала ожидания гарантирует, что вы тратите минимальное время на ожидание между повторными попытками.
Поддержка политики повторных попыток включена в следующие пакеты SDK:
- Версии 1.8.0 и выше пакета SDK для .NET для SQL и пакета SDK Java для SQL
- Версия 1.9.0 и более поздней версии пакета SDKNode.js для SQL и пакета SDK Python для SQL
- Все поддерживаемые версии пакетов SDK для .NET Core
Дополнительные сведения см. в разделе RetryAfter.
В версии 1.19 и более поздних версий пакета SDK для .NET существует механизм ведения журнала дополнительных диагностических сведений и устранения проблем с задержкой, как показано в следующем примере. Вы можете записать диагностическую строку для запросов с более высокой задержкой чтения. Записанная диагностическая строка поможет понять, сколько раз вы получили 429 ошибок для данного запроса.
ResourceResponse<Document> readDocument = await this.readClient.ReadDocumentAsync(oldDocuments[i].SelfLink);
readDocument.RequestDiagnosticsString
Кэшируйте URI документов для снижения задержки чтения
Кэшируйте URI документов каждый раз, когда это возможно для оптимальной производительности чтения. Необходимо определить логику для кэширования идентификатора ресурса при создании ресурса. Поиски на основе идентификаторов ресурсов быстрее, чем поиск на основе имен, поэтому кэширование этих значений повышает производительность.
Увеличение количества потоков или задач
См. раздел "Увеличить количество потоков и задач " в разделе "Сеть" этой статьи.
Операции запросов
Операции с запросами см. в разделе Рекомендации по повышению производительности запросов.
Политика индексирования
Исключите неиспользуемые пути из индексирования, чтобы ускорить выполнение операций записи
Политика индексирования Azure Cosmos DB также позволяет указать пути к документам, которые необходимо включить в индексирование или исключить из индексирования с помощью путей индексирования (IndexingPolicy.IncludePaths и IndexingPolicy.ExcludeedPaths). Пути индексирования могут повысить производительность записи и уменьшить хранилище индексов для сценариев, в которых шаблоны запросов известны заранее. Это обусловлено тем, что стоимость индексирования напрямую соотносится с количеством уникальных путей. Например, в этом коде показано, как исключить весь раздел документов (поддерев) из индексирования с помощью подстановочного знака "*".
var collection = new DocumentCollection { Id = "excludedPathCollection" };
collection.IndexingPolicy.IncludedPaths.Add(new IncludedPath { Path = "/*" });
collection.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath { Path = "/nonIndexedContent/*");
collection = await client.CreateDocumentCollectionAsync(UriFactory.CreateDatabaseUri("db"), collection);
Дополнительные сведения см. в статье Политики индексации Azure Cosmos DB.
Пропускная способность
Измеряйте и настраивайте для снижения использования единиц запросов в секунду
В Azure Cosmos DB предлагается обширный набор операций базы данных. К этим операциям относятся реляционные и иерархические запросы, использующие функции, определяемые пользователем, хранимые процедуры и триггеры, все они работают с документами в коллекции базы данных. Затраты, связанные с каждой из этих операций, зависят от ЦП, операций ввода-вывода и памяти, необходимых для выполнения операции. Вместо того, чтобы думать об аппаратных ресурсах и управлять ими, можно рассматривать единицу запросов (ЕЗ) в качестве одной меры для ресурсов, необходимых для выполнения различных операций базы данных и обслуживания запроса приложения.
Пропускная способность выделяется на основе количества единиц запроса, заданного для каждого контейнера. Потребление единиц запросов оценивается как показатель в секунду. Приложения, которые превышают предоставленную пропускную способность единиц запросов для их контейнера, ограничиваются до тех пор, пока частота не снизится ниже предоставленного уровня для контейнера. Если приложению требуется более высокий уровень пропускной способности, можно увеличить пропускную способность, подготовив дополнительные единицы запросов.
Сложность запроса влияет на количество единиц запросов, используемых для операции. Количество предикатов, характер предикатов, количество пользовательских функций и размер исходного набора данных влияют на стоимость операций запроса.
Чтобы измерить затраты на любую операцию (создание, обновление или удаление), проверьте заголовок x-ms-request-charge (или эквивалентное RequestCharge свойство в ResourceResponse\<T>FeedResponse\<T> пакете SDK для .NET) для измерения количества единиц запросов, потребляемых операциями:
// Measure the performance (Request Units) of writes
ResourceResponse<Document> response = await client.CreateDocumentAsync(collectionSelfLink, myDocument);
Console.WriteLine("Insert of document consumed {0} request units", response.RequestCharge);
// Measure the performance (Request Units) of queries
IDocumentQuery<dynamic> queryable = client.CreateDocumentQuery(collectionSelfLink, queryString).AsDocumentQuery();
while (queryable.HasMoreResults)
{
FeedResponse<dynamic> queryResponse = await queryable.ExecuteNextAsync<dynamic>();
Console.WriteLine("Query batch consumed {0} request units", queryResponse.RequestCharge);
}
Плата за запрос, возвращаемая в этом заголовке, составляет часть зарезервированной пропускной способности (т. е. 2000 RU/секунду). Например, если приведенный выше запрос вернет 1000 документов размером по 1 КБ каждый, затраты на операцию составят 1000. Таким образом, в течение одной секунды сервер учитывает только два таких запроса перед ограничением скорости последующих запросов. Чтобы узнать больше, ознакомьтесь с единицами запроса и калькулятором единиц запроса.
Обработка ограничения скорости / слишком высокая частота запросов
Если клиент пытается превысить зарезервированную пропускную способность для учетной записи, это не приводит к замедлению работы сервера и не позволяет использовать пропускную способность сверх зарезервированного уровня. Сервер предварительно завершит запрос с помощью RequestRateTooLarge (код состояния HTTP 429). Он вернет заголовок x-ms-retry-after-ms , указывающий время в миллисекундах, которое пользователь должен ждать, прежде чем пытаться повторить запрос.
HTTP Status 429,
Status Line: RequestRateTooLarge
x-ms-retry-after-ms :100
Все пакеты SDK автоматически перехватывают этот ответ, соблюдают указанный сервером заголовок retry-after и повторяют запрос. Если к вашей учетной записи параллельно имеет доступ только один клиент, следующая попытка будет успешной.
Если у вас более одного клиента, который последовательно работает с превышением скорости запросов, то число попыток повторного обращения по умолчанию, равное в настоящее время 9, установленных клиентом, может быть недостаточным. В этом случае клиент вызывает DocumentClientException с кодом состояния 429 для приложения.
Можно изменить число повторных попыток по умолчанию, задав RetryOptions для экземпляра ConnectionPolicy. По умолчанию, DocumentClientException с кодом состояния 429 возвращается после суммарного времени ожидания в 30 секунд, если запрос продолжает превышать установленную квоту запросов. Эта ошибка возвращается, даже если текущее число повторных попыток меньше максимального количества повторных попыток, является ли текущее значение значением по умолчанию 9 или определяемым пользователем значением.
Автоматическое поведение повторных попыток помогает повысить устойчивость и удобство использования для большинства приложений. Но это может не быть лучшим поведением при выполнении тестов производительности, особенно при измерении задержки. Если эксперимент достигает ограничения сервера и заставляет клиентский SDK повторять попытки в тихом режиме, на стороне клиента могут возникать пиковые задержки. Чтобы избежать скачков латентности во время экспериментов с производительностью, измерьте затраты каждой операции и убедитесь, что запросы работают ниже зарезервированной скорости запросов. Дополнительные сведения см. в статье Единицы запроса.
Использование документов меньшего размера для обеспечения более высокой пропускной способности
Плата за запрос (то есть стоимость обработки запросов) данной операции сопоставляется непосредственно с размером документа. За операции с большими документами взимается больше единиц запроса, чем за операции с мелкими документами.
Дальнейшие шаги
Пример приложения, который используется для оценки Azure Cosmos DB для высокопроизводительных сценариев на нескольких клиентских компьютерах, см. в статье "Производительность и масштабирование тестирования с помощью Azure Cosmos DB".
Дополнительные сведения о создании приложения с высокой масштабируемостью и производительностью см. в статье Partitioning and scaling in Azure Cosmos DB (Секционирование и масштабирование в Azure Cosmos DB).