Устранение ошибок клиентского приложения в учетных записях хранения Azure

Эта статья поможет вам исследовать ошибки клиентского приложения с помощью метрик, журналов на стороне клиента и журналов ресурсов в Azure Monitor.

Диагностика ошибок

Пользователи приложения могут уведомлять вас об ошибках, сообщаемых клиентским приложением. Azure Monitor также записывает количество различных типов ответов (измерений ResponseType ) из служб хранилища, таких как NetworkError, ClientTimeoutError или AuthorizationError. Хотя Azure Monitor записывает только количество ошибок разных типов, вы можете получить дополнительные сведения об отдельных запросах, изучив журналы на стороне сервера, клиента и сети. Как правило, код состояния HTTP, возвращаемый службой хранилища, указывает, почему произошел сбой запроса.

Примечание.

Помните, что следует ожидать появления некоторых периодических ошибок. Например, ошибки из-за временных условий сети или ошибки приложения.

Следующие ресурсы полезны для понимания состояния и кодов ошибок, связанных с хранилищем:

Клиент получает сообщения HTTP 403 (запрещено)

Если клиентское приложение выдает ошибки HTTP 403 (запрещено), скорее всего, клиент использует подписанный url-адрес (SAS) с истекшим сроком действия при отправке запроса на хранение (хотя другие возможные причины включают неравномерное распределение часов, недопустимые ключи и пустые заголовки).

Клиентская библиотека хранилища для .NET позволяет собирать данные журнала на стороне клиента, связанные с операциями хранения, выполняемыми приложением. Дополнительные сведения см. в статье Ведение журнала на стороне клиента с помощью клиентской библиотеки хранилища .NET.

В следующей таблице показан пример из клиентского журнала на стороне клиента, созданного клиентской библиотекой хранилища, который иллюстрирует эту проблему:

Source Детализации Детализации Идентификатор запроса клиента Текст операции
Microsoft.Azure.Storage Сведения 3 85d077ab-... Starting operation with location Primary per location mode PrimaryOnly.
Microsoft.Azure.Storage Сведения 3 85d077ab -... Starting synchronous request to <https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests#Synchronous_request>
Microsoft.Azure.Storage Сведения 3 85d077ab -... Waiting for response.
Microsoft.Azure.Storage Предупреждение 2 85d077ab -... Exception thrown while waiting for response: The remote server returned an error: (403) Forbidden.
Microsoft.Azure.Storage Сведения 3 85d077ab -... Response received. Status code = 403, Request ID = <Request ID>, Content-MD5 = , ETag = .
Microsoft.Azure.Storage Предупреждение 2 85d077ab -... Exception thrown during the operation: The remote server returned an error: (403) Forbidden..
Microsoft.Azure.Storage Сведения 3 85d077ab -... Checking if the operation should be retried. Retry count = 0, HTTP status code = 403, Exception = The remote server returned an error: (403) Forbidden..
Microsoft.Azure.Storage Сведения 3 85d077ab -... The next location has been set to Primary, based on the location mode.
Microsoft.Azure.Storage Error 1 85d077ab -... Retry policy did not allow for a retry. Failing with The remote server returned an error: (403) Forbidden.

В этом сценарии следует выяснить, почему истекает срок действия маркера SAS, прежде чем клиент отправит маркер на сервер:

  • Как правило, не следует задавать время начала при создании SAS для немедленного использования клиентом. Если между узлом, создающим SAS с использованием текущего времени, и службой хранилища есть небольшие различия в часах, служба хранилища может получить sas, который еще не действителен.

  • Не устанавливайте очень короткое время истечения срока действия для SAS. Опять же, небольшие различия между узлом, создающим SAS, и службой хранилища могут привести к истечению срока действия SAS раньше, чем ожидалось.

  • Соответствует ли параметр version в ключе SAS (например, sv=2015-04-05) версии используемой клиентской библиотеки хранилища? Рекомендуется всегда использовать последнюю версию клиентской библиотеки хранилища.

  • При повторном создании ключей доступа к хранилищу все существующие маркеры SAS могут быть признаны недействительными. Эта проблема может возникнуть при создании маркеров SAS с длительным сроком действия для кэша клиентских приложений.

Если вы используете клиентскую библиотеку хранилища для создания маркеров SAS, можно легко создать допустимый маркер. Однако если вы используете REST API хранилища и создаете маркеры SAS вручную, см. раздел Делегирование доступа с помощью подписанного url-адреса.

Клиент получает сообщения HTTP 404 (не найдено)

