Почему опрос принят в веб-программировании?

108

В настоящее время я работаю над проектом Ruby on Rails, который показывает список изображений.

Обязательным для этого проекта является то, что он показывает новые сообщения в режиме реального времени без необходимости обновления веб-страницы. После поиска я наткнулся на некоторые решения и сервисы JavaScript, такие как PubNub; однако ни одно из предложенных решений не имело смысла вообще.

В решении JavaScript ( опрос ) происходит следующее:

  • Пользователь 1 просматривает список фотографий.
  • В фоновом режиме код JavaScript опрашивает конечную точку каждую секунду, чтобы увидеть, есть ли новый пост.
  • Пользователь 2 добавляет новое фото.
  • Перед запуском нового цикла и получением новых данных существует задержка в 50 мс.
  • Новый контент загружается в DOM .

Это кажется странным, когда переводится на реальный пример:

  • Пользователь 1 держит кучу фотографий на своем столе.
  • Он / она идет к фотографу каждую секунду и спрашивает, есть ли у него новый.
  • Фотограф делает новое фото.
  • В эту секунду, когда он или она входит, она может сделать снимок и положить его на стопку.

На мой взгляд, решение должно быть следующим:

  • Пользователь 1 держит кучу фотографий на своем столе.
  • Фотограф снимает новую фотографию.
  • Фотограф идет к груде и кладет ее вместе с остальными.

Решение PubNub в основном то же самое, однако на этот раз между сторонами происходит обмен стажерами для обмена данными.

Излишне говорить, что оба решения потребляют много энергии, так как они запускаются даже при отсутствии данных для загрузки.

Насколько мне известно, нет (логического) объяснения, почему этот способ реализации используется почти в каждом приложении реального времени.

Деннис
источник
195
На мгновение не обращая внимания на то, что веб-браузеры не являются серверами, которые могут принимать входящие соединения ... подождите, нет, давайте не будем это игнорировать
GrandmasterB
17
@dennis: постоянная связь между сервером и клиентом с сохранением состояния, вероятно, избавит от необходимости опроса, но это не то, как был разработан веб.
FrustratedWithFormsDesigner
58
Как насчет Websockets?
I.devries
25
Или взгляните на длительный опрос. В основном вы опрашиваете, но сервер не отвечает до того, как у него появятся новые данные.
Мацеманн
53
Есть много совершенно разумных решений и алгоритмов в компьютерном пространстве, которые было бы абсолютно абсурдным в мясном пространстве.
whatsisname

Ответы:

179

Нажатие работает хорошо для 1 или ограниченного числа пользователей.

Теперь измените сценарий с одним фотографом и 1000 пользователей, которые все хотят копию картины. Фотографу придется пройти до 1000 стопок. Некоторые из них могут быть в запертом офисе или разбросаны по полу. Или их пользователь в отпуске и не интересуется новыми картинками на данный момент.

Фотограф будет постоянно гулять, а не делать новые снимки.

Принципиально: модель опроса / опроса лучше масштабируется для большого количества ненадежных читателей со слабыми требованиями в реальном времени (если картинка занимает 10 секунд спустя, чтобы получить кучу, в чём дело?).

Тем не менее, пуш-модель все еще лучше во многих ситуациях. Если вам нужна низкая задержка (вам нужно новое фото через 5 с после того, как оно было снято), или обновления редки и требуют частых и предсказуемых действий (продолжайте спрашивать фотографа каждые 10 секунд, когда он генерирует новое изображение в день), тогда вытягивание нецелесообразно. Это зависит от того, что вы пытаетесь сделать. NASDAQ: толчок. Метеослужба: тянуть. Свадебный фотограф: наверное, тянуть. Новостное фотоагентство: наверное, толчок

