Połączenie WebSocket daje aplikacji kanał wymiany wiadomości. Nie określa jednak, do której operacji należy odpowiedź, jak długo czekać ani czy powtórzone żądanie wykonać ponownie. To decyzje aplikacji.
Eksperyment z żądaniami i odpowiedziami pokazuje te decyzje w działaniu. Całość działa w przeglądarce: bez rzeczywistego gniazda, backendu i pomiaru opóźnienia sieci. Celem jest zbadanie małego protokołu w warunkach, które łatwo odtworzyć.
Problem: odpowiedź to jeszcze nie wynik
Wyobraźmy sobie dwie oczekujące operacje. Druga kończy się pierwsza. Dopasowanie kolejnej odpowiedzi do najstarszego żądania zaktualizuje niewłaściwą operację. Dodajmy limit czasu: co zrobić z pomyślną odpowiedzią, która dotarła już po pokazaniu przekroczenia limitu?
Ponowne kliknięcie lub ponowienie przez aplikację może wysłać tę samą operację jeszcze raz. Odrzucenie dodatkowej odpowiedzi chroni interfejs, ale nie cofa ponownego skutku na serwerze. Symulacja rozdziela te obowiązki.
Trzy decyzje implementacyjne
Dopasowanie przez ID. Każda nowa operacja otrzymuje identyfikator żądania. Dodatkowe kopie zachowują go. Jeden wiersz oznacza jedną operację logiczną niezależnie od liczby dostarczeń. Kolejne numery ułatwiają naukę; prawdziwy protokół potrzebuje zasad unikalności uwzględniających sesje i ponowienia.
Jeden wynik. Operacja zaczyna jako oczekująca, a kończy sukcesem, błędem lub przekroczeniem limitu czasu. Obsługa odpowiedzi sprawdza stan przed zmianą. Dodatkowe i spóźnione odpowiedzi trafiają do dziennika i są ignorowane. Terminowa odpowiedź anuluje zegar limitu. Przy równych ustawieniach wygrywa limit czasu, bo jego zegar jest rejestrowany pierwszy.
Podstawowy warunek jest krótki:
if (operation.status !== 'pending') { log(operation.id, 'ignored'); return;}Osobna deduplikacja wykonania. Symulowany serwer wybiera jeden wynik na ID. Kopie odtwarzają go, a odpowiedzi są przesunięte o 80 ms, aby było je widać. Klient przyjmuje tylko pierwszą terminową odpowiedź. To model efektu deduplikacji, a nie trwały magazyn kluczy idempotencji.
Model stanu jest oddzielony od kontrolek strony. Wstrzykiwany zegar pozwala świadomie przesuwać czas w testach, a źródło losowości — odtwarzać błędy. W interfejsie prawdopodobieństwo błędu jest losowane niezależnie dla każdej operacji logicznej. Ustawienia 0 i 100 procent są powtarzalne.
Sprawdź granice
Zacznij od scenariusza Pomyślny wynik. Wyślij żądanie, zmniejsz opóźnienie i wyślij kolejne przed zakończeniem pierwszego. Późniejsze żądanie może zakończyć się wcześniej, zachowując własny ID.
Następnie wybierz Spóźniona odpowiedź. Przy opóźnieniu 2500 ms i limicie 1000 ms operacja przekroczy limit, zanim odpowiedź pojawi się w dzienniku. Jej status już się nie zmieni. Limit kończy oczekiwanie klienta, ale nie dowodzi, że rzeczywisty serwer niczego nie wykonał.
Scenariusz Duplikaty żądań daje trzy dostarczenia, jeden wynik serwera i jeden wynik klienta. Zmiana ustawień wpływa tylko na nowe operacje, więc różne warunki można porównać w jednym przebiegu.
Kompromisy i ograniczenia
Lokalna symulacja zamienia realizm na kontrolę. Nie weryfikuje sieci, utraty połączenia, ponownego łączenia, uwierzytelniania ani kontroli przepływu. „Błąd” oznacza odpowiedź aplikacji z błędem, a nie utracony pakiet. Zegary przeglądarki nie są też precyzyjnymi czasomierzami, zwłaszcza w tle.
Produkcja wymagałaby walidacji wiadomości, obsługi cyklu życia połączenia i ograniczonego rejestru oczekujących żądań. Ponawianie zapisu potrzebuje polityki idempotencji: zakresu klucza, czasu przechowywania wyniku, obsługi równoczesnych duplikatów i atomowości zapisu klucza wraz ze skutkiem. Nowy ID przy każdym ponowieniu uniemożliwi deduplikację po ID.
Eksperyment ogranicza przebieg do 40 operacji i zachowuje 100 ostatnich zdarzeń. Czyszczenie lub opuszczenie strony anuluje zegary. Te granice ułatwiają naukę; nie są benchmarkiem przepustowości.
Wnioski
Dostarczenie, wykonanie i wynik pokazany użytkownikowi to różne zdarzenia. Żądanie może dotrzeć kilka razy, wykonać się raz i nadal przekroczyć limit czasu klienta. Wiersze operacji i dziennik pomagają zrozumieć tę różnicę.
Zacznij od prostych reguł: identyfikuj operację, określ koniec oczekiwania i przypisz odpowiedzialność za duplikaty. Sprawdź trudne granice przed dodaniem ponownego łączenia i ponowień.
Wróć do Lab i zmień warunki. Rzeczywisty interfejs przeglądarki, wysyłanie, odbieranie i sprzątanie połączenia opisuje przewodnik MDN po WebSocket.
Komentarze