Если клиентское приложение получает сообщение HTTP 404 (не найдено) от сервера, это означает, что объект, который клиент пытался использовать (например, сущность, таблица, большой двоичный объект, контейнер или очередь), не существует в службе хранилища. Для этого есть ряд возможных причин, например:

  • Клиент или другой процесс ранее удалил объект .

  • Проблема с авторизацией подписанного URL-адреса (SAS).

  • Клиентский код JavaScript не имеет разрешения на доступ к объекту.

  • Сбой сети.

Клиент или другой процесс ранее удалил объект

В сценариях, когда клиент пытается считывать, обновлять или удалять данные в службе хранилища, легко определить в журналах ресурсов хранилища предыдущую операцию, которая удаляла объект из службы хранилища. Часто данные журнала показывают, что другой пользователь или процесс удалил объект. Журналы Azure Monitor (на стороне сервера) показывают, когда клиент удалил объект.

В сценарии, когда клиент пытается вставить объект, может быть не сразу понятно, почему это приводит к ответу HTTP 404 (Не найдено), учитывая, что клиент создает новый объект. Однако если клиент создает большой двоичный объект, он должен иметь возможность найти контейнер BLOB-объектов. Если клиент создает сообщение, он должен иметь возможность найти очередь. И если клиент добавляет строку, он должен иметь возможность найти таблицу.

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

Следующий журнал на стороне клиента, созданный клиентской библиотекой хранилища, иллюстрирует проблему, когда клиенту не удается найти контейнер для большого двоичного объекта, который он создает. Этот журнал содержит сведения о следующих операциях хранения:

Идентификатор запроса Operation
07b26a5d-... DeleteIfExists метод для удаления контейнера BLOB-объектов. Эта операция включает HEAD запрос на проверка для существования контейнера.
e2d06d78... CreateIfNotExists метод для создания контейнера BLOB-объектов. Эта операция включает HEAD запрос, который проверяет наличие контейнера. Возвращает HEAD сообщение 404, но продолжается.
de8b1c3c-... UploadFromStream метод для создания большого двоичного объекта. Сбой PUT запроса с сообщением 404

Записи журнала:

Идентификатор запроса Текст операции
07b26a5d-... Starting synchronous request to https://domemaildist.blob.core.windows.net/azuremmblobcontainer.
07b26a5d-... StringToSign = HEAD............x-ms-client-request-id:07b26a5d-....x-ms-date:Tue, 03 Jun 2014 10:33:11 GMT.x-ms-version:2014-02-14./domemaildist/azuremmblobcontainer.restype:container.
07b26a5d-... Waiting for response.
07b26a5d-... Response received. Status code = 200, Request ID = eeead849-...Content-MD5 = , ETag = &quot;0x8D14D2DC63D059B&quot;.
07b26a5d-... Response headers were processed successfully, proceeding with the rest of the operation.
07b26a5d-... Downloading response body.
07b26a5d-... Operation completed successfully.
07b26a5d-... Starting synchronous request to https://domemaildist.blob.core.windows.net/azuremmblobcontainer.
07b26a5d-... StringToSign = DELETE............x-ms-client-request-id:07b26a5d-....x-ms-date:Tue, 03 Jun 2014 10:33:12 GMT.x-ms-version:2014-02-14./domemaildist/azuremmblobcontainer.restype:container.
07b26a5d-... Waiting for response.
07b26a5d-... Response received. Status code = 202, Request ID = 6ab2a4cf-..., Content-MD5 = , ETag = .
07b26a5d-... Response headers were processed successfully, proceeding with the rest of the operation.
07b26a5d-... Downloading response body.
07b26a5d-... Operation completed successfully.
e2d06d78-... Starting asynchronous request to https://domemaildist.blob.core.windows.net/azuremmblobcontainer.
e2d06d78-... StringToSign = HEAD............x-ms-client-request-id:e2d06d78-....x-ms-date:Tue, 03 Jun 2014 10:33:12 GMT.x-ms-version:2014-02-14./domemaildist/azuremmblobcontainer.restype:container.
e2d06d78-... Waiting for response.
de8b1c3c-... Starting synchronous request to https://domemaildist.blob.core.windows.net/azuremmblobcontainer/blobCreated.txt.
de8b1c3c-... StringToSign = PUT...64.qCmF+TQLPhq/YYK50mP9ZQ==........x-ms-blob-type:BlockBlob.x-ms-client-request-id:de8b1c3c-....x-ms-date:Tue, 03 Jun 2014 10:33:12 GMT.x-ms-version:2014-02-14./domemaildist/azuremmblobcontainer/blobCreated.txt.
de8b1c3c-... Preparing to write request data.
e2d06d78-... Exception thrown while waiting for response: The remote server returned an error: (404) Not Found..
e2d06d78-... Response received. Status code = 404, Request ID = 353ae3bc-..., Content-MD5 = , ETag = .
e2d06d78-... Response headers were processed successfully, proceeding with the rest of the operation.
e2d06d78-... Downloading response body.
e2d06d78-... Operation completed successfully.
e2d06d78-... Starting asynchronous request to https://domemaildist.blob.core.windows.net/azuremmblobcontainer.
e2d06d78-... StringToSign = PUT...0.........x-ms-client-request-id:e2d06d78-....x-ms-date:Tue, 03 Jun 2014 10:33:12 GMT.x-ms-version:2014-02-14./domemaildist/azuremmblobcontainer.restype:container.
e2d06d78-... Waiting for response.
de8b1c3c-... Writing request data.
de8b1c3c-... Waiting for response.
e2d06d78-... Exception thrown while waiting for response: The remote server returned an error: (409) Conflict..
e2d06d78-... Response received. Status code = 409, Request ID = c27da20e-..., Content-MD5 = , ETag = .
e2d06d78-... Downloading error response body.
de8b1c3c-... Exception thrown while waiting for response: The remote server returned an error: (404) Not Found..
de8b1c3c-... Response received. Status code = 404, Request ID = 0eaeab3e-..., Content-MD5 = , ETag = .
de8b1c3c-... Exception thrown during the operation: The remote server returned an error: (404) Not Found..
de8b1c3c-... Retry policy did not allow for a retry. Failing with The remote server returned an error: (404) Not Found..
e2d06d78-... Retry policy did not allow for a retry. Failing with The remote server returned an error: (409) Conflict..