ptyx
источник
32
Мне очень нравится ваша аналогия с 1000 пользователей, некоторые в отпуске, некоторые не заинтересованы. +1.
riwalk
4
@EsbenSkovPedersen: ограничение сокета не связано с IP-адресом. Это связано с максимально открытым дескриптором файла. Таким образом, максимальное количество открытых сокетов не зависит от того, сколько IP-адресов вы используете.
Slebetman
10
Это ужасная аналогия, мягко говоря. Чтобы пуш работал, клиент любого пользователя должен поддерживать какое-то открытое соединение. На самом деле опрос - это эмуляция соединения. Это не так, потому что некоторые клиенты опрашивают, что все клиенты уведомлены. Аналогично, когда некоторые клиенты открывают соединение для push-уведомлений, не все клиенты получают уведомление. Это очень плохой совет, который предлагает выбрасывать ресурсы в окно. Быть засыпанным 10000 запросов в секунду практически никогда не дешевле и не лучше, чем поддерживать 10000 открытых сокетов.
back2dos
8
@ptyx: здесь обсуждается интервал 1 с. 10 тыс. Запросов в секунду означает 10 тыс. TCP-рукопожатий и 10 тыс. HTTP-запросов (каждый из которых легко достигает 2 КБ), что дает вам на несколько порядков больше фонового шума, стучащего по вашему серверу. Существует множество проверенных в бою библиотек, которые делают push-подписки такими же простыми, как и опрос. Есть даже такие фреймворки, как meteor.js, которые полностью абстрагируют всю проблему. Обращение к масштабируемости без каких-либо дополнительных объяснений также вряд ли является аргументом. Во всяком случае, я высказал свои сомнения и не хочу начинать обсуждение;)
back2dos
5
Я согласен с комментарием back2dos выше. Если бы pull масштабировался лучше, чем push, в Google, стек-обмене, Facebook, онлайн-сервисах и т. Д. Использовалась бы технология pull. Но они этого не делают. По сути, удар по серверу вместо настройки станции прослушивания ужасно масштабируется. Основные службы избегают опроса.
Трэвис Дж
106

Я действительно удивлен, что только один человек упомянул WebSockets . Поддержка реализована практически во всех основных браузерах .

На самом деле PubNub использует их. Для вашего приложения браузер, вероятно, подпишется на сокет, который будет транслироваться при появлении новой фотографии. Заметьте, сокет не отправит фотографию, а просто ссылку, чтобы браузер мог загрузить ее асинхронно.

В вашем примере представьте что-то вроде:

  1. Пользователь (-и) сообщает фотографу, что он хочет знать обо всех будущих фотографиях
  2. Фотограф говорит через громкоговоритель, что доступно новое фото
  3. Пользователь просит фотографа за фото

Это немного похоже на ваш оригинальный пример решения. Это более эффективно, чем опрос, потому что клиенту не нужно отправлять какие-либо данные на сервер (за исключением, возможно, пульса ).

Кроме того, как уже упоминалось, есть другие методы, которые лучше, чем простой опрос, которые работают в старых браузерах ( longpolling и др .)

korylprince
источник
43
@RobertHarvey, почему WebSockets не связаны с этим вопросом? Вопрос состоит в том, является ли опрос приемлемой стратегией, и в настоящее время он явно не приемлем (или, по крайней мере, не оптимален). WebSockets, отправленные сервером события и длительный опрос работают намного лучше практически в каждом случае использования.
Фабрисио Мате
7
@RobertHarvey, это была только моя интерпретация, насколько я вижу, никакого перефразирования. Конечно, вопрос задавался, почему это все еще принято, а не какова оптимальная стратегия , но они все еще тесно связаны между собой.
Фабрисио Мате
25
WebSockets (и тому подобное) являются наиболее близкими к реализации «решения» ОП, поэтому я думаю, что это очень актуально, несмотря на то, что он не упомянул об этом конкретно.
korylprince
6
Не говоря уже о том, что StackExchangeсайты, подобные тому, на котором вы сейчас находитесь (если вы не просматриваете эту страницу в кэше / сохранены), используются WebSockets. Вот почему мне также было интересно, почему никто, кроме @korylprince, не упомянул WebSockets.
Трис
6
@ FabrícioMatté: на самом деле, не каждый случай использования. Длительный опрос требует, чтобы сокет был открыт для всех пользователей, которые занимают системные ресурсы. Для сервисов, которые не очень критичны по времени, но имеют много пользователей, держать сокет открытым обычно дороже, чем обслуживание коротких 304 время от времени. Для большинства услуг небольшая задержка не является проблемой. Одна машина обычно может обслуживать больше клиентов с помощью опроса, чем с помощью push.
Ли Райан
42

Иногда достаточно хорошо, достаточно хорошо.

Из всех возможных способов реализации коммуникационного процесса в режиме реального времени опрос является, пожалуй, самым простым способом. Опрос может использоваться эффективно, когда интервал опроса относительно большой (т. Е. Секунды, минуты или часы, а не мгновенные), и такты, используемые при проверке соединения или ресурса, на самом деле не имеют значения.

