Чому опитування приймається у веб-програмуванні?


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: поштовх. Служба погоди: тяг. Весільний фотограф: напевно, тягне. Агентство фото новин: напевно, натисніть.


32
Мені дуже подобається ваша аналогія з 1000 користувачами, деякі у відпустці, деякі не цікавляться. +1.
riwalk

4
@EsbenSkovPedersen: Ліміт сокета не пов’язаний з IP-адресою. Це пов'язано з максимальним дескриптором відкритого файлу. Отже максимальна кількість відкритого сокета не залежить від кількості IP-адрес, які ви використовуєте.
slebetman

10
Це жахлива аналогія, м'яко кажучи. Для того, щоб поштовх працював, будь-який клієнт повинен підтримувати відкрите з'єднання. Насправді опитування - це емуляція зв'язку. Це не так, тому що деякі клієнти опитують, що всі клієнти отримують сповіщення. Аналогічно, коли деякі клієнти відкривають з'єднання для push-повідомлень, не всі клієнти отримують сповіщення. Це дуже погана порада, яка запрошує викинути ресурси у вікно. Обстріл 10000 запитами в секунду практично ніколи не дешевший або інакше кращий, ніж підтримка 10000 відкритих розеток.
back2dos

8
@ptyx: Інтервал 1s - це той, про який йде мова. 10k запитів в секунду означає 10k TCP рукостискань і 10k HTTP запитів (кожен легко досягає 2KB), що дає вам на кілька порядків більше фонового шуму, що забиває ваш сервер. Існує безліч бібліотечних тестованих бібліотек, які роблять накладні підписки настільки ж простими, як і встановлення опитування на місці. Навіть є такі структури, як meteor.js, які повністю абстрагують всю проблему. Звернення до масштабованості без додаткових пояснень також навряд чи є аргументом. У всякому разі, я висловив свої сумніви і не бажаю починати дискусію;)
back2dos

5
Я згоден з коментарем back2dos вище. Якщо витягнути масштаб краще, ніж push, google, обмін стеками, facebook, онлайн-фондові послуги тощо, використовували б технологію pull. Але вони цього не роблять. По суті, забивання сервера замість того, щоб налаштовувати станцію прослуховування, жахливо масштабує. Основні служби уникають опитування.
Travis J

106

Я дуже здивований, що лише одна людина згадала WebSockets . Підтримка реалізована в основному у кожному великому браузері .

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

У своєму прикладі уявіть щось на кшталт:

  1. Користувачі дають фотографу знати, що він хоче знати про всі майбутні фотографії
  2. Фотограф каже через гучномовець, що доступна нова фотографія
  3. Користувач запитує у фотографа фотографію

Це дещо схоже на ваше оригінальне прикладне рішення. Це ефективніше, ніж опитування, оскільки клієнту не потрібно надсилати будь-які дані на сервер (крім, можливо, серцебиття ).

Також, як згадували інші, є й інші методи, які краще, ніж прості опитування, які працюють у старих браузерах ( longpolling та ін .)


43
@RobertHarvey, чому веб-сокети не пов'язані з питанням? Питання задає питання про те, чи є опитування прийнятною стратегією, і сьогодні явно не прийнятна (або не принаймні оптимальна). WebSockets, події, що надсилаються сервером, і тривале опитування працюють набагато краще практично у кожному випадку використання.
Фабріціо Матте

7
@RobertHarvey, це було лише моєю інтерпретацією, без рефреймінгу, наскільки я бачу. Звичайно, питання, чому це все ще прийнято, а не яка оптимальна стратегія , але вони все ще тісно пов'язані.
Фабрісіо Матте

25
WebSockets (тощо) є найбільш близькими до реалізації "рішення" ОП, тому я думаю, що це дуже актуально, незважаючи на те, що він не згадує про це конкретно.
korylprince

6
Не кажучи вже про те, що StackExchangeтакі сайти, як той, на якому ви зараз перебуваєте (якщо ви не переглядаєте цю веб-сторінку, кешовану / збережену), використовуєте WebSockets. Ось чому мені також було цікаво, чому ніхто до тих пір, поки @korylprince не згадав WebSockets.
trysis

6
@ FabrícioMatté: насправді не у всіх випадках використання. Тривале опитування вимагає збереження розетки відкритою для всіх користувачів, які забирають системні ресурси. Fr служби, які не дуже критичні за часом, але мають багато користувачів, тримати розетку відкритою зазвичай дорожче, ніж обслуговування коротких 304 раз у раз. Для більшості послуг невелика затримка не є проблемою. Одна машина зазвичай може обслуговувати більше клієнтів з опитуванням, ніж з натисканням.
Лежати Райан

