Cykl życia połączenia i ponowne łączenie
Połączenie Realtime to jeden WebSocket. Zmiany sieci, usypianie urządzeń i restarty infrastruktury mogą je zamknąć. Klient łączy się ponownie automatycznie, a Twoja aplikacja może wyświetlać bieżący stan połączenia.
Sześć stanów
bird.connection.state w kliencie przeglądarkowym oraz bird.connectionState w Swift i Kotlin zawsze przyjmuje jedną z poniższych wartości (Kotlin zapisuje je jako stałe ConnectionState, więc unavailable ma postać ConnectionState.UNAVAILABLE):
| Stan | Znaczenie |
|---|---|
| initialized | Klient istnieje, ale jeszcze nie otworzył gniazda. |
| connecting | Gniazdo jest otwierane lub otwarte i czeka na handshake. |
| connected | Handshake zakończony. Połączenie ma ID i może subskrybować. |
| unavailable | Połączenie zostało zerwane i zaplanowano ponowne łączenie. |
| disconnected | Wywołano disconnect(). Nic nie jest zaplanowane. |
| failed | Serwer odrzucił to połączenie. Klient nie ponawia prób. |
Zbinduj state_change, aby widzieć każde przejście, lub zbinduj nazwę pojedynczego stanu, gdy interesuje Cię tylko jeden:
import { BirdRealtime } from "@messagebird/realtime";
const bird = new BirdRealtime({ appKey: "your-app-key", region: "us1" });
bird.connection.bind("state_change", ({ previous, current }) => {
console.log(previous, "->", current);
});
bird.connection.bind("unavailable", () => showReconnectingBanner());
bird.connection.bind("connected", () => hideReconnectingBanner());import BirdRealtime
let bird = BirdRealtime(options: .init(appKey: "your-app-key", region: "us1"))
bird.onConnectionStateChange { previous, current in
print(previous, "->", current)
if current == .unavailable { showReconnectingBanner() }
if current == .connected { hideReconnectingBanner() }
}import com.bird.realtime.BirdRealtime
import com.bird.realtime.BirdRealtimeOptions
import com.bird.realtime.ConnectionState
val bird = BirdRealtime(BirdRealtimeOptions(appKey = "your-app-key", region = "us1"))
bird.onConnectionStateChange { previous, current ->
println("$previous -> $current")
if (current == ConnectionState.UNAVAILABLE) showReconnectingBanner()
if (current == ConnectionState.CONNECTED) hideReconnectingBanner()
}Swift i Kotlin używają jednego obserwatora dla każdego przejścia, więc rozgałęziaj po current. Handlery uruchamiają się na głównej kolejce w Swift i na głównym looperze Androida w Kotlin, jeśli jest dostępny. Przekaż deliveryQueue lub Executor, aby użyć innego kontekstu wykonania.
Otwarte gniazdo pozostaje w stanie connecting, dopóki nie nadejdzie handshake z serwera. Handshake ustawia bird.connection.connectionId, zanim stan zmieni się na connected, dzięki czemu autoryzacja może podpisać to ID. Jeśli handshake nie zawiera ID, klient zgłasza błąd i zamyka gniazdo.
Automatyczne ponowne łączenie
Po nieoczekiwanym zerwaniu klient czeka, zanim otworzy nowe gniazdo. Opóźnienie korzysta z wykładniczego backoffu z pełnym jitterem, bazą jednosekundową i limitem 30 sekund. Każdy udany handshake resetuje backoff.
Kod zamknięcia decyduje o jednym z trzech zachowań:
| Kod zamknięcia | Zachowanie |
|---|---|
| 4000 do 4099 | Odrzucone. Brak ponownej próby, stan przechodzi do failed. |
| 4200 do 4299 | Natychmiastowa ponowna próba. |
| Wszystko inne | Stan przechodzi do unavailable, potem ponowna próba z backoffem. |
Awarie sieci korzystają ze ścieżki backoffu. Obsłuż kody odrzucenia w swoim UI, ponieważ te terminalne błędy nie łączą się ponownie automatycznie.
Sprawdzanie nieaktywnego połączenia
Gniazdo może wyglądać na otwarte po awarii ścieżki sieciowej. Klient wysyła ping po upływie limitu aktywności, który domyślnie wynosi 120 sekund, chyba że handshake przekaże inną wartość. Jeśli pong nie nadejdzie w ciągu domyślnego 30-sekundowego limitu pong, klient zamyka gniazdo z kodem natychmiastowej ponownej próby.
Co dzieje się z Twoimi kanałami
Subskrypcje należą do połączenia, więc zerwanie je usuwa. Klient zachowuje każdy obiekt kanału, ponownie subskrybuje po następnym stanie connected i utrzymuje istniejące handlery.
Klient wywołuje Twój authEndpoint ponownie dla każdego kanału prywatnego i presence, używając nowego ID połączenia. Nie może ponownie użyć starej sygnatury, ponieważ zawiera ona poprzednie ID połączenia. Po jednym wywołaniu signin() klient loguje się również przy każdym nowym połączeniu i zgłasza późniejsze błędy przez signin_error.
bird.connection.bind("signin_error", ({ message }) => {
console.warn("connection has no identity:", message);
});bird.onSigninError { error in
print("connection has no identity:", error.message)
}bird.onSigninError { error ->
println("connection has no identity: ${error.message}")
}Gdy kanał łączy się ponownie, channel.trigger zwraca false bez wysyłania zdarzenia klienta. Sprawdź channel.subscribed lub wysyłaj po bird:subscription_succeeded, które odpala się po każdej udanej ponownej subskrypcji.
const room = bird.subscribe("presence-room-1");
room.bind("bird:subscription_succeeded", ({ members }) => {
renderMembers(members);
});guard let room = bird.subscribe("presence-room-1") as? PresenceChannel else { return }
room.bind(BirdProtocol.Event.subscriptionSucceeded) { _ in
renderMembers(room.members)
}val room = bird.subscribe("presence-room-1")
if (room is PresenceChannel) {
room.bind(BirdProtocol.Event.SUBSCRIPTION_SUCCEEDED) {
renderMembers(room.members)
}
}Realtime nie odtwarza zdarzeń opublikowanych, gdy klient był rozłączony. Jeśli widok musi odzyskać dane po przerwie, pobierz jego bieżący stan przy bird:subscription_succeeded i od tego momentu stosuj kolejne zdarzenia.
Celowe rozłączanie
bird.disconnect() zamyka gniazdo bez planowania ponownego łączenia. Używaj go, gdy wylogowany lub nieaktywny klient nie potrzebuje już danych na żywo. Klient zachowuje kanały, więc późniejsze bird.connect() ponownie otwiera gniazdo i subskrybuje.
bird.disconnect(); // state: disconnected, no reconnect
bird.connect(); // reopens and re-subscribesbird.disconnect() // state: disconnected, no reconnect
bird.connect() // reopens and re-subscribesbird.disconnect() // state: DISCONNECTED, no reconnect
bird.connect() // reopens and re-subscribesNa urządzeniach mobilnych rozłączaj się, gdy odpowiedni widok lub aktywność się zatrzymuje, i łącz ponownie, gdy wznawia. Obiekty kanałów i bindowania pozostają dostępne.
Błędy na połączeniu a błędy na kanale
Błędy serwera dotyczące jednego kanału trafiają na ten kanał. Najczęściej jest to odrzucona subskrypcja, a autoryzator zwracający 403 pojawia się tutaj:
room.bind("bird:subscription_error", (err) => {
console.warn("could not join:", err);
});room.bind(BirdProtocol.Event.subscriptionError) { error in
print("could not join:", error ?? "")
}room.bind(BirdProtocol.Event.SUBSCRIPTION_ERROR) { error ->
println("could not join: $error")
}Wszystko, czego protokół nie przypisuje do kanału, trafia na połączenie:
bird.connection.bind("error", ({ code, message }) => {
console.warn(code, message);
});bird.onError { error in
print(error.code ?? 0, error.message)
}bird.onError { error ->
println("${error.code} ${error.message}")
}Obsługa kodu zamknięcia 4009
Kod 4009 należy do pasma bez ponownych prób, więc połączenie przechodzi w stan failed. Sprawdź przyczynę, aby rozróżnić te sytuacje:
- Zakończony członek. Twój backend wywołał disconnect API dla tego członka, więc każde jego połączenie zostało zamknięte. Zobacz Kończenie połączeń członków.
- Połączenie, które nigdy nie zostało autoryzowane. Aplikacja wymaga autoryzowanych połączeń, a to nie zostało autoryzowane w wymaganym czasie. Zobacz Wymaganie autoryzowanych połączeń.
Klient nie łączy się ponownie automatycznie, więc Twoja aplikacja decyduje, co dzieje się dalej:
bird.connection.bind("error", ({ code }) => {
if (code === 4009) showSignedOutScreen();
});bird.onError { error in
if error.code == 4009 { showSignedOutScreen() }
}bird.onError { error ->
if (error.code == 4009) showSignedOutScreen()
}Stan wylogowania jest odpowiedni, gdy uwierzytelnianie się zakończyło. Wywołanie bird.connect() rozpoczyna nowe połączenie i powtarza autoryzację, więc łącz ponownie dopiero po zmianie stanu autoryzacji wywołującego.
Następne kroki
- Autoryzacja kanałów to kontrakt implementowany przez Twój backend i żądanie, które klient powtarza przy każdym ponownym połączeniu.
- Wymaganie autoryzowanych połączeń zamienia nieautoryzowane połączenie w zamknięte.
- Kończenie połączeń członków to sposób celowego zamknięcia połączenia z kodem 4009.
- Przegląd Realtime opisuje kanały, członków i połączenia jako model.
Powiązane zasoby
Kontynuuj z dokumentacją, przewodnikami i przykładami dotyczącymi tego tematu. Zasoby są w języku angielskim.
Poznaj możliwościRealtimePodążaj ścieżką naukiBuild your first integrationPrzewodnik wdrożeniowySend your first realtime event
Wypróbuj ćwiczenie i uzyskaj brief wdrożeniowy