Résoudre les erreurs d’application cliente dans les comptes de stockage Azure

Cet article vous aide à examiner les erreurs d’application cliente en utilisant des métriques, des journaux côté client et des journaux de ressources dans Azure Monitor.

Diagnostic des erreurs

Les utilisateurs de votre application peuvent vous informer des erreurs signalées par l’application cliente. Azure Monitor enregistre également le nombre de différents types de réponse (dimensions ResponseType ) à partir de vos services de stockage, tels que NetworkError, ClientTimeoutError ou AuthorizationError. Bien qu’Azure Monitor enregistre uniquement le nombre de différents types d’erreurs, vous pouvez obtenir plus de détails sur les demandes individuelles en examinant les journaux côté serveur, côté client et réseau. En règle générale, le code status HTTP retourné par le service de stockage donne une indication de la raison de l’échec de la requête.

Remarque

N’oubliez pas que vous devez vous attendre à voir des erreurs intermittentes. Par exemple, les erreurs dues à des conditions réseau temporaires ou à des erreurs d’application.

Les ressources suivantes sont utiles pour comprendre les status et les codes d’erreur liés au stockage :

Le client reçoit des messages HTTP 403 (Interdit)

Si votre application cliente génère des erreurs HTTP 403 (Interdit), une cause probable est que le client utilise une signature d’accès partagé (SAP) expirée lorsqu’il envoie une demande de stockage (bien que d’autres causes possibles incluent l’asymétrie de l’horloge, les clés non valides et les en-têtes vides).

La bibliothèque cliente de stockage pour .NET vous permet de collecter des données de journal côté client relatives aux opérations de stockage effectuées par votre application. Pour plus d’informations, consultez Journalisation côté client avec la bibliothèque cliente de stockage .NET.

Le tableau suivant présente un exemple du journal côté client généré par la bibliothèque cliente de stockage qui illustre ce problème :

Source Verbosité Verbosité ID de demande client Texte de l’opération
Microsoft.Azure.Storage Information 3 85d077ab-... Starting operation with location Primary per location mode PrimaryOnly.
Microsoft.Azure.Storage Information 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 Information 3 85d077ab -... Waiting for response.
Microsoft.Azure.Storage Avertissement 2 85d077ab -... Exception thrown while waiting for response: The remote server returned an error: (403) Forbidden.
Microsoft.Azure.Storage Information 3 85d077ab -... Response received. Status code = 403, Request ID = <Request ID>, Content-MD5 = , ETag = .
Microsoft.Azure.Storage Avertissement 2 85d077ab -... Exception thrown during the operation: The remote server returned an error: (403) Forbidden..
Microsoft.Azure.Storage Information 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 Information 3 85d077ab -... The next location has been set to Primary, based on the location mode.
Microsoft.Azure.Storage Erreur 1 85d077ab -... Retry policy did not allow for a retry. Failing with The remote server returned an error: (403) Forbidden.

Dans ce scénario, vous devez examiner pourquoi le jeton SAP expire avant que le client n’envoie le jeton au serveur :

  • En règle générale, vous ne devez pas définir une heure de début lorsque vous créez une signature d’accès partagé pour un client à utiliser immédiatement. S’il existe de petites différences d’horloge entre l’hôte générant la SAP à l’aide de l’heure actuelle et le service de stockage, il est possible que le service de stockage reçoive une signature d’accès partagé qui n’est pas encore valide.

  • Ne définissez pas un délai d’expiration très court sur une signature d’accès partagé. Là encore, de petites différences d’horloge entre l’hôte générant la sape et le service de stockage peuvent entraîner l’expiration d’une signature d’accès partagé plus tôt que prévu.

  • Le paramètre de version dans la clé SAP (par exemple, sv=2015-04-05) correspond-il à la version de la bibliothèque cliente de stockage que vous utilisez ? Nous vous recommandons de toujours utiliser la dernière version de la bibliothèque cliente de stockage.

  • Si vous régénérez vos clés d’accès de stockage, tous les jetons SAP existants peuvent être invalidés. Ce problème peut survenir si vous générez des jetons SAP avec un délai d’expiration long pour les applications clientes à mettre en cache.

Si vous utilisez la bibliothèque cliente de stockage pour générer des jetons SAS, il est facile de générer un jeton valide. Toutefois, si vous utilisez l’API REST de stockage et que vous construisez les jetons SAP manuellement, consultez Délégation de l’accès avec une signature d’accès partagé.

Le client reçoit des messages HTTP 404 (introuvable)