42

Іноді досить добре - досить добре.

З усіх можливих способів реалізації процесу зв’язку в режимі реального часу опитування є чи не найпростішим способом. Опитування може бути ефективно використане, коли інтервал опитування відносно довгий (тобто секунди, хвилини або години, а не миттєвий), а цикли годин, витрачені на перевірку з'єднання або ресурсу, насправді не мають значення.


3
Це, у тисячу разів більше, ніж це. Це прийнято, тому що це зазвичай досить добре.
corsiKa

1
Це досить хороша відповідь
Zain R

31

Протокол HTTP обмежений тим, що клієнт ОБОВ'ЯЗКОВО повинен бути ініціатором запиту. Сервер не може спілкуватися з клієнтом, якщо не відповів на запит клієнта.

Отже, щоб налаштувати приклад вашого реального світу, додайте таке обмеження:

  • Користувач 2 може ТОЛЬКО відповісти на запитання Користувача 1 одним реченням, після чого Користувач 1 повинен піти. Користувач 2 не має іншого способу спілкування.

З цією новою стриманістю, як би ви це зробили, крім опитування?


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 секунд, він вважається мертвим. Тож навіть якщо у вас є лише відкрите з'єднання між сервером і клієнтом, не надсилаючи жодних даних, сервер і клієнт повинні надсилати регулярні пакети збереження живих даних (це обробляється на низькому рівні, якщо ви відкриваєте з'єднання між ними) - і як це це зрештою щось відрізняється від опитування?

Тож найкращим підходом, мабуть, буде довготривале опитування:

Клієнт відправляє запит одразу після завантаження сайту (наприклад, кажу фотографові "Скажи мені, чи є якісь нові фотографії"), але сервер не відповідає, якщо немає нових фотографій. Як тільки запит вичерпується, клієнт запитує знову.

Якщо на сервері з'явилися нові зображення, він може негайно відповісти на всіх клієнтів, які стоять у черзі на нові фотографії. Тож ваш час реакції після нового зображення ще коротший, ніж при натисканні, оскільки клієнт все ще чекає у відкритому з'єднанні на відповідь, і вам не доведеться встановлювати з'єднання з клієнтом. А запити на опитування від клієнта не набагато більше трафіку, ніж постійний зв’язок між клієнтом і сервером для відповіді!


Я не погоджуюся, що кожне рішення закінчується опитуванням на низькому рівні. Ви плутаєте опитування, необхідне для надсилання даних із опитуваннями, необхідними для того, щоб знати, коли клієнт втрачений. Так, останні завжди закінчуватимуться опитуванням десь під стеком протоколів, але це може бути з дуже низькою частотою (наприклад, раз на п’ять хвилин), тоді як опитування фактичних даних щосекунди є марною тратою, якої неможливо уникнути справжніми push-повідомленнями тобто НЕ опитується на будь-якому рівні стеку.
Аллон Гуралнек

По-перше, більшість пакетів зберігання виконується з досить високою частотою, оскільки ви хочете уникати загальних інтервалів очікування, тому для TCP / IP кілька секунд не рідкість, і майже все, що не використовує tcp, може бути заблоковано брандмауерами. Тож коли мені потрібно кожні X секунд надсилати пакет даних, чому б не заповнити його деякими даними практично без витрат?
Falco

1
@Guralnek, навіть якщо у вас був зв'язок з інтервалом збереження в 5 хвилин, час очікування буде більшим, оскільки ви повинні додати фактичну затримку та втрачені пакети. І сервер зберігав би багато підключень протягом 5 хв після відключення клієнтів, тому в цілому це, швидше за все, коштуватиме більше ресурсів сервера, зберігаючи лише мінімальну пропускну здатність
Falco

1
+1 для тривалого опитування. Подивіться на Comet 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), щоб базовий стек протоколів міг розпізнати проблему доставки та шукати новий маршрут, але коли ситуація працює, модель запиту-звіту буде ефективнішою, ніж використання підтверджень на рівні посилань.


