Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Это важно
В этой статье рассматривается устранение неполадок только пакета SDK Java для Azure Cosmos DB версии 4. Дополнительные сведения см. в заметках о выпуске пакета SDK java для Azure Cosmos DB версии 4, репозитории Maven и советах по производительности . Если вы используете более раннюю версию версии 4, ознакомьтесь с руководством по переходу на пакет SDK Java для Azure Cosmos DB версии 4 , чтобы помочь при обновлении до версии 4.
В этой статье рассматриваются распространенные проблемы, обходные пути, шаги диагностики и средства при использовании пакета SDK Java для Azure Cosmos DB версии 4 с учетными записями Azure Cosmos DB для NoSQL. Пакет SDK Java для Azure Cosmos DB версии 4 предоставляет логическое представление на стороне клиента для доступа к Azure Cosmos DB для NoSQL. В этой статье описываются средства и подходы, которые помогут вам, если вы столкнетесь с проблемами.
Начните со следующего списка:
- Ознакомьте с разделом Распространенные проблемы и их обходные решения в этой статье.
- Просмотрите Java SDK в центральном репозитории Azure Cosmos DB, который доступен как проект с открытым исходным кодом на GitHub. В нем есть раздел проблем , который активно отслеживается. Проверьте, уже ли зарегистрирована похожая проблема с обходным решением. Одним из полезных советов является фильтрация проблем по тегу
*cosmos:v4-item*. - Ознакомьтесь с советами по производительности пакета SDK Java для Azure Cosmos DB версии 4 и следуйте рекомендациям.
- Прочитайте остальную часть этой статьи, если вы не нашли решение. Затем создайте проблему на GitHub. Если есть возможность добавить теги в проблему GitHub, добавьте
*cosmos:v4-item*тег.
Сбор данных диагностики
Ответы базы данных, контейнера, элемента и запросов в SDK для Java версии 4 имеют свойство Diagnostics. В это свойство записываются все сведения, связанные с одним запросом, в том числе сведения о повторных попытках и временных сбоях.
Результаты диагностики возвращаются в виде строки. Строка изменяется с каждой версией, так как она улучшена, чтобы лучше устранять неполадки в разных сценариях. В каждой версии пакета SDK строка может нарушить его формат. Не анализируйте эту строку, чтобы избежать существенных изменений.
В следующем примере кода показано, как считывать журналы диагностики с помощью пакета SDK для Java версии 4:
Это важно
Мы рекомендуем проверить минимальную рекомендуемую версию пакета SDK для Java версии 4 и убедиться, что вы используете эту версию или более позднюю. Рекомендуемую версию можно проверить здесь.
Операции с базой данных
CosmosDatabaseResponse databaseResponse = client.createDatabaseIfNotExists(databaseName);
CosmosDiagnostics diagnostics = databaseResponse.getDiagnostics();
logger.info("Create database diagnostics : {}", diagnostics);
Операции контейнера
CosmosContainerResponse containerResponse = database.createContainerIfNotExists(containerProperties,
throughputProperties);
CosmosDiagnostics diagnostics = containerResponse.getDiagnostics();
logger.info("Create container diagnostics : {}", diagnostics);
Операции с элементами
// Write Item
CosmosItemResponse<Family> item = container.createItem(family, new PartitionKey(family.getLastName()),
new CosmosItemRequestOptions());
CosmosDiagnostics diagnostics = item.getDiagnostics();
logger.info("Create item diagnostics : {}", diagnostics);
// Read Item
CosmosItemResponse<Family> familyCosmosItemResponse = container.readItem(documentId,
new PartitionKey(documentLastName), Family.class);
CosmosDiagnostics diagnostics = familyCosmosItemResponse.getDiagnostics();
logger.info("Read item diagnostics : {}", diagnostics);
Операции запроса
String sql = "SELECT * FROM c WHERE c.lastName = 'Witherspoon'";
CosmosPagedIterable<Family> filteredFamilies = container.queryItems(sql, new CosmosQueryRequestOptions(),
Family.class);
// Add handler to capture diagnostics
filteredFamilies = filteredFamilies.handle(familyFeedResponse -> {
logger.info("Query Item diagnostics through handle : {}",
familyFeedResponse.getCosmosDiagnostics());
});
// Or capture diagnostics through iterableByPage() APIs.
filteredFamilies.iterableByPage().forEach(familyFeedResponse -> {
logger.info("Query item diagnostics through iterableByPage : {}",
familyFeedResponse.getCosmosDiagnostics());
});
Исключения Azure Cosmos DB
try {
CosmosItemResponse<Family> familyCosmosItemResponse = container.readItem(documentId,
new PartitionKey(documentLastName), Family.class);
} catch (CosmosException ex) {
CosmosDiagnostics diagnostics = ex.getDiagnostics();
logger.error("Read item failure diagnostics : {}", diagnostics);
}
Ведение журнала диагностики
Версии Java V4 SDK начиная с 4.43.0 и выше поддерживают автоматическое ведение журнала диагностики Cosmos для всех запросов или ошибок при соблюдении определенных критериев. Разработчики приложений могут определять пороговые значения задержки (для операций с точкой (создание, чтение, замена, обновление, исправление) или неодноточечные операции (запрос, канал изменений, массовые и пакетные операции)), затраты на запрос и размер полезной нагрузки. Если запросы превышают эти определенные пороговые значения, диагностика Cosmos для этих запросов будет автоматически выполняться.
По умолчанию пакет SDK для Java версии 4 автоматически регистрирует эти диагностические данные в определенном формате. Однако это можно изменить, реализуя CosmosDiagnosticsHandler интерфейс и предоставляя собственный настраиваемый обработчик диагностики.
Эти CosmosDiagnosticsThresholds и CosmosDiagnosticsHandler затем можно использовать в CosmosClientTelemetryConfig объекте, который необходимо передать в CosmosClientBuilder при создании синхронного или асинхронного клиента.
ПРИМЕЧАНИЕ. Эти пороговые значения диагностики применяются для различных типов диагностики, включая ведение журнала, трассировку и телеметрию клиента.
В следующих примерах кода показано, как определить пороговые значения диагностики, пользовательский средство ведения журнала диагностики и использовать их с помощью конфигурации телеметрии клиента:
Определение настраиваемых пороговых значений диагностики
// Create diagnostics threshold
CosmosDiagnosticsThresholds cosmosDiagnosticsThresholds = new CosmosDiagnosticsThresholds();
// These thresholds are for demo purposes
// NOTE: Do not use the same thresholds for production
cosmosDiagnosticsThresholds.setPayloadSizeThreshold(100_00);
cosmosDiagnosticsThresholds.setPointOperationLatencyThreshold(Duration.ofSeconds(1));
cosmosDiagnosticsThresholds.setNonPointOperationLatencyThreshold(Duration.ofSeconds(5));
cosmosDiagnosticsThresholds.setRequestChargeThreshold(100f);
Определение пользовательского обработчика диагностики
// By default, DEFAULT_LOGGING_HANDLER can be used
CosmosDiagnosticsHandler cosmosDiagnosticsHandler = CosmosDiagnosticsHandler.DEFAULT_LOGGING_HANDLER;
// App developers can also define their own diagnostics handler
cosmosDiagnosticsHandler = new CosmosDiagnosticsHandler() {
@Override
public void handleDiagnostics(CosmosDiagnosticsContext diagnosticsContext, Context traceContext) {
logger.info("This is custom diagnostics handler: {}", diagnosticsContext.toJson());
}
};
Определение CosmosClientTelemetryConfig
// Create Client Telemetry Config
CosmosClientTelemetryConfig cosmosClientTelemetryConfig =
new CosmosClientTelemetryConfig();
cosmosClientTelemetryConfig.diagnosticsHandler(cosmosDiagnosticsHandler);
cosmosClientTelemetryConfig.diagnosticsThresholds(cosmosDiagnosticsThresholds);
// Create sync client
CosmosClient client = new CosmosClientBuilder()
.endpoint(AccountSettings.HOST)
.key(AccountSettings.MASTER_KEY)
.clientTelemetryConfig(cosmosClientTelemetryConfig)
.buildClient();
Проектирование повторных попыток
Ознакомьтесь с нашим руководством по проектированию устойчивых приложений с помощью SDK для Azure Cosmos DB, чтобы узнать, как проектировать устойчивые приложения и понять, какие повторные попытки поддерживаются SDK.
Распространенные проблемы и обходные решения для них
Проверка метрик портала
Проверка метрик портала помогает определить, возникла ли проблема на стороне клиента или возникла ли проблема со службой. Например, если метрики содержат много запросов подряд с кодом состояния HTTP 429 (ограничение количества), значит, к запросам применяется регулирование. В этом случае просмотрите сведения в разделе Слишком высокая частота запросов.
Проблемы с сетью, сбой времени ожидания чтения Netty, низкая пропускная способность, высокая задержка
Общие рекомендации
Обеспечить наилучшую производительность можно так.
- Убедитесь, что приложение запущено в том же регионе, что и учетная запись Azure Cosmos DB.
- Проверьте использование ЦП на узле, где работает приложение. Если загрузка ЦП составляет 50 процентов или больше, запустите приложение на узле с более высокой конфигурацией. Кроме того, вы можете распределить нагрузку на другие компьютеры.
- Если вы используете приложение в службе Azure Kubernetes, вы можете использовать Azure Monitor для мониторинга использования ЦП.
Регулирование подключений
Регулирование подключений может произойти из-за ограничения подключения на хост-компьютере или из-за истощения портов SNAT (PAT).
Ограничение подключения на хост-компьютере
Некоторые системы Linux, такие как Red Hat, имеют верхний предел общего количества открытых файлов. Сокеты в Linux реализованы в виде файлов, поэтому это число также ограничивает общее количество подключений. Выполните следующую команду.
ulimit -a
Максимально допустимое количество разрешенных открытых файлов, которые определяются как "nofile", должно быть по крайней мере в два раза больше размера пула подключений. Дополнительные сведения см. в советах по производительности пакета SDK java для Azure Cosmos DB версии 4.
Исчерпание портов SNAT (PAT) Azure
Если приложение развернуто на виртуальных машинах Azure без общедоступного IP-адреса, по умолчанию порты SNAT Azure устанавливают подключения к любой конечной точке за пределами виртуальной машины. Количество разрешенных подключений от виртуальной машины к конечной точке Azure Cosmos DB ограничивается конфигурацией Azure SNAT.
Порты SNAT Azure используются только в том случае, если у виртуальной машины есть частный IP-адрес, а процесс из виртуальной машины пытается подключиться к общедоступному IP-адресу. Существует два обходных решения, чтобы избежать ограничения SNAT Azure:
Добавьте конечную точку службы Azure Cosmos DB к подсети виртуальной сети для службы "Виртуальные машины Azure". Дополнительные сведения см. в статье Конечные точки служб для виртуальной сети Azure.
При включении конечной точки службы запросы больше не отправляются с общедоступного IP-адреса в Azure Cosmos DB. Вместо этого отправляются идентификаторы виртуальной сети и подсети. Это изменение может привести к сбою брандмауэра, если разрешены только общедоступные IP-адреса. Если вы используете брандмауэр, при включении конечной точки службы добавьте подсеть в брандмауэр с помощью ACL виртуальной сети.
Назначьте общедоступный IP-адрес виртуальной машине Azure.
Не удается добраться до службы — брандмауэр
ConnectTimeoutException указывает, что пакет SDK не может связаться со службой.
При использовании прямого режима может возникнуть сбой, аналогичный следующему:
GoneException{error=null, resourceAddress='https://cdb-ms-prod-westus-fd4.documents.azure.com:14940/apps/e41242a5-2d71-5acb-2e00-5e5f744b12de/services/d8aa21a5-340b-21d4-b1a2-4a5333e7ed8a/partitions/ed028254-b613-4c2a-bf3c-14bd5eb64500/replicas/131298754052060051p//', statusCode=410, message=Message: The requested resource is no longer available at the server., getCauseInfo=[class: class io.netty.channel.ConnectTimeoutException, message: connection timed out: cdb-ms-prod-westus-fd4.documents.azure.com/101.13.12.5:14940]
Если на компьютере приложения запущен брандмауэр, откройте диапазон портов от 10 000 до 20 000, которые используются в прямом режиме. Также следуйте ограничению подключения на хост-компьютере.
UnknownHostException
UnknownHostException означает, что платформа Java не может разрешить запись DNS для конечной точки Azure Cosmos DB на затронутом компьютере. Вы должны убедиться, что компьютер может разрешить запись DNS, или, если у вас есть пользовательское программное обеспечение для разрешения DNS (например, VPN, прокси-сервер или пользовательское решение), убедитесь, что оно содержит правильную конфигурацию для конечной точки DNS, о которой ошибка утверждает, что она не может быть разрешена. Если ошибка происходит постоянно, можно проверить разрешение DNS компьютера с помощью команды curl на конечной точке, описанной в этой ошибке.
Прокси-сервер HTTP
При использовании прокси-сервера HTTP убедитесь, что он может поддерживать число подключений, указанное в свойстве ConnectionPolicy пакета SDK.
В противном случае возникнут проблемы с подключением.
Недопустимый шаблон кодирования: блокировка потока ввода-вывода Netty
Пакет SDK использует библиотеку ввода-вывода Netty для взаимодействия с Azure Cosmos DB. Пакет SDK имеет асинхронный API и использует неблокирующие API ввода-вывода Netty. Работа ввода-вывода пакета SDK выполняется в потоках IO Netty. Число потоков IO Netty настроено так же, как и количество ядер ЦП компьютера приложения.
Потоки ввода-вывода Netty предназначены только для неблокировки работы интернета вещей. Пакет SDK возвращает результат вызова API для одного из потоков ввода-вывода Netty в код приложения. Если приложение выполняет долгосрочную операцию после получения результатов в потоке Netty, пакет SDK может не иметь достаточно потоков ввода-вывода для выполнения внутренних операций ввода-вывода. Такой код приложения может привести к низкой пропускной способности, высокой задержке и io.netty.handler.timeout.ReadTimeoutException сбоям. Обходной путь заключается в переключении потока, когда вы знаете, что операция занимает время.
Например, ознакомьтесь со следующим фрагментом кода, который добавляет элементы в контейнер (см. инструкции по настройке базы данных и контейнера). Вы можете выполнить долгосрочную работу, которая занимает более нескольких миллисекундах в потоке Netty. Если это так, в конечном итоге может возникнуть состояние, при котором отсутствует поток ввода-вывода Netty для обработки операций. В результате возникает сбой ReadTimeoutException.
Асинхронный API Java SDK версии 4 (Maven com.azure::azure-cosmos)
//Bad code with read timeout exception
int requestTimeoutInSeconds = 10;
/* ... */
AtomicInteger failureCount = new AtomicInteger();
// Max number of concurrent item inserts is # CPU cores + 1
Flux<Family> familyPub =
Flux.just(Families.getAndersenFamilyItem(), Families.getAndersenFamilyItem(), Families.getJohnsonFamilyItem());
familyPub.flatMap(family -> {
return container.createItem(family);
}).flatMap(r -> {
try {
// Time-consuming work is, for example,
// writing to a file, computationally heavy work, or just sleep.
// Basically, it's anything that takes more than a few milliseconds.
// Doing such operations on the IO Netty thread
// without a proper scheduler will cause problems.
// The subscriber will get a ReadTimeoutException failure.
TimeUnit.SECONDS.sleep(2 * requestTimeoutInSeconds);
} catch (Exception e) {
}
return Mono.empty();
}).doOnError(Exception.class, exception -> {
failureCount.incrementAndGet();
}).blockLast();
assert(failureCount.get() > 0);
Обходной путь — изменить поток, в котором выполняется работа, которая занимает время. Определите одиночный экземпляр планировщика для вашего приложения.
Асинхронный API Java SDK версии 4 (Maven com.azure::azure-cosmos)
// Have a singleton instance of an executor and a scheduler.
ExecutorService ex = Executors.newFixedThreadPool(30);
Scheduler customScheduler = Schedulers.fromExecutor(ex);
Возможно, вам потребуется выполнить работу, которая занимает время, например, вычислительно тяжелые задачи или блокирующие операции ввода-вывода. В этом случае переключите поток на рабочий, предоставленный вашим customScheduler, используя API .publishOn(customScheduler).
Асинхронный API Java SDK версии 4 (Maven com.azure::azure-cosmos)
container.createItem(family)
.publishOn(customScheduler) // Switches the thread.
.subscribe(
// ...
);
С помощью publishOn(customScheduler)вы освобождаете поток ввода-вывода Netty и переключаеесь на собственный пользовательский поток, предоставляемый настраиваемым планировщиком. Это изменение решает проблему. Вы больше не получите сбой io.netty.handler.timeout.ReadTimeoutException .
Высокая частота запросов
Этот сбой — это сбой на стороне сервера. Он указывает, что вы потребляли подготовленную пропускную способность. Повторите попытку позже. Если этот сбой часто возникает, рассмотрите возможность увеличения пропускной способности для обработки коллекции.
Реализация отката в интервалах getRetryAfterInMilliseconds
Во время тестирования производительности необходимо увеличивать нагрузку до тех пор, пока небольшая часть запросов не начнет ограничиваться. При ограничении в скорости клиентское приложение должно прекратить попытки на интервал повторных попыток, заданного сервером. Учитывая обратный выход, вы гарантируете, что вы тратите минимальное время ожидания между повторными попытками.
Обработка ошибок в реактивной цепочке Java SDK
Обработка ошибок из пакета SDK Java для Azure Cosmos DB важна, когда речь идет о логике приложения клиента. Существуют различные механизмы обработки ошибок, предоставляемые платформой реактора, которая может использоваться в различных сценариях. Мы рекомендуем клиентам подробно понять эти операторы обработки ошибок и использовать те, которые соответствуют сценариям логики повторных попыток лучше всего.
Это важно
Не рекомендуется использовать onErrorContinue() оператор, так как он не поддерживается во всех сценариях.
Обратите внимание, что onErrorContinue() - это специализированный оператор, который может сделать поведение вашей реактивной цепочки менее понятным. Он функционирует с входящими, а не исходящими операторами, требует поддержки со стороны конкретных операторов для своей работы, и область может легко распространяться вверх по цепочке в код библиотеки, который её не ожидал (что может привести к непреднамеренному поведению). Дополнительные сведения об этом специальном операторе см. в документацииonErrorContinue().
Сбой при подключении к эмулятору Azure Cosmos DB
Сертификат HTTPS эмулятора Azure Cosmos DB самозаверяется. Чтобы пакет SDK работал с эмулятором, импортируйте сертификат эмулятора в Java TrustStore. Дополнительные сведения см. в статье "Экспорт сертификатов эмулятора Azure Cosmos DB".
Проблемы с конфликтом зависимостей
Пакет SDK Java для Azure Cosmos DB извлекает множество зависимостей; Как правило, если дерево зависимостей проекта включает более старую версию артефакта, от которой зависит пакет SDK Java для Azure Cosmos DB, это может привести к непредвиденным ошибкам при запуске приложения. Если вы отлаживаете, почему ваше приложение неожиданно вызывает исключение, следует убедиться, что дерево зависимостей случайно не содержит более раннюю версию одной или нескольких зависимостей Java SDK для Azure Cosmos DB.
Решение этой проблемы заключается в том, чтобы определить, какие из зависимостей проекта привносят старую версию, и исключить транзитивную зависимость от этой старой версии, позволив Azure Cosmos DB Java SDK использовать более новую версию.
Чтобы определить, какая из зависимостей вашего проекта приносит более раннюю версию чего-то, от чего зависит Azure Cosmos DB Java SDK, выполните следующую команду в вашем файле pom.xml проекта.
mvn dependency:tree
Дополнительные сведения см. в руководстве по дереве зависимостей maven.
После того как вы знаете, какая зависимость проекта зависит от старой версии, можно изменить зависимость от этого lib в файле pom и исключить транзитивную зависимость, следуя приведенному ниже примеру (что предполагает, что ядро реактора является устаревшей зависимостью):
<dependency>
<groupId>${groupid-of-lib-which-brings-in-reactor}</groupId>
<artifactId>${artifactId-of-lib-which-brings-in-reactor}</artifactId>
<version>${version-of-lib-which-brings-in-reactor}</version>
<exclusions>
<exclusion>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</exclusion>
</exclusions>
</dependency>
Дополнительные сведения см. в руководстве по исключаемой транзитивной зависимости.
Включение ведения журнала пакета SDK для клиента
Пакет SDK Java для Azure Cosmos DB версии 4 использует SLF4j в качестве фасада для ведения журнала, который поддерживает работу с популярными платформами ведения журналов, такими как log4j и logback.
Например, если вы хотите использовать log4j в качестве фреймворка журналирования, добавьте в classpath Java следующие библиотеки.
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
Кроме того, добавьте конфигурацию log4j.
# this is a sample log4j configuration
# Set root logger level to INFO and its only appender to A1.
log4j.rootLogger=INFO, A1
log4j.category.com.azure.cosmos=INFO
#log4j.category.io.netty=OFF
#log4j.category.io.projectreactor=OFF
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %5X{pid} [%t] %-5p %c - %m%n
Дополнительные сведения см. в руководстве по ведению журнала sfl4j.
Статистика сети ОС
Выполните команду netstat, чтобы получить представление о количестве подключений в таких состояниях, как ESTABLISHED и CLOSE_WAIT.
В Linux можно выполнить следующую команду.
netstat -nap
В Windows можно выполнить одну и ту же команду с различными флагами аргументов:
netstat -abn
Отфильтруйте результат только для подключений к конечной точке Azure Cosmos DB.
Количество подключений к конечной точке Azure Cosmos DB в ESTABLISHED состоянии не может превышать размер настроенного пула подключений.
Многие подключения к конечной точке Azure Cosmos DB могут находиться в CLOSE_WAIT состоянии. Может быть более 1000. Число, настолько высокое, указывает на то, что соединения устанавливаются и разрываются быстро. Эта ситуация потенциально вызывает проблемы. Дополнительные сведения см. в разделе "Распространенные проблемы и обходные пути ".
Типичные проблемы с запросами
Метрики запросов помогают определить, где запрос тратит большую часть времени. С помощью метрик запроса можно узнать, какая часть работы выполняется во внутренней службе, а какая в клиенте. Дополнительные сведения см. в руководстве по повышению производительности запросов.
Дальнейшие шаги
- Сведения о рекомендациях по производительности пакета SDK для Java версии 4
- Узнайте о лучших практиках для Java SDK версии 4