В этом примере журнал показывает, что клиент чередует запросы из CreateIfNotExists метода (идентификатор запроса e2d06d78...) с запросами из UploadFromStream метода (de8b1c3c-...). Это чередование происходит из-за того, что клиентское приложение асинхронно вызывает эти методы. Измените асинхронный код в клиенте, чтобы убедиться, что он создает контейнер, прежде чем пытаться передать данные в большой двоичный объект в этом контейнере. В идеале все контейнеры следует создать заранее.

Проблема с авторизацией подписанного URL-адреса (SAS)

Если клиентское приложение пытается использовать ключ SAS, который не содержит необходимых разрешений для операции, служба хранилища возвращает клиенту сообщение HTTP 404 (не найдено). В то же время в метриках Azure Monitor вы также увидите AuthorizationError для измерения ResponseType .

Изучите, почему клиентское приложение пытается выполнить операцию, для которой ему не были предоставлены разрешения.

Клиентский код JavaScript не имеет разрешения на доступ к объекту

Если вы используете клиент JavaScript и служба хранилища возвращает сообщения HTTP 404, проверка для следующих ошибок JavaScript в браузере:

SEC7120: источник http://localhost:56309 не найден в заголовке Access-Control-Allow-Origin.
SCRIPT7002: XMLHttpRequest: сетевая ошибка 0x80070005, доступ запрещен.

Примечание.

Средства разработчика F12 в Интернете Обозреватель можно использовать для трассировки сообщений, передаваемых между браузером и службой хранилища при устранении неполадок с JavaScript на стороне клиента.

Эти ошибки возникают из-за того, что веб-браузер реализует одно и то же ограничение безопасности политики источника , которое не позволяет веб-странице вызывать API в другом домене из домена, из который поступает страница.

Чтобы обойти проблему JavaScript, можно настроить общий доступ к ресурсам между источниками (CORS) для службы хранилища, к ней обращается клиент. Дополнительные сведения см. в статье Поддержка общего доступа к ресурсам между источниками (CORS) для служб хранилища Azure.

В следующем примере кода показано, как настроить службу BLOB-объектов, чтобы разрешить JavaScript, работающему в домене Contoso, доступ к BLOB-объекту в службе хранилища BLOB-объектов:

