Long Polling е техника за взаимодействие между клиент и сървър, при която сървърът държи HTTP заявката отворена до появата на нови данни или изтичане на тайм-аут. За разлика от периодичното запитване, сървърът не връща празен отговор веднага, а изчаква настъпване на събитие за изпращане на данни към клиента. Според MDN Web Docs, 2024, Long Polling остава търсено решение за приложения в реално време, където WebSocket не е наличен или е излишен.
Основни точки
Long Polling е модел на взаимодействие в архитектурата клиент-сървър, при който клиентът инициира HTTP заявка, а сървърът отлага изпращането на отговор до момента, в който се появят нови данни или изтече определен тайм-аут. След получаване на отговора клиентът незабавно изпраща следващата заявка, създавайки ефект на непрекъсната връзка.
Техниката Long Polling се появи като еволюционно развитие на Short Polling за намаляване на броя на празните HTTP заявки. При традиционното запитване клиентът изпраща заявки на всеки N секунди и сървърът отговаря дори при липса на нови данни. При Long Polling сървърът използва механизъм за задържане на връзката, което радикално намалява обема на безполезния трафик.
Преди появата на WebSocket през 2011 г., Long Polling беше основният начин за организиране на реално време в уеб. Компании като Facebook и Gmail използваха тази техника за своите чатове и уведомления в началото на 2010-те години. Според изследването High Performance Browser Networking (Grigorik, 2013), Long Polling обработваше до 95% от всички връзки в реално време в големите уеб приложения от този период.
Клиентът изпраща стандартна HTTP заявка към сървъра. Сървърът, след получаване на заявката, не връща отговор веднага — поставя заявката в опашка за изчакване. Когато на сървъра настъпи събитие (ново съобщение, промяна на данни), сървърът формира отговор и го изпраща на клиента. Клиентът, след получаване на отговора, незабавно създава нова Long Polling заявка и цикълът се повтаря.
Long Polling работи по следната последователност от стъпки. Клиентът изпраща HTTP GET заявка към сървърния endpoint. Сървърът, след получаване на заявката, проверява наличието на нови данни в опашката от събития. Ако няма данни, сървърът държи заявката в състояние на изчакване, без да изпраща отговор веднага. Механизмът на задържане зависи от имплементацията на сървъра — най-често се използва асинхронна обработка с callback или архитектура, базирана на събития.
Когато от страна на сървъра настъпи събитие (например потребител изпрати съобщение в чата), сървърът формира HTTP отговор с тяло, съдържащо тези данни, и прекратява връзката. Клиентът получава отговора, обработва данните и незабавно инициира нова заявка. Ако по време на изчакване данните не са се появили, сървърът изпраща празен отговор след изтичане на тайм-аута и клиентът също възстановява връзката. Timeout обикновено е 30-60 секунди за баланс между натоварване и закъснение.
Ключовият параметър за конфигуриране на Long Polling е тайм-аутът на изчакване. Твърде кратък тайм-аут (по-малко от 10 секунди) води до увеличаване на броя заявки, приближавайки техниката до Short Polling. Твърде дълъг (повече от 120 секунди) може да доведе до прекъсване на връзката от междинни проксита и балансьори на натоварването. Препоръчителната стойност за повечето сценарии е 30-45 секунди.
Ако на сървъра са настъпили няколко събития по време на една Long Polling заявка, сървърът трябва да ги предаде всички в един отговор или да организира опашка от събития от страна на клиента. За целта се използва буфериране на събития: сървърът събира събитията, настъпили по време на задържане на заявката, и ги предава като масив от данни в тялото на отговора.
Нека разгледаме проста имплементация на Long Polling от страна на клиента, използвайки модерния Fetch API. Клиентската функция изпраща заявка и рекурсивно се извиква след получаване на отговор.
async function longPoll(url) {
try {
const response = await fetch(url);
const data = await response.json();
handleData(data);
longPoll(url);
} catch (error) {
console.error("Грешка в Long Polling", error);
setTimeout(() => longPoll(url), 3000);
}
}
function handleData(data) {
if (data.events && data.events.length > 0) {
data.events.forEach(event => {
console.log("Ново събитие:", event);
});
}
}
longPoll("/api/events");
Този код създава безкраен цикъл на Long Polling: след получаване на отговора функцията незабавно изпраща нова заявка. При грешка на връзката се задава трисекундно закъснение преди повторен опит, за да се избегне лавинообразно натоварване на сървъра.
От страна на сървъра е необходимо да се задържи заявката до появата на събитие или изтичане на тайм-аута. Пример за имплементация, използваща EventEmitter в Node.js, демонстрира този механизъм.
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);
Сървърната част използва EventEmitter за уведомяване на чакащите Long Polling връзки при поява на нови данни. При достигане на 30-секундния тайм-аут сървърът връща празен масив от събития и клиентът създава нова заявка.
Long Polling се прилага в сценарии, където се изисква доставка на данни в реално време, но използването на WebSocket е невъзможно по технически или инфраструктурни причини. Най-честите случаи — корпоративни проксита и защитни стени, блокиращи WebSocket връзки, както и среди с ограничена поддръжка на протокола от страна на сървъра.
Ключовият фактор за избор на Long Polling е обратната съвместимост. Всички HTTP клиенти и сървъри поддържат този метод, което го прави универсално решение за реално време без допълнителни зависимости. Според HTTP Archive (2024), около 8% от всички уебсайтове продължават да използват Long Polling за основна функционалност в реално време.
Long Polling и Short Polling решават една и съща задача — доставка на данни от сървъра до клиента — но се различават съществено по механизъм и ефективност. Short Polling използва фиксиран интервал на запитване, при който клиентът изпраща HTTP заявки на равни интервали от време, независимо от това дали на сървъра са се появили нови данни.
| Характеристика | Long Polling | Short Polling |
|---|---|---|
| Иницииране на отговор | Сървърът изпраща данни при събитие | Сървърът отговаря на всяка заявка на клиента |
| Закъснение на доставка | Минимално, до 1 секунда | Зависи от интервала на запитване, 3-60 секунди |
| Брой заявки | 1 заявка на събитие или тайм-аут | N заявки за единица време (фиксиран) |
| Трафик в покой | Нисък (една отворена заявка) | Висок (заявки на всеки N секунди) |
| Натоварване на сървъра | Задържане на връзки | Обработка на чести заявки |
| Сложност на имплементация | Средна (асинхронна обработка) | Ниска (обикновени HTTP заявки) |
Short Polling е по-лесен за имплементиране, но създава значително по-голямо натоварване на сървъра и мрежата при същата честота на обновяване на данните. Ако е необходимо закъснение под 5 секунди, Short Polling генерира десетки заявки в минута, докато Long Polling използва една заявка на събитие или тайм-аут. За приложения с редки събития Long Polling е с порядък по-ефективен по отношение на трафика.
WebSocket е пълноценен двупосочен протокол за реално време, работещ върху TCP след начално HTTP ръкостискане. За разлика от Long Polling, WebSocket установява една постоянна връзка и позволява на сървъра да изпраща данни на клиента по всяко време без създаване на нова HTTP заявка.
Изборът между Long Polling и WebSocket зависи от няколко фактора. Съвместимост: Long Polling работи през всички проксита и защитни стени, WebSocket може да бъде блокиран от корпоративни мрежи. Производителност: WebSocket има по-малък overhead (2 байта на кадър в сравнение с пълни HTTP заглавки), което е критично при висока честота на съобщенията. Мащабируемост: Long Polling изисква повече ресурси от страна на сървъра поради задържане на множество връзки, WebSocket използва фиксирана връзка на сесия.
Според Mozilla Developer Network (2024), WebSocket се поддържа от всички модерни браузъри от версии 2011-2015, но корпоративните проксита (напр. Symantec Blue Coat) продължават да го блокират в 15-20% от корпоративните мрежи, което поддържа актуалността на Long Polling като fallback решение.
Често задавани въпроси
Long Polling е когато клиентът помоли сървъра: „отговори, когато се появят нови данни“, и сървърът държи връзката отворена, очаквайки събитие. Веднага щом данните се появят, сървърът отговаря, а клиентът веднага задава същия въпрос отново.
При Short Polling клиентът пита сървъра на всеки N секунди дали има данни, дори ако няма. При Long Polling клиентът пита веднъж и сървърът отговаря само когато данните наистина се появят. Long Polling създава по-малко празни заявки и намалява натоварването на мрежата.
Long Polling трябва да се използва, когато WebSocket не е наличен: в корпоративни мрежи с блокиране на не-HTTP протоколи, при необходимост от обратна съвместимост със стари браузъри или ограничения от страна на хостинга. WebSocket е по-ефективен за високочестотен обмен на данни.
Препоръчителният тайм-аут за Long Polling е 30-45 секунди. По-малка стойност (10-15 секунди) увеличава броя на заявките, по-голяма (60+ секунди) е рискова поради прекъсване на връзката от междинни балансьори. Стойността на тайм-аута зависи от архитектурата на мрежата и изискванията за закъснение.
Основните недостатъци на Long Polling — висока консумация на памет на сървъра при задържане на хиляди връзки, трудност при хоризонтално мащабиране (изисква централизирана опашка от събития) и липса на истинска двупосочна комуникация — за изпращане на данни към сървъра са необходими отделни POST заявки.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също