Роберт Харви
источник
3
Это в тысячу раз больше. Это принято, потому что это обычно достаточно хорошо.
CorsiKa
1
Это достаточно хороший ответ
Zain R
31

Протокол HTTP ограничен тем, что клиент ДОЛЖЕН быть тем, кто инициирует запрос. Сервер не может связаться с клиентом, если не отвечает на запрос клиента.

Поэтому, чтобы настроить пример из реального мира, добавьте следующее ограничение:

  • Пользователь 2 может ТОЛЬКО отвечать на вопросы Пользователя 1 одним предложением, после чего Пользователь 1 должен уйти. У пользователя 2 нет другого способа общения.

С этим новым ограничением, как бы вы сделали это, кроме голосования?

riwalk
источник
6
HTTP 2.0 будет поддерживать запросы сервера. «Нажатие позволяет серверам отправлять представления клиентам без явного запроса». en.wikipedia.org/wiki/HTTP_2.0
kaptan
5
@kaptan, это здорово, но его нет в наличии. Делай то, что у тебя есть.
riwalk
7
Существует также длинный опрос, который доступен прямо сейчас и имитирует пуш-модель с использованием тяги.
Тим Б
24
@dennis: Написав программное обеспечение для промышленной автоматизации, я бы хотел прокомментировать пример опроса датчиков. Опрос датчиков служит двум целям - наиболее очевидным является получение новых данных. Менее очевидным является обнаружение того, что датчик все еще жив, не разбился из-за ошибки или ожога из-за пожара на заводе или расплавился из-за промышленной аварии. Молчание, тот факт, что вы не получили ответа, также является ценной информацией.
Slebetman
3
Датчики @dennis часто чувствуют себя намного быстрее, чем вас интересуют данные. Опрос позволяет вам получить значение датчика именно тогда, когда вы этого хотите, не будучи залиты обновлениями, которые вас не интересуют. (Представьте, если ОС уведомляет ваше приложение каждый раз, когда файл изменяется где-либо на диске, вместо того, чтобы ваше приложение открывало и читало файл)
immibis
13

Почему опрос принят? Ведь на самом деле каждое решение - это опрос низкого уровня!

Если сервер должен обновить вас, как только появятся новые изображения, он обычно должен иметь к вам соединение - потому что IP-адреса часто меняются, и вы никогда не узнаете, кому-то это больше не интересно, поэтому клиент должен отправить какую-то форму сигнал подтверждения активности, например: «Я все еще здесь, я не в сети»

Все соединения с состоянием (например, TCP / IP) работают одинаково, поскольку вы можете отправлять только отдельные пакеты данных через Интернет; Вы никогда не знаете, если другая сторона все еще там.

Таким образом, у каждого протокола есть тайм-аут. Если объект не отвечает в течение X секунд, он считается мертвым. Таким образом, даже если у вас есть только открытое соединение между сервером и клиентом, без отправки каких-либо данных, сервер и клиент должны отправлять регулярные пакеты keep-alive (это обрабатывается на низком уровне, если вы открываете соединение между ними) - и как это в конце концов отличается от опроса?

Таким образом, лучший подход, вероятно, будет длинным опросом:

Клиент отправляет запрос сразу после загрузки сайта (например, говорит фотографу «Скажите, есть ли новые фотографии»), но сервер не отвечает, если новых фотографий нет. Как только запрос истекает, клиент снова просит.

Если на сервере появились новые изображения, он может немедленно ответить всем клиентам, которые стоят в очереди за новыми изображениями. Таким образом, ваше время реакции после нового изображения даже короче, чем с push, поскольку клиент все еще ожидает ответа в открытом соединении, и вам не нужно устанавливать соединение с клиентом. И запросы на опрос от клиента не намного больше трафика, чем постоянное соединение между клиентом и сервером для ответа!

