Co zrobić, gdy żądanie jest wysyłane do serwera i podczas oczekiwania na odpowiedź utracono połączenie z Internetem?

14

Wysyłam ogromną ilość danych na serwer. Teraz, gdy wysłałem dane i czekam na odpowiedź serwera, nagle moje urządzenie z Androidem traci połączenie z Internetem.
Tak więc zwykłem wyświetlać okno dialogowe z ostrzeżeniem o utracie połączenia, ale po stronie serwera dane zostały już przetworzone i zostały zaktualizowane gdzieś np. Pod dowolnym adresem URL. Ale mój telefon z Androidem tego nie wie, ponieważ nigdy nie otrzymał odpowiedzi. Jak to rozwiązać?
Czy można to zrobić po stronie serwera, czy na samym Androidzie Jak?
Skąd serwer wiedziałby, że telefon z Androidem nie będzie nasłuchiwał odpowiedzi?
Może to być perspektywa optymalizacji komunikacji klient-serwer.

mayank_droid
źródło
O ile danych mówimy? Gigabajty?
Daniel Hollinrake
Wokół nie ma 7-8 MB, ale czas reakcji serwera jest zbyt długi, a szybkość przesyłania z telefonu wynosi około 128 KB / S. Nie mówię o wielkości danych, ale problem z połączeniem.
mayank_droid

Odpowiedzi:

15

Jest to dość powszechny problem z transakcjami asynchronicznymi i dzieli się na kilka części.

  1. Skąd obie strony wiedzą, że żądanie transakcji zostało pomyślnie otrzymane?
  2. Jak ponownie przesłać żądanie transakcji, które według klienta nie zostało poprawnie odebrane?
  3. W jaki sposób serwer wykrywa powtarzające się żądania od klienta, gdy serwer pomyślnie otrzymał pierwsze żądanie?
  4. Skąd klient wie, skąd wziąć wyniki transakcji?

Wspaniałą rzeczą w HTTP jest to, że dość łatwo można rozwiązać wszystkie te problemy.

Wyobraź sobie taką strukturę URL:

POST http://my.server.com/application/engine/queue 
GET   http://my.server.com/application/engine/results?jobid=43425

Użycie postu HTTP do wysłania żądania do serwera, użycie unikalnego identyfikatora żądania klienta - i serwer powinien odpowiedzieć za pomocą identyfikatora zadania. Z perspektywy klienta, jeśli ta odpowiedź nie występuje, żądanie musi zostać ponownie wysłane. Z perspektywy serwera identyfikator żądania klienta musi być buforowany przez kilka minut, na wypadek, gdyby klient wysłał zduplikowane żądania. Zduplikowane żądania są obsługiwane po prostu przez zwrócenie tego samego identyfikatora zadania klientowi.

Klient otrzymuje wyniki żądania z adresu URL wyników. To połączenie można powtarzać tak często, jak to konieczne, aby uzyskać wyniki. Jeśli zostanie wywołany, zanim wyniki będą dostępne, odpowiedź może być odpowiedzią BRAK ZAWARTOŚCI, aby klient wiedział, że serwer rozpoznaje identyfikator zadania, ale nie ma jeszcze treści. Jeśli identyfikator zadania nie zostanie rozpoznany, wówczas odpowiednią odpowiedzią jest NOT-FOUND.

Efektem końcowym jest to, że klient zawsze może podjąć rozsądne działanie, gdy sieć zostanie utracona i odzyskana, a serwer może zawsze rozsądnie przetwarzać żądania od klienta

Michael Shaw
źródło
3
To, lub po prostu krótkie żądanie z prośbą o identyfikator transakcji, następnie kilka żądań dodających dane do transakcji (możesz tutaj podzielić transfer na mniejsze części, aby uzyskać częściowe potwierdzenia), a następnie końcowe żądanie „zatwierdzenia”. Następnie można ustawić różne limity czasu dla całkowicie pustych transakcji (klient najprawdopodobniej nie otrzymał identyfikatora), częściowo przesłanych transakcji i wyników (jeśli klient nie otrzyma wyników, może ponowić żądanie „zatwierdzenia”).
Simon Richter
To poradziłoby sobie z sytuacją, w której połączenie zostało utracone podczas transmisji żądania. Zadane pytanie dotyczy utraty połączenia po wysłaniu danych, ale przed przetworzeniem żądania zostało zakończone.
Michael Shaw
1
To również jest obsługiwane. Transakcja „zatwierdzenia” jest niewielka i wykorzystuje identyfikator transakcji, więc można ją tanio ponownie wydać bez ponownego przesyłania danych, a serwer może albo rozpocząć przetwarzanie, albo zwrócić wynik z wcześniejszego wywołania. Jest to bardzo podobne do tego, co sugerujesz; Różnica polega na tym, że mam osobne żądanie utworzenia identyfikatora zadania, więc mam dodatkowy punkt synchronizacji, dzięki czemu klient może wiedzieć, czy zadanie już istnieje, bez ponownego przesyłania pełnego żądania.
Simon Richter
tak, to ma sens.
Michael Shaw
W ten sposób, jeśli transakcja zawiera częściowe dane na serwerze, wiem, że istnieje klient, który zna ten identyfikator i próbuje dokończyć transakcję, dzięki czemu mogę zachować stan częściowy i zaoferować wznowienie transmisji w połowie, minimalizując wymagania dotyczące przepustowości i usuwając należy porównać treść żądania, aby znaleźć duplikaty.
Simon Richter
4

Dotyczy to podstaw komunikacji w protokole. Klient systemu Android zażądał transakcji, a serwer musi ją wykonać. Jeśli transakcja jest zależna od potwierdzenia klienta Android, to należy zadzwonić do komunikacji ACK / NAK.

ACK (potwierdzenie) i NAK (negatywne potwierdzenie) są używane do poinformowania drugiej strony o wyniku żądania.

To, o co pytasz, to rodzaj wymiany uzgadniania między klientem a serwerem, którą można wykonać za pomocą podstawowej wymiany ACK / NAK.

Oto przykład przesyłania przez system Android pliku z dwukierunkowym potwierdzeniem.

Android -> upload files -> Server
Android <- ACK #id <- Server
Android -> ACK #id -> Server

W powyższym przykładzie dodałem #idunikalny identyfikator transakcji. Serwer powinien otrzymać pliki, utworzyć rekord transakcji i wysłać go jako odpowiedź z powrotem do Androida. Android powinien następnie potwierdzić tę transakcję (lub alternatywnie NAK za odrzucenie).

Oto przykład odłączania się Androida podczas uzgadniania.

Android -> upload files -> Server
Android <- ACK #id <- Server
/** no ACK response **/

W powyższym przykładzie serwer zaakceptował przesłane pliki i wysłał #idodpowiedź ACK z powrotem do Androida, ale Android nigdy nie odpowiada ACK. Urządzenie z Androidem nie zakończyło uzgadniania. To Ty decydujesz, jak serwer powinien to obsłużyć. Zniszcz transakcję, zachowaj transakcję i poczekaj, aż urządzenie z Androidem wróci później lub mimo to sfinalizuj transakcję.

Serwer może założyć, że ponieważ urządzenie nie odpowiedziało za pomocą ACK. To, że urządzenie z Androidem nie zaktualizowało stanu wewnętrznego, aby wskazać, że przesyłanie się powiodło. Odrzuciłbym transakcję i pozwoliłbym urządzeniu powtórzyć ją w przyszłości.

Reactgular
źródło