Solucionar problemas de erros de aplicativo cliente em contas de armazenamento do Azure

Este artigo ajuda você a investigar erros de aplicativo cliente usando métricas, logs do lado do cliente e logs de recursos no Azure Monitor.

Diagnosticar erros

Os usuários do aplicativo podem notificá-lo de erros relatados pelo aplicativo cliente. O Azure Monitor também registra contagens de diferentes tipos de resposta (dimensões ResponseType ) de seus serviços de armazenamento, como NetworkError, ClientTimeoutError ou AuthorizationError. Embora o Azure Monitor registre apenas contagens de diferentes tipos de erro, você pode obter mais detalhes sobre solicitações individuais examinando logs do lado do servidor, do lado do cliente e da rede. Normalmente, o código HTTP status retornado pelo serviço de armazenamento fornecerá uma indicação de por que a solicitação falhou.

Observação

Lembre-se de que você deve esperar ver alguns erros intermitentes. Por exemplo, erros devido a condições transitórias de rede ou erros de aplicativo.

Os recursos a seguir são úteis para entender os códigos de erro e status relacionados ao armazenamento:

O cliente está recebendo mensagens HTTP 403 (proibidas)

Se o aplicativo cliente estiver gerando erros HTTP 403 (Proibido), uma causa provável é que o cliente esteja usando uma SAS (Assinatura de Acesso Compartilhado) expirada quando envia uma solicitação de armazenamento (embora outras causas possíveis incluam distorção de relógio, chaves inválidas e cabeçalhos vazios).

A Biblioteca de Clientes de Armazenamento para .NET permite coletar dados de log do lado do cliente relacionados às operações de armazenamento executadas pelo seu aplicativo. Para obter mais informações, consulte Log do lado do cliente com a Biblioteca de Clientes de Armazenamento do .NET.

A tabela a seguir mostra um exemplo do log do lado do cliente gerado pela Biblioteca de Clientes de Armazenamento que ilustra esse problema que ocorre:

Origem Verbosidade Verbosidade ID da solicitação do cliente Texto da operação
Microsoft.Azure.Storage Informações 3 85d077ab-... Starting operation with location Primary per location mode PrimaryOnly.
Microsoft.Azure.Storage Informações 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 Informações 3 85d077ab -... Waiting for response.
Microsoft.Azure.Storage Aviso 2 85d077ab -... Exception thrown while waiting for response: The remote server returned an error: (403) Forbidden.
Microsoft.Azure.Storage Informações 3 85d077ab -... Response received. Status code = 403, Request ID = <Request ID>, Content-MD5 = , ETag = .
Microsoft.Azure.Storage Aviso 2 85d077ab -... Exception thrown during the operation: The remote server returned an error: (403) Forbidden..
Microsoft.Azure.Storage Informações 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 Informações 3 85d077ab -... The next location has been set to Primary, based on the location mode.
Microsoft.Azure.Storage Erro 1 85d077ab -... Retry policy did not allow for a retry. Failing with The remote server returned an error: (403) Forbidden.

Nesse cenário, você deve investigar por que o token SAS está expirando antes que o cliente envie o token para o servidor:

  • Normalmente, você não deve definir uma hora de início ao criar um SAS para um cliente usar imediatamente. Se houver pequenas diferenças de relógio entre o host que gera o SAS usando o tempo atual e o serviço de armazenamento, é possível que o serviço de armazenamento receba um SAS que ainda não seja válido.

  • Não defina um tempo de validade muito curto em um SAS. Novamente, pequenas diferenças de relógio entre o host que gera o SAS e o serviço de armazenamento podem levar a uma SAS expirando mais cedo do que o previsto.

  • O parâmetro de versão na chave SAS (por exemplo, sv=2015-04-05) corresponde à versão da Biblioteca de Clientes de Armazenamento que você está usando? Recomendamos que você sempre use a versão mais recente da biblioteca de clientes de armazenamento.

  • Se você regenerar as chaves de acesso ao armazenamento, todos os tokens SAS existentes poderão ser invalidados. Esse problema poderá surgir se você gerar tokens SAS com um longo tempo de validade para os aplicativos cliente armazenarem em cache.

Se você estiver usando a Biblioteca de Clientes de Armazenamento para gerar tokens SAS, será fácil criar um token válido. No entanto, se você estiver usando a API REST de Armazenamento e construindo os tokens SAS manualmente, consulte Delegando acesso com uma Assinatura de Acesso Compartilhado.

O cliente está recebendo mensagens HTTP 404 (não encontradas)

