Поделиться через


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

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

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

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

Примечание.

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

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

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

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

С помощью клиентской библиотеки хранилища для .NET вы можете собирать на стороне клиента данные журнала, связанные с операциями хранилища, которые выполняются приложением. Дополнительные сведения см. в статье Client-side Logging with the .NET Storage Client Library (Ведение журналов на стороне клиента с помощью клиентской библиотеки хранилища для .NET).

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

Исходный код Уровень детализации Уровень детализации Идентификатор запроса клиента Operation Text
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 Ошибка 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 истечет раньше, чем ожидалось.

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

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

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

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

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

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

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

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

  • Сбой сети.

Объект удален ранее клиентом или другим процессом.

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

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

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

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

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

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

Идентификатор запроса Operation Text
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..

В этом примере журнал показывает, что клиент чередует запросы из метода (идентификатор запроса e2d06d78...) с запросами из CreateIfNotExists 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 в Internet Explorer можно использовать для трассировки сообщений, обмениваемых между браузером и службой хранилища при устранении неполадок JavaScript на стороне клиента.

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

Чтобы обойти проблему JavaScript, можно настроить общий доступ к ресурсам между источниками (CORS) для службы хранилища, к ней обращается клиент. Дополнительные сведения см. в статье Cross-Origin Resource Sharing (CORS) Support for Azure Storage Services (Поддержка общего доступа к ресурсам независимо от источника (CORS) для служб хранилища Azure).

В этом примере кода показано, как настроить службу BLOB-объектов, чтобы разрешить работу приложения JavaScript в домене Contoso для получения доступа к хранящемуся в ней 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) — не найдено» и внести ее в журнал клиента, но позволить клиенту продолжить работу.

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

Когда клиент удаляет контейнеры больших двоичных объектов, таблицы или очереди, перед тем как имя станет доступным снова, существует короткий период. Если код в клиентском приложении удаляется, а затем немедленно создает контейнер БОЛЬШИХ двоичных объектов с тем же именем, CreateIfNotExists метод в конечном итоге завершается ошибкой HTTP 409 (Конфликт).

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

Метрики отображают низкое значение PercentSuccess или в записях журналов аналитики присутствуют операции с состоянием транзакции ClientOtherErrors

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

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

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

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

См. также

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

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