Falco
источник
Я не согласен с тем, что каждое решение - это опрос низкого уровня. Вы путаете опрос, требуемый для отправки данных, с опросом, необходимым, чтобы знать, когда клиент потерян. Да, последний всегда будет заканчивать опрос где-нибудь в стеке протоколов, но это может происходить с очень низкой частотой (например, раз в пять минут), тогда как опрос фактических данных каждую секунду - это пустая трата, которую МОЖНО избежать с помощью настоящих push-уведомлений это НЕ опрос на любом уровне стека.
Аллон Гуралнек
Во-первых, большинство пакетов keepalive выполняются с довольно высокой частотой, потому что вы хотите избежать общих интервалов тайм-аута, так что несколько секунд не являются редкостью для TCP / IP и почти все, что не использует tcp, может быть заблокировано брандмауэрами. Поэтому, когда мне нужно отправлять пакет данных каждые X секунд, почему бы не заполнить его некоторыми данными практически бесплатно?
Falco
1
@Guralnek, даже если у вас было соединение с интервалом поддержания активности в 5 минут, время ожидания будет выше, так как вам нужно добавить фактическую задержку и потерянные пакеты. И сервер будет сохранять много подключений в течение 5 минут после отключения клиентов, поэтому в целом это, вероятно, будет стоить больше ресурсов сервера при сохранении только минимальной пропускной способности
Falco
1
+1 за длительный опрос. Посмотрите комету en.wikipedia.org/wiki/Comet_%28programming%29
Zan Lynx
9

Одно из преимуществ опроса состоит в том, что он ограничивает вред, который может быть причинен, если сообщение пропадает или происходит сбой в состоянии чего-либо. Если X запрашивает Y о своем состоянии один раз каждые пять секунд, то потеря запроса или ответа приведет к тому, что информация X будет на десять секунд устаревшей, а не 5. Если Y перезагрузится, X может узнать об этом в следующем время Y может ответить на одно из сообщений X. Если X будет перезагружен, он может никогда не спросить Y о чем-либо после этого, но тот, кто наблюдает за статусом X, должен признать, что он был перезагружен.

Если вместо опроса X Y, X полагался на Y, чтобы сообщать ему всякий раз, когда его состояние изменялось, тогда, если состояние Y изменилось, и он отправил сообщение X, но по какой-либо причине это сообщение не было получено, X может никогда не узнать об изменении , Точно так же, если Y перезагружается и у него никогда нет причин отправлять X сообщение о чем-либо.

В некоторых случаях для X может быть полезно запросить, чтобы Y автономно отправлял сообщения со своим статусом, либо периодически, либо когда он изменяется, и проводил опрос X, только если он идет слишком долго, ничего не слыша от Y. Такой дизайн может устранить необходимо, чтобы X отправлял большинство своих сообщений (обычно X должен хотя бы иногда сообщать Y, что он все еще заинтересован в получении сообщений, а Y должен прекратить отправку сообщений, если он идет слишком долго без каких-либо признаков интереса). Такой дизайн, однако, потребовал бы, чтобы Y постоянносохранить информацию о X, вместо того, чтобы просто отправлять ответ тому, кто ее опрашивал, и сразу же забывать, кто это был. Если Y является встроенной системой, такое упрощение может помочь в достаточной степени уменьшить требования к памяти, чтобы позволить использовать меньший и более дешевый контроллер.

Опрос может иметь дополнительное преимущество при использовании потенциально ненадежной среды связи (например, UDP или радио): он может в значительной степени устранить необходимость в подтверждениях канального уровня. Если X отправляет Y запрос состояния Q, Y отвечает отчетом о состоянии R, а X слышит R, X не нужно будет слышать какое-либо подтверждение канального уровня для Q, чтобы узнать, что оно было получено. И наоборот, как только Y отправляет R, ему не нужно знать или заботиться, получил ли X его. Если X отправляет запрос статуса и не получает ответа, он может отправить другой. Если Y отправляет отчет, а X не слышит его, X отправит другой запрос. Если каждый запрос отправляется один раз и либо дает ответ, либо нет, ни одна из сторон не должна знать или заботиться о том, было ли получено какое-либо конкретное сообщение. Поскольку отправка подтверждения может потреблять почти столько же пропускной способности, сколько запрос статуса или отчет, использование двустороннего запроса-отчета не стоит намного дороже, чем нежелательный отчет и подтверждение. Если X отправляет несколько запросов без получения ответов, в некоторых динамически маршрутизируемых сетях может потребоваться включить подтверждения на уровне канала (и запросить в своем запросе, что Y делает аналогичным образом), чтобы базовый стек протоколов мог распознать проблему доставки и выполнить поиск новый маршрут, но когда все работает, модель запроса-отчета будет более эффективной, чем использование подтверждений на уровне канала.