Si l’application cliente reçoit un message HTTP 404 (introuvable) du serveur, cela implique que l’objet que le client tentait d’utiliser (par exemple, une entité, une table, un objet blob, un conteneur ou une file d’attente) n’existe pas dans le service de stockage. Il existe un certain nombre de raisons possibles à cela, telles que :

  • Le client ou un autre processus a précédemment supprimé l’objet.

  • Problème d’autorisation de signature d’accès partagé (SAP).

  • Le code JavaScript côté client n’est pas autorisé à accéder à l’objet.

  • Défaillance réseau.

Le client ou un autre processus a précédemment supprimé l’objet

Dans les scénarios où le client tente de lire, mettre à jour ou supprimer des données dans un service de stockage, il est facile d’identifier dans les journaux de ressources de stockage une opération précédente qui a supprimé l’objet en question du service de stockage. Souvent, les données de journal indiquent qu’un autre utilisateur ou processus a supprimé l’objet. Les journaux Azure Monitor (côté serveur) indiquent quand un client a supprimé un objet.

Dans le scénario où un client tente d’insérer un objet, la raison pour laquelle cela entraîne une réponse HTTP 404 (Introuvable) n’est peut-être pas immédiatement évidente, étant donné que le client crée un nouvel objet. Toutefois, si le client crée un objet blob, il doit être en mesure de trouver le conteneur d’objets blob. Si le client crée un message, il doit être en mesure de trouver une file d’attente. Et si le client ajoute une ligne, il doit être en mesure de trouver la table.

Vous pouvez utiliser le journal côté client de la bibliothèque cliente de stockage pour mieux comprendre quand le client envoie des demandes spécifiques au service de stockage.

Le journal côté client suivant généré par la bibliothèque cliente de stockage illustre le problème lorsque le client ne trouve pas le conteneur pour l’objet blob qu’il crée. Ce journal contient les détails des opérations de stockage suivantes :

ID de la demande Opération
07b26a5d-... DeleteIfExists pour supprimer le conteneur d’objets blob. Cette opération inclut une demande HEAD à case activée pour l’existence du conteneur.
e2d06d78... CreateIfNotExists pour créer le conteneur d’objets blob. Cette opération inclut une HEAD requête qui vérifie l’existence du conteneur. Retourne HEAD un message 404, mais continue.
de8b1c3c-... UploadFromStream pour créer l’objet blob. La PUT demande échoue avec un message 404

Entrées de journal :

ID de la demande Texte de l’opération
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..

Dans cet exemple, le journal indique que le client entrelace les requêtes de la CreateIfNotExists méthode (ID de requête e2d06d78...) avec les requêtes de la UploadFromStream méthode (de8b1c3c-...). Cet entrelacement se produit car l’application cliente appelle ces méthodes de manière asynchrone. Modifiez le code asynchrone dans le client pour vous assurer qu’il crée le conteneur avant de tenter de charger des données dans un objet blob dans ce conteneur. Dans l’idéal, vous devez créer tous vos conteneurs à l’avance.

Problème d’autorisation de signature d’accès partagé (SAP)

Si l’application cliente tente d’utiliser une clé SAP qui n’inclut pas les autorisations nécessaires pour l’opération, le service de stockage retourne un message HTTP 404 (Introuvable) au client. En même temps, dans les métriques Azure Monitor, vous verrez également un AuthorizationError pour la dimension ResponseType .

Examinez pourquoi votre application cliente tente d’effectuer une opération pour laquelle aucune autorisation n’a été accordée.

Le code JavaScript côté client n’a pas l’autorisation d’accéder à l’objet

Si vous utilisez un client JavaScript et que le service de stockage retourne des messages HTTP 404, case activée pour les erreurs JavaScript suivantes dans le navigateur :

SEC7120 : Origine http://localhost:56309 introuvable dans l’en-tête Access-Control-Allow-Origin.
SCRIPT7002 : XMLHttpRequest : erreur réseau 0x80070005, accès refusé.

Remarque

Vous pouvez utiliser les outils de développement F12 dans Internet Explorer pour suivre les messages échangés entre le navigateur et le service de stockage lorsque vous résolvez des problèmes JavaScript côté client.

Ces erreurs se produisent parce que le navigateur web implémente la même restriction de sécurité de stratégie d’origine qui empêche une page web d’appeler une API dans un domaine différent du domaine d’origine de la page.

Pour contourner le problème JavaScript, vous pouvez configurer cors (Cross-Origin Resource Sharing) pour le service de stockage auquel le client accède. Pour plus d’informations, consultez Prise en charge du partage de ressources cross-origin (CORS) pour les services de stockage Azure.