Se o aplicativo cliente receber uma mensagem HTTP 404 (Não encontrada) do servidor, isso implica que o objeto que o cliente estava tentando usar (como uma entidade, tabela, blob, contêiner ou fila) não existe no serviço de armazenamento. Há várias razões possíveis para isso, como:

  • O cliente ou outro processo excluiu anteriormente o objeto.

  • Um problema de autorização de SAS (Assinatura de Acesso Compartilhado).

  • O código JavaScript do lado do cliente não tem permissão para acessar o objeto.

  • Falha de rede.

O cliente ou outro processo excluiu anteriormente o objeto

Em cenários em que o cliente está tentando ler, atualizar ou excluir dados em um serviço de armazenamento, é fácil identificar nos logs de recursos de armazenamento uma operação anterior que excluiu o objeto em questão do serviço de armazenamento. Geralmente, os dados de log mostram que outro usuário ou processo excluiu o objeto. Os logs do Azure Monitor (lado do servidor) mostram quando um cliente excluiu um objeto.

No cenário em que um cliente está tentando inserir um objeto, talvez não seja imediatamente óbvio por que isso resulta em uma resposta HTTP 404 (Não encontrada), dado que o cliente está criando um novo objeto. No entanto, se o cliente estiver criando um blob, ele deverá ser capaz de localizar o contêiner de blob. Se o cliente estiver criando uma mensagem, ele deverá ser capaz de encontrar uma fila. E se o cliente estiver adicionando uma linha, ele deve ser capaz de encontrar a tabela.

Você pode usar o log do lado do cliente da Biblioteca de Clientes de Armazenamento para entender melhor quando o cliente envia solicitações específicas para o serviço de armazenamento.

O log do lado do cliente a seguir gerado pela biblioteca do Cliente de Armazenamento ilustra o problema quando o cliente não consegue encontrar o contêiner para o blob que está criando. Este log inclui detalhes das seguintes operações de armazenamento:

ID do Pedido Operação
07b26a5d-... DeleteIfExists método para excluir o contêiner de blob. Essa operação inclui uma solicitação HEAD para marcar para a existência do contêiner.
e2d06d78... CreateIfNotExists método para criar o contêiner de blob. Essa operação inclui uma solicitação HEAD que verifica a existência do contêiner. O HEAD retorna uma mensagem 404, mas continua.
de8b1c3c-... UploadFromStream método para criar o blob. A PUT solicitação falha com uma mensagem 404

Entradas de log:

ID do Pedido Texto da Operação
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..

Neste exemplo, o log mostra que o cliente está intercalando solicitações do CreateIfNotExists método (ID da solicitação e2d06d78...) com as solicitações do UploadFromStream método (de8b1c3c-...). Essa intercalação acontece porque o aplicativo cliente está invocando esses métodos de forma assíncrona. Modifique o código assíncrono no cliente para garantir que ele crie o contêiner antes de tentar carregar qualquer dado em um blob nesse contêiner. Idealmente, você deve criar todos os contêineres com antecedência.

Um problema de autorização de SAS (Assinatura de Acesso Compartilhado)

Se o aplicativo cliente tentar usar uma chave SAS que não inclua as permissões necessárias para a operação, o serviço de armazenamento retornará uma mensagem HTTP 404 (Não encontrada) ao cliente. Ao mesmo tempo, nas métricas do Azure Monitor, você também verá um AuthorizationError para a dimensão ResponseType .

Investigue por que seu aplicativo cliente está tentando executar uma operação para a qual não foi concedida permissões.

O código JavaScript do lado do cliente não tem permissão para acessar o objeto

Se você estiver usando um cliente JavaScript e o serviço de armazenamento estiver retornando mensagens HTTP 404, marcar para os seguintes erros javaScript no navegador:

SEC7120: origem http://localhost:56309 não encontrada no cabeçalho Access-Control-Allow-Origin.
SCRIPT7002: XMLHttpRequest: erro de rede 0x80070005, o acesso é negado.

Observação

Você pode usar as Ferramentas de Desenvolvedor F12 na Internet Explorer para rastrear as mensagens trocadas entre o navegador e o serviço de armazenamento quando estiver solucionando problemas do JavaScript do lado do cliente.

Esses erros ocorrem porque o navegador da Web implementa a mesma restrição de segurança de política de origem que impede uma página da Web de chamar uma API em um domínio diferente do domínio do qual a página vem.

Para contornar o problema do JavaScript, você pode configurar o CORS (Compartilhamento de Recursos de Origem Cruzada) para o serviço de armazenamento que o cliente está acessando. Para obter mais informações, confira Suporte ao CORS (Compartilhamento de Recursos de Origem Cruzada) para Serviços de Armazenamento do Azure.