Supercat
источник
Проблема, о которой вы говорите, когда Y отправляет сообщения в X (второй абзац), может быть исправлена ​​путем добавления серийного номера к каждому сообщению. Если сообщение потеряно, X узнает, потому что он не получил этот сериал. На этом этапе могут быть приняты другие меры для синхронизации с Y. DNS master -> slave replication работает таким образом.
korylprince
@korylprince: Любая сторона может узнать о пропущенном сообщении, если другая сторона имеет возможность отправить что-то (и делает это успешно), или если у нее есть причина ожидать чего-то от другой стороны и никогда не получит его. Если одна сторона отправляет обновление статуса и либо не требует подтверждений, либо сдается после повторных попыток несколько раз, а другая сторона не ожидает запланированных передач, другая сторона не будет знать, что соединение исчезло.
суперкат
2
@korylprince - проблема в том, что без периодических сообщений X может обнаружить пропущенное сообщение с опозданием на день, на год или на 10 лет позже. Чтобы обнаружить пропущенный пакет в разумные сроки, нужно как-то опросить. Вы можете «вытянуть» опрос или вы можете «подтолкнуть» опрос. Первый называется "опрос", второй называется "сердцебиение"
slebetman
Оба очень верны. Все зависит от ситуации.
korylprince
@slebetman: Без периодических сообщений, если Y будет перезагружен, возможно, не будет механизма, с помощью которого X когда-либо обнаружит его.
суперкат
1

Вопрос в том, чтобы сбалансировать количество ненужных опросов и количество ненужных нажатий.

Если вы опросите:

  • Вы получите ответ в этот самый момент. Хорошо, если вы спрашиваете только изредка или вам нужен набор данных в этот самый момент.
  • Вы можете получить ответ «без контента», что приведет к бессмысленной загрузке линии.
  • Вы ставите нагрузку на линию только при опросе, но всегда при опросе.

Если вы нажмете:

  • Вы доставляете ответ правильно, когда он доступен, что позволяет немедленно обрабатывать на стороне клиента.
  • Вы можете доставлять данные клиентам, которые не заинтересованы в этих данных, что приводит к бессмысленной загрузке линии.
  • Вы помещаете нагрузку в линию каждый раз, когда появляются новые данные, но только когда появляются новые данные.

Существует несколько решений о том, как справляться с различными сценариями и их недостатками, например, например, минимальное время между опросами, прокси-серверы только для опросов, чтобы снять нагрузку с основной системы, или - для толчков - правила регистрации и указания требуемые данные с последующей отменой регистрации при выходе из системы. Какой из них подходит лучше всего, вы ничего не можете сказать в общем, это зависит от системы.

В вашем примере опрос является не самым эффективным решением, но самым практичным. Очень легко написать систему опроса на JavaScript, а также очень легко реализовать ее на стороне доставки. Сервер, созданный для доставки данных изображения, должен иметь возможность обрабатывать дополнительные запросы, а если нет, то он может линейно масштабироваться, поскольку данные в основном статичны и поэтому могут легко кэшироваться.

Метод push, реализующий вход в систему, описание требуемых данных и, наконец, выход из системы, был бы наиболее эффективным, но, вероятно, слишком сложным для обычного «сценария-ребенка», и ему необходимо решить вопрос: что, если пользователь просто выключает браузер и выход из системы не может быть выполнен?

Может быть, лучше иметь больше пользователей (так как доступ к ним проще), чем сохранять несколько долларов на другом кеш-сервере?

TwoThe
источник
1

По какой-то причине в наши дни все молодые веб-разработчики, похоже, забыли уроки прошлого и почему некоторые вещи развивались так, как они это делали.

  1. Пропускная способность была проблемой
  2. Соединение может быть прерывистым.
  3. Браузеры не обладали такой вычислительной мощностью
  4. Были и другие способы доступа к контенту. Сеть не w3.

Перед лицом этих ограничений у вас может не быть постоянной двусторонней связи. И если вы посмотрите на модель OSI, вы обнаружите, что большинство соображений предназначены для отделения постоянства с базовым соединением.

Имея это в виду, метод опроса получения информации является отличным способом уменьшить пропускную способность и вычисления на стороне клиента. Рост push - это, по большей части, просто клиент, выполняющий постоянный опрос или веб-сокеты. Лично, если бы я был всем остальным, я бы оценил регулярность опроса как средство анализа трафика, когда несвоевременный запрос GET / POST сигнализировал бы о человеке, находящемся в какой-то средней ситуации.

guestaccount
источник