L’exemple de code suivant montre comment configurer votre service blob pour permettre à JavaScript s’exécutant dans le domaine Contoso d’accéder à un objet blob dans votre service de stockage d’objets 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);

Réseau défaillant

Dans certains cas, la perte de paquets réseau peut entraîner le renvoi des messages HTTP 404 au client par le service de stockage. Par exemple, lorsque votre application cliente supprime une entité du service de table, vous voyez le client lever une exception de stockage signalant un message status « HTTP 404 (introuvable) » du service de table. Lorsque vous examinez la table dans le service de stockage de table, vous voyez que le service a supprimé l’entité comme demandé.

Les détails de l’exception dans le client incluent l’ID de demande (7e84f12d...) attribué par le service de table pour la demande : vous pouvez utiliser ces informations pour localiser les détails de la demande dans les journaux de ressources de stockage dans Azure Monitor en recherchant dans Champs qui décrivent comment l’opération a été authentifiée des entrées de journal. Vous pouvez également utiliser les métriques pour identifier les défaillances de ce type, puis rechercher dans les fichiers journaux en fonction de l’heure à laquelle les métriques ont enregistré cette erreur. Cette entrée de journal indique que la suppression a échoué avec un message status « Erreur http (404) autre client ». La même entrée de journal inclut également l’ID de requête généré par le client dans la client-request-id colonne (813ea74f...).

Le journal côté serveur inclut également une autre entrée avec la même client-request-id valeur (813ea74f...) pour une opération de suppression réussie pour la même entité et à partir du même client. Cette opération de suppression réussie a eu lieu peu de temps avant l’échec de la demande de suppression.

La cause la plus probable de ce scénario est que le client a envoyé une demande de suppression pour l’entité au service de table, qui a réussi mais n’a pas reçu d’accusé de réception du serveur (peut-être en raison d’un problème réseau temporaire). Le client a ensuite retenté automatiquement l’opération (à l’aide du même client-request-id), et cette nouvelle tentative a échoué, car l’entité avait déjà été supprimée.

Si ce problème se produit fréquemment, vous devez examiner pourquoi le client ne parvient pas à recevoir les accusés de réception du service de table. Si le problème est intermittent, vous devez intercepter l’erreur « HTTP (404) Introuvable » et la journaliser dans le client, mais autoriser le client à continuer.

Le client reçoit des messages HTTP 409 (conflit)

Lorsqu’un client supprime des conteneurs d’objets blob, des tables ou des files d’attente, il existe un bref délai avant que le nom ne soit à nouveau disponible. Si le code de votre application cliente supprime, puis recrée immédiatement un conteneur d’objets blob avec le même nom, la CreateIfNotExists méthode échoue finalement avec l’erreur HTTP 409 (conflit).

L’application cliente doit utiliser des noms de conteneurs uniques chaque fois qu’elle crée de nouveaux conteneurs si le modèle de suppression/recréation est courant.

Les métriques indiquent que les entrées de journal PercentSuccess ou analytics faibles ont des opérations avec des status de transaction de ClientOtherErrors

Une dimension ResponseType égale à une valeur de Success capture le pourcentage d’opérations qui ont réussi en fonction de leur code d’état HTTP. Les opérations avec des codes status 2XX sont comptabilisées comme ayant réussi, tandis que les opérations avec des codes status dans les plages 3XX, 4XX et 5XX sont comptabilisées comme ayant échoué et réduisent la valeur de la métrique Réussite. Dans les journaux des ressources de stockage, ces opérations sont enregistrées avec une transaction status de ClientOtherError.

Ces opérations se sont terminées correctement et n’affectent donc pas d’autres métriques, telles que la disponibilité. Voici quelques exemples d’opérations qui s’exécutent correctement, mais qui peuvent entraîner l’échec des codes de status HTTP :

  • ResourceNotFound (Not Found 404), par exemple, à partir d’une requête GET vers un objet blob qui n’existe pas.
  • ResourceAlreadyExists (Conflit 409), par exemple, à partir d’une CreateIfNotExist opération où la ressource existe déjà.
  • ConditionNotMet (Non modifié 304), par exemple, à partir d’une opération conditionnelle telle qu’un client envoie une ETag valeur et un en-tête HTTP If-None-Match pour demander une image uniquement si elle a été mise à jour depuis la dernière opération.

Vous trouverez la liste des codes d’erreur courants de l’API REST que les services de stockage retournent dans la page Codes d’erreur d’API REST courants.

Voir aussi

Contactez-nous pour obtenir de l’aide

Pour toute demande ou assistance, créez une demande de support ou posez une question au support de la communauté Azure. Vous pouvez également soumettre des commentaires sur les produits à la communauté de commentaires Azure.