var connectionString = Constants.connectionString;

 BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);

 BlobServiceProperties sp = blobServiceClient.GetProperties();

 // Set the service properties.
 sp.DefaultServiceVersion = "2013-08-15";
 BlobCorsRule bcr = new BlobCorsRule();
 bcr.AllowedHeaders = "*";

 bcr.AllowedMethods = "GET,POST";
 bcr.AllowedOrigins = "http://www.contoso.com";
 bcr.ExposedHeaders = "x-ms-*";
 bcr.MaxAgeInSeconds = 5;
 sp.Cors.Clear();
 sp.Cors.Add(bcr);
 blobServiceClient.SetProperties(sp);

Сбой сети

В некоторых случаях потерянные сетевые пакеты могут привести к тому, что служба хранилища вернет клиенту сообщения HTTP 404. Например, когда клиентское приложение удаляет сущность из службы таблиц, вы увидите, что клиент выдает исключение хранилища с сообщением о состоянии "HTTP 404 (не найдено)" из службы таблиц. При изучении таблицы в службе хранилища таблиц вы увидите, что служба удалила сущность в соответствии с запросом.

Сведения об исключении в клиенте включают идентификатор запроса (7e84f12d...), назначенный службой таблиц для запроса. Эти сведения можно использовать для поиска сведений о запросах в журналах ресурсов хранилища в Azure Monitor, выполнив поиск в полях, описывающих проверку подлинности операций для записей журнала. Вы также можете использовать метрики, чтобы определить, когда происходят сбои, а затем выполнить поиск в файлах журнала в зависимости от времени, когда метрики записали эту ошибку. Эта запись журнала показывает, что удаление завершилось ошибкой с сообщением о состоянии "HTTP (404) Client Other Error". Та же запись журнала также включает идентификатор запроса, созданного клиентом в столбце client-request-id (813ea74f...).

Серверный журнал также содержит другую запись с тем же client-request-id значением (813ea74f...) для успешной операции удаления для той же сущности и из того же клиента. Эта операция удаления была выполнена незадолго до неудачного запроса на удаление.

Наиболее вероятной причиной этого сценария является отправка клиентом запроса на удаление сущности в службу таблиц, которая завершилась успешно, но не получила подтверждение от сервера (возможно, из-за временной проблемы с сетью). Затем клиент автоматически повторил операцию (используя тот же client-request-id), и эта попытка завершилась ошибкой, так как сущность уже была удалена.

Если эта проблема возникает часто, следует выяснить, почему клиент не получает подтверждения от службы таблиц. Если проблема возникает периодически, следует перехватить ошибку "HTTP (404) Not Found" и записать ее в клиент, но разрешить клиенту продолжить работу.

Клиент получает сообщения HTTP 409 (конфликт)

При удалении клиентом контейнеров BLOB-объектов, таблиц или очередей существует короткий период, прежде чем имя снова станет доступным. Если код в клиентском приложении удаляется, а затем немедленно воссоздает контейнер BLOB-объектов с тем же именем, CreateIfNotExists метод в конечном итоге завершается ошибкой HTTP 409 (конфликт).

Клиентское приложение должно использовать уникальные имена контейнеров при создании новых контейнеров, если шаблон удаления и повторного создания является общим.

Метрики показывают низкий процентSuccess или записи журнала аналитики имеют операции с состоянием транзакции ClientOtherErrors

Измерение ResponseType , равное значению Success , фиксирует процент успешных операций на основе их кода состояния HTTP. Операции с кодами состояния 2XX считаются успешными, тогда как операции с кодами состояния в диапазонах 3XX, 4XX и 5XX считаются неудачными и понижают значение метрики Успешно. В журналах ресурсов хранилища эти операции записываются с состоянием транзакции ClientOtherError.

Эти операции успешно завершены и, следовательно, не влияют на другие метрики, такие как доступность. Ниже приведены некоторые примеры операций, которые выполняются успешно, но могут привести к неудачным кодам состояния HTTP:

  • ResourceNotFound (Не найдено 404), например, из запроса GET к не существующему BLOB-объекту.
  • ResourceAlreadyExists (Conflict 409), например, из операции, в которой CreateIfNotExist ресурс уже существует.
  • ConditionNotMet (не изменено 304), например из условной операции, например, когда клиент отправляет ETag значение и http-заголовок If-None-Match для запроса изображения только в том случае, если оно было обновлено с момента последней операции.

Список распространенных кодов ошибок REST API, возвращаемых службами хранилища, можно найти на странице Общие коды ошибок REST API.

См. также

Свяжитесь с нами для получения помощи

Если у вас есть вопросы или вам нужна помощь, создайте запрос в службу поддержки или обратитесь за поддержкой сообщества Azure. Вы также можете отправить отзыв о продукте в сообщество отзывов Azure.