Проблему, про яку ви говорите з підштовхуванням повідомлень Y до X (другий абзац), можна вирішити, додавши до кожного повідомлення серійний номер. Якщо повідомлення буде втрачено, X дізнається, що не отримав цю послідовність. У цей момент він може вжити інших заходів для синхронізації з Y. DNS-майстром -> реплікація підлеглого працює таким чином.
korylprince

@korylprince: Будь-яка сторона може дізнатися про пропущене повідомлення, якщо інша сторона має привід надіслати щось (і робить це успішно) або якщо у нього є підстави очікувати чогось з іншої сторони і ніколи його не отримувати. Якщо одна сторона надсилає оновлення статусу і не потребує підтвердження або відмовляється після повторного повторного повторного повторного перегляду, а інша сторона не очікує запланованих передач, інша сторона не дізнається, що з'єднання зникло.
supercat

2
@korylprince - Проблема полягає в тому, що без періодичних повідомлень X може виявити пропущене повідомлення на день пізніше або на рік пізніше або на 10 років. Для виявлення відсутнього пакету в розумний час вам потрібно якось опитатись. Ви можете "витягнути" опитування або ви можете "підштовхнути" опитування. Перший називається "опитуванням", другий називається "серцебиттям"
slebetman

Обидва дуже вірні. Все залежить від ситуації.
korilprince

@slebetman: Без періодичних повідомлень, якщо Y перезавантажиться, може не існувати механізму, за допомогою якого X коли-небудь виявить це.
supercat

1

Питання полягає в тому, щоб збалансувати кількість зайвих опитувань та кількість непотрібних поштовхів.

Якщо ви опитуєте:

  • Ви отримаєте відповідь саме цього моменту. Добре, якщо ви запитуєте лише зрідка або вам потрібен набір даних саме цього моменту.
  • Ви можете отримати відповідь "без вмісту", що призведе до безглуздого навантаження на лінію.
  • Ви ставите навантаження на лінію лише тоді, коли опитуєте, але завжди, коли опитуєте.

Якщо натиснути:

  • Ви отримуєте відповідь право, коли вона доступна, що дозволяє негайно обробити на стороні клієнта.
  • Ви можете доставити дані клієнтам, які не цікавляться цими даними, що спричинить безглуздо навантаження на лінію.
  • Ви ставите навантаження на лінію щоразу, коли з’являються нові дані, але лише тоді, коли є нові дані.

Існує кілька рішень щодо того, як поводитися з різними сценаріями та їх недоліками, наприклад, наприклад, мінімальний час між опитуваннями, проксі-сервери, які відповідають лише опитуванням, щоб зняти навантаження з основної системи, або - для підштовхувань - регламент про реєстрацію та уточнення шукані дані з подальшим видаленням реєстрації під час виходу. Хто вам найбільше підходить, загалом ви нічого не можете сказати, це залежить від системи.

У вашому прикладі опитування - це не найефективніше рішення, а саме практичне. Написати систему опитування в JavaScript дуже просто, а також реалізувати її на стороні доставки. Сервер, створений для доставки графічних даних, повинен мати можливість обробляти додаткові запити, а якщо ні, то їх можна лінійно масштабувати, оскільки дані переважно статичні і тому їх легко кешувати.

Метод натискання, що реалізує вхід, опис потрібних даних і, нарешті, вихід із системи, був би найбільш ефективним, але, ймовірно, занадто складним для середнього "скрипта-кидді", і йому потрібно вирішити питання: що робити, якщо користувач просто закривається веб-переглядач, а вихід не може бути здійснений?

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


1

Чомусь у ці дні всі молодші веб-розробники, здається, забули уроки минулого, і чому деякі речі розвивалися так, як вони робили.

  1. Пропускна здатність була проблемою
  2. Зв'язок може бути переривчастим.
  3. Браузери не мали стільки обчислювальної потужності
  4. Існували й інші методи доступу до вмісту. Веб - це не w3.

Зважаючи на ці обмеження, у вас може не бути постійного двостороннього спілкування. І якщо ви подивилися на модель OSI, то виявите, що більшість міркувань мають на меті відключити стійкість базового з'єднання.

Зважаючи на це, метод опитування для отримання інформації - це чудовий спосіб зменшити пропускну здатність та обчислення на стороні клієнта. Зростання поштовху є здебільшого просто клієнтом, який здійснює постійне опитування або веб-розетки. Особисто, якби я був усім іншим там, я оцінив би регулярність опитування як засіб аналізу трафіку, де позачерговий запит GET / POST би сигналізував про людину, яка перебуває в якійсь ситуації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.