O exemplo de código a seguir mostra como configurar o serviço de blob para permitir que o JavaScript em execução no domínio Contoso acesse um blob no serviço de armazenamento de blobs:

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);

Falha na rede

Em algumas circunstâncias, pacotes de rede perdidos podem levar o serviço de armazenamento a retornar mensagens HTTP 404 ao cliente. Por exemplo, quando seu aplicativo cliente está excluindo uma entidade do serviço de tabela, você verá o cliente lançar uma exceção de armazenamento relatando uma mensagem "HTTP 404 (Não Encontrado)" status do serviço de tabela. Ao investigar a tabela no serviço de armazenamento de tabelas, você verá que o serviço excluiu a entidade conforme solicitado.

Os detalhes de exceção no cliente incluem a ID da solicitação (7e84f12d...) atribuída pelo serviço de tabela para a solicitação: você pode usar essas informações para localizar os detalhes da solicitação nos logs de recursos de armazenamento no Azure Monitor pesquisando em Campos que descrevem como a operação foi autenticada de entradas de log. Você também pode usar as métricas para identificar quando ocorrem falhas como essa e pesquisar os arquivos de log com base na hora em que as métricas registraram esse erro. Essa entrada de log mostra que a exclusão falhou com uma mensagem status "HTTP (404) Client Other Error". A mesma entrada de log também inclui a ID da solicitação gerada pelo cliente na client-request-id coluna (813ea74f...).

O log do lado do servidor também inclui outra entrada com o mesmo client-request-id valor (813ea74f...) para uma operação de exclusão bem-sucedida para a mesma entidade e do mesmo cliente. Essa operação de exclusão bem-sucedida ocorreu pouco antes da solicitação de exclusão com falha.

A causa mais provável desse cenário é que o cliente enviou uma solicitação de exclusão para a entidade para o serviço de tabela, que teve êxito, mas não recebeu um reconhecimento do servidor (talvez devido a um problema temporário de rede). O cliente então repetiu automaticamente a operação (usando o mesmo client-request-id), e essa nova tentativa falhou porque a entidade já havia sido excluída.

Se esse problema ocorrer com frequência, você deverá investigar por que o cliente não está recebendo reconhecimentos do serviço de tabela. Se o problema for intermitente, você deverá capturar o erro "HTTP (404) Não Encontrado" e fazer logon no cliente, mas permitir que o cliente continue.

O cliente está recebendo mensagens HTTP 409 (Conflito)

Quando um cliente exclui contêineres de blob, tabelas ou filas, há um breve período para que o nome fique disponível novamente. Se o código em seu aplicativo cliente excluir e recriar imediatamente um contêiner de blob usando o mesmo nome, o CreateIfNotExists método acabará falhando com o erro HTTP 409 (Conflito).

O aplicativo cliente deve usar nomes de contêiner exclusivos sempre que criar novos contêineres se o padrão de exclusão/recriação for comum.

As métricas mostram que entradas de log percentSuccess ou analytics baixas têm operações com status de transação do ClientOtherErrors

Uma dimensão ResponseType igual a um valor de êxito captura a porcentagem de operações que foram bem-sucedidas com base no código de status HTTP. As operações com códigos status de 2XX contam como bem-sucedidas, enquanto as operações com códigos status nos intervalos 3XX, 4XX e 5XX são contadas como mal sucedidas e reduzem o valor da métrica Success. Nos logs de recursos de armazenamento, essas operações são registradas com um status de transação do ClientOtherError.

Essas operações foram concluídas com êxito e, portanto, não afetam outras métricas, como disponibilidade. Alguns exemplos de operações que são executadas com êxito, mas que podem resultar em códigos http status mal sucedidos incluem:

  • ResourceNotFound (Not Found 404), por exemplo, de uma solicitação GET a um blob que não existe.
  • ResourceAlreadyExists (Conflict 409), por exemplo, de uma CreateIfNotExist operação em que o recurso já existe.
  • ConditionNotMet (Not Modified 304), por exemplo, de uma operação condicional como quando um cliente envia um ETag valor e um cabeçalho HTTP If-None-Match para solicitar uma imagem somente se ela tiver sido atualizada desde a última operação.

Você pode encontrar uma lista de códigos de erro comuns da API REST que os serviços de armazenamento retornam na página Códigos de Erro de API REST Comuns.

Confira também

Entre em contato conosco para obter ajuda

Se você tiver dúvidas ou precisar de ajuda, crie uma solicitação de suporte ou peça ajuda à comunidade de suporte do Azure. Você também pode enviar comentários sobre o produto para a comunidade de comentários do Azure.