Rozwiązywanie problemów z błędami aplikacji klienckich na kontach usługi Azure Storage

Ten artykuł ułatwia badanie błędów aplikacji klienckich przy użyciu metryk, dzienników po stronie klienta i dzienników zasobów w usłudze Azure Monitor.

Diagnozowanie błędów

Użytkownicy aplikacji mogą powiadamiać o błędach zgłaszanych przez aplikację kliencką. Usługa Azure Monitor rejestruje również liczby różnych typów odpowiedzi (wymiary ResponseType ) z usług magazynu, takich jak NetworkError, ClientTimeoutError lub AuthorizationError. Usługa Azure Monitor rejestruje tylko liczby różnych typów błędów, ale można uzyskać więcej szczegółów na temat poszczególnych żądań, sprawdzając dzienniki po stronie serwera, po stronie klienta i sieci. Zazwyczaj kod stanu HTTP zwracany przez usługę magazynu wskazuje, dlaczego żądanie nie powiodło się.

Uwaga

Należy pamiętać, że należy spodziewać się sporadycznych błędów. Na przykład błędy z powodu przejściowych warunków sieciowych lub błędów aplikacji.

Następujące zasoby są przydatne do zrozumienia stanu i kodów błędów związanych z magazynem:

Klient odbiera komunikaty HTTP 403 (Zabronione)

Jeśli aplikacja kliencka zgłasza błędy HTTP 403 (Zabronione), prawdopodobną przyczyną jest to, że klient używa wygasłego sygnatury dostępu współdzielonego (SAS) podczas wysyłania żądania magazynu (chociaż inne możliwe przyczyny to niesymetryczność zegara, nieprawidłowe klucze i puste nagłówki).

Biblioteka klienta magazynu dla platformy .NET umożliwia zbieranie danych dziennika po stronie klienta, które odnoszą się do operacji magazynu wykonywanych przez aplikację. Aby uzyskać więcej informacji, zobacz Rejestrowanie po stronie klienta przy użyciu biblioteki klienta magazynu platformy .NET.

W poniższej tabeli przedstawiono przykład z dziennika po stronie klienta wygenerowanego przez bibliotekę klienta magazynu, który ilustruje ten problem:

Źródło Szczegółowości Szczegółowości Identyfikator żądania klienta Tekst operacji
Microsoft.Azure.Storage Informacji 3 85d077ab-... Starting operation with location Primary per location mode PrimaryOnly.
Microsoft.Azure.Storage Informacji 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 Informacji 3 85d077ab -... Waiting for response.
Microsoft.Azure.Storage Ostrzeżenie 2 85d077ab -... Exception thrown while waiting for response: The remote server returned an error: (403) Forbidden.
Microsoft.Azure.Storage Informacji 3 85d077ab -... Response received. Status code = 403, Request ID = <Request ID>, Content-MD5 = , ETag = .
Microsoft.Azure.Storage Ostrzeżenie 2 85d077ab -... Exception thrown during the operation: The remote server returned an error: (403) Forbidden..
Microsoft.Azure.Storage Informacji 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 Informacji 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.

W tym scenariuszu należy zbadać, dlaczego token SAS wygasa, zanim klient wyśle token do serwera:

  • Zazwyczaj nie należy ustawiać czasu rozpoczęcia podczas tworzenia sygnatury dostępu współdzielonego dla klienta do natychmiastowego użycia. Jeśli istnieją niewielkie różnice zegara między hostem generującym sygnaturę dostępu współdzielonego przy użyciu bieżącego czasu i usługi magazynu, usługa magazynu może odbierać sygnaturę dostępu współdzielonego, która nie jest jeszcze prawidłowa.

  • Nie ustawiaj bardzo krótkiego czasu wygaśnięcia dla sygnatury dostępu współdzielonego. Ponownie małe różnice zegara między hostem generującym sygnaturę dostępu współdzielonego a usługą magazynu mogą prowadzić do wygaśnięcia sygnatury dostępu współdzielonego wcześniej niż przewidywano.

  • Czy parametr wersji w kluczu sygnatury dostępu współdzielonego (na przykład sv=2015-04-05) jest zgodny z wersją używanej biblioteki klienta magazynu? Zalecamy, aby zawsze używać najnowszej wersji biblioteki klienta magazynu.

  • W przypadku ponownego wygenerowania kluczy dostępu do magazynu wszystkie istniejące tokeny SAS mogą zostać unieważnione. Ten problem może wystąpić, jeśli wygenerujesz tokeny SAS z długim czasem wygaśnięcia dla aplikacji klienckich do pamięci podręcznej.

