Long Polling — to technika interakcji klienta i serwera, w której serwer utrzymuje otwarte żądanie HTTP aż do pojawienia się nowych danych lub upływu czasu oczekiwania. W przeciwieństwie do okresowego odpytywania, serwer nie zwraca natychmiast pustej odpowiedzi, lecz czeka na wystąpienie zdarzenia, aby wysłać dane do klienta. Według MDN Web Docs, 2024, Long Polling pozostaje popularnym rozwiązaniem dla aplikacji czasu rzeczywistego, gdzie WebSocket jest niedostępny lub zbędny.
Najważniejsze
Long Polling — to wzorzec interakcji w architekturze klient-serwer, w którym klient inicjuje żądanie HTTP, a serwer opóźnia wysłanie odpowiedzi do momentu pojawienia się nowych danych lub upływu określonego czasu oczekiwania. Po otrzymaniu odpowiedzi klient natychmiast wysyła kolejne żądanie, tworząc efekt ciągłego połączenia.
Technika Long Polling powstała jako ewolucyjne rozwinięcie Short Polling w celu zmniejszenia liczby pustych żądań HTTP. W tradycyjnym odpytywaniu klient wysyła żądania co N sekund, a serwer odpowiada nawet przy braku nowych danych. W Long Polling serwer stosuje mechanizm utrzymywania połączenia, co radykalnie zmniejsza ilość bezużytecznego ruchu.
Przed pojawieniem się WebSocket w 2011 roku Long Polling był głównym sposobem organizacji czasu rzeczywistego w sieci. Firmy takie jak Facebook i Gmail używały tej techniki do swoich czatów i powiadomień na początku 2010 roku. Według badań High Performance Browser Networking (Grigorik, 2013), Long Polling obsługiwał do 95% wszystkich połączeń czasu rzeczywistego w dużych aplikacjach internetowych tamtego okresu.
Klient wysyła standardowe żądanie HTTP do serwera. Serwer po otrzymaniu żądania nie zwraca odpowiedzi natychmiast — umieszcza żądanie w kolejce oczekiwania. Gdy na serwerze wystąpi zdarzenie (nowa wiadomość, zmiana danych), serwer tworzy odpowiedź i wysyła ją do klienta. Klient po otrzymaniu odpowiedzi natychmiast tworzy nowe żądanie Long Polling i cykl się powtarza.
Long Polling działa zgodnie z następującą sekwencją kroków. Klient wysyła żądanie HTTP GET do endpointu serwera. Serwer po otrzymaniu żądania sprawdza dostępność nowych danych w kolejce zdarzeń. Jeśli danych nie ma, serwer utrzymuje żądanie w stanie oczekiwania, nie wysyłając odpowiedzi natychmiast. Mechanizm utrzymywania zależy od implementacji serwera — najczęściej stosuje się przetwarzanie asynchroniczne z callbackami lub architekturę zdarzeniową.
Gdy po stronie serwera wystąpi zdarzenie (na przykład użytkownik wysłał wiadomość na czacie), serwer tworzy odpowiedź HTTP z treścią zawierającą te dane i kończy połączenie. Klient otrzymuje odpowiedź, przetwarza dane i natychmiast inicjuje nowe żądanie. Jeśli w czasie oczekiwania dane się nie pojawiły, serwer wysyła pustą odpowiedź po upływie czasu oczekiwania, a klient również odtwarza połączenie. Timeout wynosi zwykle 30–60 sekund dla równowagi między obciążeniem a opóźnieniem.
Kluczowym parametrem konfiguracji Long Polling jest czas oczekiwania (timeout). Zbyt krótki czas oczekiwania (poniżej 10 sekund) prowadzi do wzrostu liczby żądań, przybliżając technikę do Short Polling. Zbyt długi (powyżej 120 sekund) może spowodować zerwanie połączenia przez pośrednie proxy i load balancery. Zalecana wartość dla większości scenariuszy to 30–45 sekund.
Jeśli na serwerze wystąpiło kilka zdarzeń podczas jednego żądania Long Polling, serwer powinien przekazać je wszystkie w jednej odpowiedzi lub zorganizować kolejkę zdarzeń po stronie klienta. W tym celu stosuje się buforowanie zdarzeń: serwer gromadzi zdarzenia, które wystąpiły podczas utrzymywania żądania, i przekazuje je jako tablicę danych w treści odpowiedzi.
Rozważmy prostą implementację Long Polling po stronie klienta z użyciem nowoczesnego Fetch API. Funkcja kliencka wysyła żądanie i rekurencyjnie wywołuje siebie po otrzymaniu odpowiedzi.
async function longPoll(url) {
try {
const response = await fetch(url);
const data = await response.json();
handleData(data);
longPoll(url);
} catch (error) {
console.error("Błąd Long Polling", error);
setTimeout(() => longPoll(url), 3000);
}
}
function handleData(data) {
if (data.events && data.events.length > 0) {
data.events.forEach(event => {
console.log("Nowe zdarzenie:", event);
});
}
}
longPoll("/api/events");
Ten kod tworzy nieskończoną pętlę Long Polling: po otrzymaniu odpowiedzi funkcja natychmiast wysyła nowe żądanie. W przypadku błędu połączenia ustawiane jest trzysekundowe opóźnienie przed ponowną próbą, aby uniknąć lawinowego obciążenia serwera.
Po stronie serwera należy utrzymywać żądanie aż do pojawienia się zdarzenia lub upływu czasu oczekiwania. Przykład implementacji z użyciem EventEmitter w Node.js demonstruje ten mechanizm.
const express = require("express");
const EventEmitter = require("events");
const app = express();
const eventBus = new EventEmitter();
app.get("/api/events", (req, res) => {
const timeout = setTimeout(() => {
res.json({ events: [] });
}, 30000);
eventBus.once("new-event", (data) => {
clearTimeout(timeout);
res.json({ events: [data] });
});
});
app.post("/api/events", (req, res) => {
eventBus.emit("new-event", req.body);
res.send({ status: "ok" });
});
app.listen(3000);
Część serwerowa używa EventEmitter do powiadamiania oczekujących połączeń Long Polling o pojawieniu się nowych danych. Po osiągnięciu 30-sekundowego czasu oczekiwania serwer zwraca pustą tablicę zdarzeń, a klient tworzy nowe żądanie.
Long Polling jest stosowany w scenariuszach wymagających dostarczania danych w czasie rzeczywistym, ale gdy użycie WebSocket jest niemożliwe ze względów technicznych lub infrastrukturalnych. Najczęstsze przypadki to korporacyjne proxy i firewalle blokujące połączenia WebSocket, a także środowiska z ograniczonym wsparciem protokołu po stronie serwera.
Kluczowym czynnikiem wyboru Long Polling jest wsteczna kompatybilność. Wszystkie klienty i serwery HTTP obsługują tę metodę, co czyni ją uniwersalnym rozwiązaniem dla czasu rzeczywistego bez dodatkowych zależności. Według HTTP Archive (2024), około 8% wszystkich stron internetowych nadal używa Long Polling do podstawowej funkcjonalności czasu rzeczywistego.
Long Polling i Short Polling rozwiązują to samo zadanie — dostarczanie danych z serwera do klienta — ale zasadniczo różnią się mechanizmem i wydajnością. Short Polling używa stałego interwału odpytywania, w którym klient wysyła żądania HTTP w równych odstępach czasu niezależnie od tego, czy na serwerze pojawiły się nowe dane.
| Cecha | Long Polling | Short Polling |
|---|---|---|
| Inicjacja odpowiedzi | Serwer wysyła dane przy zdarzeniu | Serwer odpowiada na każde żądanie klienta |
| Opóźnienie dostarczenia | Minimalne, do 1 sekundy | Zależy od interwału odpytywania, 3–60 sekund |
| Liczba żądań | 1 żądanie na zdarzenie lub timeout | N żądań na jednostkę czasu (stałe) |
| Ruch przy bezczynności | Niski (jedno otwarte żądanie) | Wysoki (żądania co N sekund) |
| Obciążenie serwera | Utrzymywanie połączeń | Przetwarzanie częstych żądań |
| Złożoność implementacji | Średnia (przetwarzanie asynchroniczne) | Niska (zwykłe żądania HTTP) |
Short Polling jest prostszy w implementacji, ale generuje znacznie większe obciążenie serwera i sieci przy tej samej częstotliwości aktualizacji danych. Jeśli wymagane jest opóźnienie poniżej 5 sekund, Short Polling generuje dziesiątki żądań na minutę, podczas gdy Long Polling używa jednego żądania na zdarzenie lub timeout. Dla aplikacji z rzadkimi zdarzeniami Long Polling jest o rząd wielkości bardziej wydajny pod względem ruchu.
WebSocket — to pełnoprawny dwukierunkowy protokół czasu rzeczywistego działający na TCP po początkowym uzgadnianiu HTTP. W przeciwieństwie do Long Polling, WebSocket ustanawia jedno stałe połączenie i pozwala serwerowi wysyłać dane do klienta w dowolnym momencie bez tworzenia nowego żądania HTTP.
Wybór między Long Polling a WebSocket zależy od kilku czynników. Kompatybilność: Long Polling działa przez wszystkie proxy i firewalle, WebSocket może być blokowany przez sieci korporacyjne. Wydajność: WebSocket ma mniejszy narzut (2 bajty na ramkę w porównaniu do pełnych nagłówków HTTP), co jest krytyczne przy wysokiej częstotliwości wiadomości. Skalowalność: Long Polling wymaga więcej zasobów po stronie serwera z powodu utrzymywania wielu połączeń, WebSocket używa stałego połączenia na każdą sesję.
Według Mozilla Developer Network (2024), WebSocket jest obsługiwany przez wszystkie nowoczesne przeglądarki od wersji 2011–2015, ale korporacyjne proxy (np. Symantec Blue Coat) nadal blokują go w 15–20% sieci firmowych, co utrzymuje znaczenie Long Polling jako rozwiązania fallback.
Często zadawane pytania
Long Polling — to sytuacja, w której klient prosi serwer: „odpowiedz, gdy pojawią się nowe dane“, a serwer utrzymuje połączenie otwarte, oczekując zdarzenia. Gdy tylko dane się pojawią, serwer odpowiada, a klient natychmiast zadaje kolejne takie samo pytanie.
Przy Short Polling klient pyta serwer co N sekund, czy są dane, nawet jeśli ich nie ma. Przy Long Polling klient pyta raz, a serwer odpowiada tylko wtedy, gdy dane rzeczywiście się pojawią. Long Polling generuje mniej pustych żądań i zmniejsza obciążenie sieci.
Long Polling warto stosować, gdy WebSocket jest niedostępny: w sieciach korporacyjnych blokujących protokoły nie-HTTP, przy konieczności wstecznej kompatybilności ze starymi przeglądarkami lub ograniczeniach po stronie hostingu. WebSocket jest bardziej wydajny przy wymianie danych o wysokiej częstotliwości.
Zalecany timeout Long Polling to 30–45 sekund. Mniejsza wartość (10–15 sekund) zwiększa liczbę żądań, większa (60+ sekund) jest ryzykowna z powodu zrywania połączenia przez pośrednie load balancery. Wartość timeoutu zależy od architektury sieci i wymagań dotyczących opóźnienia.
Główne wady Long Polling — wysokie zużycie pamięci na serwerze przy utrzymywaniu tysięcy połączeń, trudność skalowania poziomego (wymagana scentralizowana kolejka zdarzeń) i brak prawdziwej komunikacji dwukierunkowej — do wysyłania danych na serwer potrzebne są osobne żądania POST.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również