Очень доступным языком о Long-Polling?
2. Запрошенная страница выполняет JavaScript, который запрашивает файл от сервера.
3. Сервер НЕ реагирует на запрошенную информацию и ждет, пока не появится новой информации
4. Когда появляется новая информация, сервер отсылает ее клиенту
5. Клиент получает новую информацию и НЕМЕДЛЕННО отсылает другой запрос серверу, запуская процесс ожидания на нем снова.
Что значит 3 и 4 пункты? В каком смысле, ждет пока не появится новой информации? Я лично вижу это так:
Хочу сэмулировать, чтобы понять.
Пишет человек в чат:
First User: Привет (это сообщение отправлено на сервер, но не реагирует на это сообщение, то есть Second User это сообщение не получает?)
First User: Еще раз привет! (А вот это сообщение уже доставлено Second User, т.к. появилась новая информация, и можно отослать клиенту ее?)
Second User: Привет! (и тут также, сообщение отправлено, но не реагирует сервер на сообщение, пока он не напишет еще чего то?)
Можно немного подробнее пояснить? в таком же примере, потому что из статей я что-то ничего не понял. Спасибо)
- Вопрос задан более трёх лет назад
- 27229 просмотров
1 комментарий
Средний 1 комментарий
Длинные опросы
Длинные опросы – это самый простой способ поддерживать постоянное соединение с сервером, не используя при этом никаких специфических протоколов (типа WebSocket или Server Sent Events).
Его очень легко реализовать, и он хорошо подходит для многих задач.
Частые опросы
Самый простой способ получать новую информацию от сервера – периодический опрос. То есть, регулярные запросы на сервер вида: «Привет, я здесь, у вас есть какая-нибудь информация для меня?». Например, раз в 10 секунд.
В ответ сервер, во-первых, помечает у себя, что клиент онлайн, а во-вторых посылает весь пакет сообщений, накопившихся к данному моменту.
Это работает, но есть и недостатки:
- Сообщения передаются с задержкой до 10 секунд (между запросами).
- Даже если сообщений нет, сервер «атакуется» запросами каждые 10 секунд, даже если пользователь переключился куда-нибудь или спит. С точки зрения производительности, это довольно большая нагрузка.
Так что, если речь идёт об очень маленьком сервисе, подход может оказаться жизнеспособным, но в целом он нуждается в улучшении.
Длинные опросы
«Длинные опросы» – гораздо лучший способ взаимодействия с сервером.
Они также очень просты в реализации, и сообщения доставляются без задержек.
Как это происходит:
- Запрос отправляется на сервер.
- Сервер не закрывает соединение, пока у него не возникнет сообщение для отсылки.
- Когда появляется сообщение – сервер отвечает на запрос, посылая его.
- Браузер немедленно делает новый запрос.
Для данного метода ситуация, когда браузер отправил запрос и удерживает соединение с сервером в ожидании ответа, является стандартной. Соединение прерывается только доставкой сообщений.
Если соединение будет потеряно, скажем, из-за сетевой ошибки, браузер немедленно посылает новый запрос.
Примерный код клиентской функции subscribe , которая реализует длинные опросы:
async function subscribe() < let response = await fetch("/subscribe"); if (response.status == 502) < // Статус 502 - это таймаут соединения; // возможен, когда соединение ожидало слишком долго // и сервер (или промежуточный прокси) закрыл его // давайте восстановим связь await subscribe(); >else if (response.status != 200) < // Какая-то ошибка, покажем её showMessage(response.statusText); // Подключимся снова через секунду. await new Promise(resolve =>setTimeout(resolve, 1000)); await subscribe(); > else < // Получим и покажем сообщение let message = await response.text(); showMessage(message); // И снова вызовем subscribe() для получения следующего сообщения await subscribe(); >> subscribe();
Функция subscribe() делает запрос, затем ожидает ответ, обрабатывает его и снова вызывает сама себя.
Сервер должен поддерживать много ожидающих соединений.
Архитектура сервера должна быть способна работать со многими ожидающими подключениями.
Некоторые серверные архитектуры запускают отдельный процесс для каждого соединения. Для большого количества соединений будет столько же процессов, и каждый процесс занимает значительный объём памяти. Так много соединений просто поглотят всю память.
Часто такая проблема возникает с бэкендом, написанными на PHP или Ruby, но технически дело не в языке, а в реализации. На большинстве современных языков можно написать подходящий сервер, но на некоторых это проще сделать.
Бэкенды, написанные с помощью Node.js, обычно не имеют таких проблем.
Демо: чат
Вот демо-чат, вы также можете скачать его и запустить локально (если вам знаком Node.js и можете поставить модули):
Long polling
Long polling is the simplest way of having persistent connection with server, that doesn’t use any specific protocol like WebSocket or Server Sent Events.
Being very easy to implement, it’s also good enough in a lot of cases.
Regular Polling
The simplest way to get new information from the server is periodic polling. That is, regular requests to the server: “Hello, I’m here, do you have any information for me?”. For example, once every 10 seconds.
In response, the server first takes a notice to itself that the client is online, and second – sends a packet of messages it got till that moment.
That works, but there are downsides:
- Messages are passed with a delay up to 10 seconds (between requests).
- Even if there are no messages, the server is bombed with requests every 10 seconds, even if the user switched somewhere else or is asleep. That’s quite a load to handle, speaking performance-wise.
So, if we’re talking about a very small service, the approach may be viable, but generally, it needs an improvement.
Long polling
So-called “long polling” is a much better way to poll the server.
It’s also very easy to implement, and delivers messages without delays.
- A request is sent to the server.
- The server doesn’t close the connection until it has a message to send.
- When a message appears – the server responds to the request with it.
- The browser makes a new request immediately.
This situation, where the browser has sent a request and keeps a pending connection with the server, is standard for this method. Only when a message is delivered, the connection is closed and reestablished.
If the connection is lost, because of, say, a network error, the browser immediately sends a new request.
A sketch of client-side subscribe function that makes long requests:
async function subscribe() < let response = await fetch("/subscribe"); if (response.status == 502) < // Status 502 is a connection timeout error, // may happen when the connection was pending for too long, // and the remote server or a proxy closed it // let's reconnect await subscribe(); >else if (response.status != 200) < // An error - let's show it showMessage(response.statusText); // Reconnect in one second await new Promise(resolve =>setTimeout(resolve, 1000)); await subscribe(); > else < // Get and show the message let message = await response.text(); showMessage(message); // Call subscribe() again to get the next message await subscribe(); >> subscribe();
As you can see, subscribe function makes a fetch, then waits for the response, handles it and calls itself again.
Server should be ok with many pending connections
The server architecture must be able to work with many pending connections.
Certain server architectures run one process per connection, resulting in there being as many processes as there are connections, while each process consumes quite a bit of memory. So, too many connections will just consume it all.
That’s often the case for backends written in languages like PHP and Ruby.
Servers written using Node.js usually don’t have such problems.
That said, it isn’t a programming language issue. Most modern languages, including PHP and Ruby allow to implement a proper backend. Just please make sure that your server architecture works fine with many simultaneous connections.
Demo: a chat
Here’s a demo chat, you can also download it and run locally (if you’re familiar with Node.js and can install modules):
HTTP Long Polling
HTTP Long Polling (или Server-Sent Events) — технология и способ взаимодействия между клиентом и сервером. Long Polling предполагает установление постоянного соединения между клиентом и сервером.
Клиент-серверная модель в стандартном виде подразумевает, что инициатором любого обмена данными является клиент. Сервер всегда находится в сети и работает, отдавая контент только тогда когда к нему обращается клиент.
Такая организация не очень хорошо подходит для ряда приложений. Например, мэссенджеров и социальных сетей. В любой социальной сети есть лента новостей или уведомления, сообщения в них должны появляться не тогда когда приходит запрос от клиента, а тогда когда на сервер поступают новые данные.
Реализовать это позволяет HTTP Long Poling.
Модель HTTP Long Polling
HTTP Long Poling в общем работает следующим образом:
1. Клиент обращается к серверу с запросом
2. Сервер предоставляет ответ, оставляя при этом соединение открытым
3. Как только на сервер поступает новая информация, адресованная клиенту, информация направляется к нему используя открытое соединение. Пакеты, отправляемые таким образом называются push notifications
Как только клиент получает информацию, он вновь отправляет запрос и устанавливая соединение с сервером, далее процесс повторяется.
Фактически, создается подобие модели при которой запросы генерируются сервером. Клиент всегда готов принимать HTTP запросы, которые отправляет сервер.
При использовании Server-Sent Events (HTTP Long Poling) в приложении всегда возникает ряд моментов и потенциальных сложностей, основные из них
- Использование WiFI и сетей мобильных операторов с постоянным переключением между ними — при этом меняется IP адрес и разрывается соединение
- Сообщения могут теряться если клиент недоступен, система должна быть организована так, чтобы все сообщения доходили, при этом в нужном порядке
- Балансировка нагрузки между серверами, обеспечивающими Long Poling
Все задачи можно реализовать самостоятельно или воспользоваться готовыми решениями, некоторые провайдеры предлагают потоковые стриминговые сети, способные обрабатывать большие объемы данных в режиме реального времени.
Приложения, требующие использования технологий передачи данных, инициализируемых сервером обычно используют AJAX запросы Javascript или написаны на Ruby/Python.