Jeśli używasz biblioteki klienta magazynu do generowania tokenów SAS, możesz łatwo utworzyć prawidłowy token. Jeśli jednak używasz interfejsu API REST magazynu i konstruujesz tokeny SAS ręcznie, zobacz Delegowanie dostępu za pomocą sygnatury dostępu współdzielonego.

Klient odbiera komunikaty HTTP 404 (nie znaleziono)

Jeśli aplikacja kliencka odbiera komunikat HTTP 404 (Nie znaleziono) z serwera, oznacza to, że obiekt, którego klient próbował użyć (taki jak jednostka, tabela, obiekt blob, kontener lub kolejka), nie istnieje w usłudze magazynu. Istnieje wiele możliwych przyczyn, takich jak:

  • Klient lub inny proces wcześniej usunął obiekt.

  • Problem z autoryzacją sygnatury dostępu współdzielonego (SAS).

  • Kod JavaScript po stronie klienta nie ma uprawnień dostępu do obiektu.

  • Awaria sieci.

Klient lub inny proces wcześniej usunął obiekt

W scenariuszach, w których klient próbuje odczytać, zaktualizować lub usunąć dane w usłudze magazynu, łatwo jest zidentyfikować w dziennikach zasobów magazynu poprzednią operację, która usunęła dany obiekt z usługi magazynu. Często dane dziennika pokazują, że inny użytkownik lub proces usunął obiekt. Dzienniki usługi Azure Monitor (po stronie serwera) pokazują, kiedy klient usunął obiekt.

W scenariuszu, w którym klient próbuje wstawić obiekt, może nie być od razu oczywiste, dlaczego powoduje to odpowiedź HTTP 404 (Nie znaleziono), biorąc pod uwagę, że klient tworzy nowy obiekt. Jeśli jednak klient tworzy obiekt blob, musi mieć możliwość znalezienia kontenera obiektów blob. Jeśli klient tworzy komunikat, musi mieć możliwość znalezienia kolejki. A jeśli klient dodaje wiersz, musi mieć możliwość znalezienia tabeli.

Możesz użyć dziennika po stronie klienta z biblioteki klienta magazynu, aby lepiej zrozumieć, kiedy klient wysyła określone żądania do usługi magazynu.

Poniższy dziennik po stronie klienta wygenerowany przez bibliotekę klienta magazynu ilustruje problem, gdy klient nie może znaleźć kontenera dla tworzonego obiektu blob. Ten dziennik zawiera szczegółowe informacje o następujących operacjach magazynowania:

Identyfikator żądania Operacja
07b26a5d-... DeleteIfExists metoda usuwania kontenera obiektów blob. Ta operacja obejmuje żądanie HEAD w celu sprawdzenia istnienia kontenera.
e2d06d78... CreateIfNotExists metoda tworzenia kontenera obiektów blob. Ta operacja obejmuje HEAD żądanie, które sprawdza istnienie kontenera. Zwraca HEAD komunikat 404, ale jest kontynuowany.
de8b1c3c-... UploadFromStream metoda tworzenia obiektu blob. Żądanie PUT kończy się niepowodzeniem z komunikatem 404

Wpisy dziennika:

Identyfikator żądania Tekst operacji
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..

W tym przykładzie dziennik pokazuje, że klient przeplata żądania z CreateIfNotExists metody (identyfikator żądania e2d06d78...) z żądaniami z UploadFromStream metody (de8b1c3c-...). Ta interleaving dzieje się, ponieważ aplikacja kliencka wywołuje te metody asynchronicznie. Zmodyfikuj kod asynchroniczny w kliencie, aby upewnić się, że tworzy kontener przed podjęciem próby przekazania jakichkolwiek danych do obiektu blob w tym kontenerze. Najlepiej utworzyć wszystkie kontenery z wyprzedzeniem.

Problem z autoryzacją sygnatury dostępu współdzielonego

Jeśli aplikacja kliencka próbuje użyć klucza SAS, który nie zawiera niezbędnych uprawnień do operacji, usługa magazynu zwraca klientowi komunikat HTTP 404 (Nie znaleziono). Jednocześnie w metrykach usługi Azure Monitor zobaczysz również element AuthorizationError dla wymiaru ResponseType .

Zbadaj, dlaczego aplikacja kliencka próbuje wykonać operację, do której nie udzielono jej uprawnień.

Kod JavaScript po stronie klienta nie ma uprawnień dostępu do obiektu

Jeśli używasz klienta JavaScript, a usługa magazynu zwraca komunikaty HTTP 404, sprawdź następujące błędy języka JavaScript w przeglądarce:

SEC7120: nie odnaleziono źródła http://localhost:56309 w nagłówku Access-Control-Allow-Origin.
SCRIPT7002: XMLHttpRequest: błąd sieci 0x80070005, odmowa dostępu.

Uwaga

Narzędzia deweloperskie F12 w programie Internet Explorer umożliwiają śledzenie komunikatów wymienianych między przeglądarką a usługą magazynu podczas rozwiązywania problemów z językiem JavaScript po stronie klienta.

Te błędy występują, ponieważ przeglądarka sieci Web implementuje to samo ograniczenie zabezpieczeń zasad pochodzenia , które uniemożliwia stronie internetowej wywoływanie interfejsu API w innej domenie niż domena, z których pochodzi strona.

Aby obejść problem z językiem JavaScript, możesz skonfigurować współużytkowanie zasobów między źródłami (CORS) dla usługi magazynu, do którą uzyskuje dostęp klient. Aby uzyskać więcej informacji, zobacz Obsługa współużytkowania zasobów między źródłami (CORS) dla usług Azure Storage.

W poniższym przykładzie kodu pokazano, jak skonfigurować usługę blob, aby umożliwić skryptowi JavaScript działającemu w domenie firmy Contoso dostęp do obiektu blob w usłudze blob Storage:

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

Awaria sieci

W pewnych okolicznościach utracone pakiety sieciowe mogą prowadzić do zwrócenia przez usługę magazynu komunikatów HTTP 404 do klienta. Na przykład gdy aplikacja kliencka usuwa jednostkę z usługi tabel, zobaczysz, że klient zgłasza wyjątek magazynu, zgłaszając komunikat o stanie "HTTP 404 (nie znaleziono)" z usługi tabel. Podczas badania tabeli w usłudze magazynu tabel zobaczysz, że usługa usunie jednostkę zgodnie z żądaniem.

Szczegóły wyjątku w kliencie obejmują identyfikator żądania (7e84f12d...) przypisany przez usługę tabel dla żądania: możesz użyć tych informacji, aby zlokalizować szczegóły żądania w dziennikach zasobów magazynu w usłudze Azure Monitor, wyszukując w polach informacje opisujące sposób uwierzytelniania operacji wpisów dziennika. Możesz również użyć metryk, aby określić, kiedy wystąpią takie błędy, a następnie przeszukać pliki dziennika na podstawie czasu zarejestrowania tego błędu przez metryki. Ten wpis dziennika pokazuje, że usuwanie nie powiodło się z komunikatem o stanie "HTTP (404) Client Other Error". Ten sam wpis dziennika zawiera również identyfikator żądania wygenerowany przez klienta w kolumnie client-request-id (813ea74f...).

Dziennik po stronie serwera zawiera również inny wpis o tej samej client-request-id wartości (813ea74f...) dla pomyślnej operacji usuwania dla tej samej jednostki i z tego samego klienta. Ta pomyślna operacja usuwania miała miejsce na krótko przed niepowodzeniem żądania usunięcia.

Najbardziej prawdopodobną przyczyną tego scenariusza jest wysłanie przez klienta żądania usunięcia jednostki do usługi tabel, która zakończyła się pomyślnie, ale nie otrzymała potwierdzenia z serwera (być może z powodu tymczasowego problemu z siecią). Następnie klient automatycznie ponowił próbę wykonania operacji (przy użyciu tego samego client-request-id), a ta ponawianie próby nie powiodło się, ponieważ jednostka została już usunięta.

Jeśli ten problem występuje często, należy zbadać, dlaczego klient nie otrzymuje potwierdzenia z usługi tabel. Jeśli problem występuje sporadycznie, należy wychwycić błąd "HTTP (404) Nie znaleziono" i zalogować go w kliencie, ale zezwolić klientowi na kontynuowanie.

Klient odbiera komunikaty HTTP 409 (konflikt)

Gdy klient usuwa kontenery obiektów blob, tabele lub kolejki, istnieje krótki okres, zanim nazwa stanie się ponownie dostępna. Jeśli kod w aplikacji klienckiej usunie, a następnie natychmiast ponownie utworzy kontener obiektów blob przy użyciu tej samej nazwy, CreateIfNotExists metoda ostatecznie zakończy się niepowodzeniem z powodu błędu HTTP 409 (Konflikt).

Aplikacja kliencka powinna używać unikatowych nazw kontenerów za każdym razem, gdy tworzy nowe kontenery, jeśli wzorzec usuwania/ponownego tworzenia jest typowy.

Metryki pokazują, że wpisy dziennika funkcji PercentSuccess lub analytics mają operacje ze stanem transakcji ClientOtherErrors

Wymiar ResponseType równy wartości Success przechwytuje procent operacji, które zakończyły się powodzeniem na podstawie kodu stanu HTTP. Operacje z kodami stanu 2XX są pomyślne, natomiast operacje z kodami stanu w zakresach 3XX, 4XX i 5XX są liczone jako nieudane i obniżają wartość metryki Success. W dziennikach zasobów magazynu te operacje są rejestrowane ze stanem transakcji ClientOtherError.

Te operacje zostały wykonane pomyślnie i w związku z tym nie mają wpływu na inne metryki, takie jak dostępność. Oto kilka przykładów operacji, które są wykonywane pomyślnie, ale mogą powodować niepowodzenie kodów stanu HTTP:

  • ResourceNotFound (Nie znaleziono 404), na przykład z żądania GET do obiektu blob, który nie istnieje.
  • ResourceAlreadyExists (Konflikt 409), na przykład z CreateIfNotExist operacji, w której zasób już istnieje.
  • ConditionNotMet (Nie zmodyfikowano 304), na przykład z operacji warunkowej, takiej jak wysłanie przez klienta ETag wartości i nagłówka HTTP If-None-Match w celu żądania obrazu tylko wtedy, gdy został zaktualizowany od ostatniej operacji.

Listę typowych kodów błędów interfejsu API REST zwracanych przez usługi magazynu można znaleźć na stronie Typowe kody błędów interfejsu API REST.

Zobacz też

Skontaktuj się z nami, aby uzyskać pomoc

Jeśli masz pytania lub potrzebujesz pomocy, utwórz wniosek o pomoc techniczną lub zadaj pytanie w społeczności wsparcia dla platformy Azure. Możesz również przesłać opinię o produkcie do społeczności opinii platformy Azure.