В яких умовах (якщо такі є), є хорошою практикою запитувати два сервери та споживати лише найшвидший відповідь?


12

Я запитав, що зараз є питанням видаленої спільноти щодо SO про те, чому хтось використовує JavaScript Promise.race, і користувач з високою репутацією прокоментував це:

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

Я гуглився про надмірність і про цей випадок використання в цілому, але я нічого не міг знайти, і, з моєї POV, ніколи не годиться просто додавати робоче навантаження на сервер / службу, якщо ви не збираєтесь використовувати відповідь.


Приклад іграшки: замість того, щоб завжди використовувати quicksort, ви копіюєте дані, відправляєте їх у кікспорт, і злиття, і групу, і т. Д. Вам не потрібно перевіряти дані, щоб побачити, чи це паталогічний випадок для будь-якого з них, тому що він не буде pathalogical випадок для всіх з них
Caleth

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

Другий "запит сервера" може бути підробкою. Він може просто захотіти протягом 5 секунд, а потім повернути відповідь заповнювача. Це дає вам тайм-аут на реальний запит.
користувач253751

Замовити ліфт, а потім замовити Uber. Візьміть, хто з них стане першим.
користувач2023861

@ user2023861 за цією аналогією, поки один водій безглуздо їхав до вашого місця, він / вона міг взяти на себе ще один запит
Аделін

Відповіді:


11

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

Я розбиваю свою відповідь на чотири частини:

  • Управління ризиками
  • Стратегії
  • Витрати
  • Інтуїція

Управління ризиками

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

Але не за межами ваших знань. Ви повинні знати:

  • Як часто це відбувається.
  • Який вплив це має.

Наприклад, якщо невдача та повторна спроба трапляються лише приблизно в 2% часу, її, ймовірно, не варто вирішувати. Якщо це трапляється приблизно 80% часу, то ... залежить ...

Скільки часу клієнту потрібно чекати? І як це перетворюється на витрати ... Розумієте, у вас є невелика затримка у звичайному застосуванні, це, мабуть, не велика справа. Якщо це важливо, і у вас є програма в режимі реального часу або онлайн-відео-гра, це відверне користувачів, і ви, ймовірно, краще інвестувати в більші або кращі сервери. В іншому випадку ви, ймовірно, можете поставити повідомлення "завантаження" або "очікування сервера". Якщо затримка дійсно не велика (порядку десятків секунд), то вона може бути занадто великою навіть для звичайного застосування.


Стратегії

Як я вже говорив вище, існує кілька способів вирішити цю проблему. Я припускаю, що у вас вже є цикл try-fail-retry. Отже, давайте подивимось ...

  • Помістіть повідомлення про завантаження. Це дешево, сприяє утриманню користувачів.
  • Паралельно запитуйте. Може бути швидше, все ще може провалитися. Буде потрібний резервний сервер (може бути дорогим), буде витрачатися час сервера та мережевий трафік.
  • Паралельно запитуйте, щоб стабілізувати швидший сервер і використовувати його звідти далі. Може бути швидше, все ще може провалитися. Буде потрібно надлишковий сервер (може бути дорогим), не буде витрачати стільки часу на сервер і мережевий трафік.

Тепер, зауважте, я кажу, що це все ще може бути невдалим. Якщо припустити, що запит на сервер має 80% шансу виходу з ладу, то паралельний запит до двох серверів має 64% шансу виходу з ладу. Таким чином, вам, можливо, доведеться повторити спробу.

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

Що нагадує мені, якщо ви можете зрозуміти, чому запит не працює, зробіть це. Це допоможе вам краще керувати ситуацією, навіть якщо ви не можете запобігти невдачам. Наприклад, чи потрібна вам більша швидкість передачі на стороні сервера?

Трошки більше:

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

І хто сказав, що ти повинен зробити лише одне з них? Ви можете розмістити повідомлення про завантаження, запитувати декілька серверів, які розповсюджуються по вручанню, щоб вибрати швидше і використовувати це лише звідти, при спробі повторити спробу в циклі, і кожен з цих серверів буде кластером машин з балансуванням навантаження . Чому ні? Ну, коштує ...


Витрати

Існує чотири витрати:

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

Ви повинні їх збалансувати.

Наприклад, скажімо, що ви заробляєте близько долара на задоволеного користувача. Що у вас є 3000 користувачів на день. Що прохання провалюються близько 50% часу. І що 2% користувачів залишають без оплати, коли запит не відповідає. Це означає, що ви втрачаєте (3000 * 50% * 2%) 30 доларів на день. Тепер скажемо, що розробка нової функції обійдеться вам у 100 доларів, а розгортання серверів обійдеться вам у 800 доларів - а ігнорування витрат на виконання - це означає, що ви отримаєте віддачу від інвестицій ((100 + 800) / 30 ) 30 днів. Тепер ви можете перевірити свій бюджет і прийняти рішення.

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

Додатки:

  • Пам'ятайте, що я також ігнорую деталі. Наприклад, у вас може бути невелика вартість розгортання, але ви платите за час процесора, і вам потрібно це врахувати.
  • Деякі клієнти можуть вдячні, якщо ви не витрачаєте їх пакет даних на надмірні запити.
  • Удосконалення вашого продукту може допомогти надати природну рекламу.
  • Не забувайте про можливі витрати. Чи варто розробляти щось інше?

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


Інтуїція

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

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

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

Я б запропонував зробити це замість того, щоб витрачати мережевий трафік і час сервера на кожен запит, також пам’ятайте, що навіть при надмірному сервері може статися збій.


2
Я не думаю, що мені потрібно це говорити, але це чудова відповідь :) Я знав, що прийму це в перших 10 рядках, але я дав вам можливість все-таки провалитись і прочитати його до кінця. Ви цього не зробили
Аделін

9

Це прийнятно, якщо час клієнта є більш цінним, ніж час на сервері.

Якщо клієнту потрібно бути швидким і акуратним. Ви можете виправдати запит на кілька серверів. І приємно скасувати запит, якщо надійде відповідь дійсна.

І звичайно, завжди розумно проконсультуватися з власниками / менеджерами серверів.


Чому потрібно скасувати запит? Звичайно, це суб'єктивно.
JᴀʏMᴇᴇ

@ JᴀʏMᴇᴇ, це побудова в параної. Я колись працював із системою, яка не очистила свою чергу, і вона вийшла з ладу, коли черга була повна (Так, це було професійне програмне забезпечення).
Toon Krijthe

4

Ця методика може зменшити затримку. Час відповіді сервера не є детермінованим. За шкалою, ймовірно, щонайменше один сервер покаже поганий час відгуку. Тому все, що використовує цей сервер, також матиме поганий час відгуку. Подавши декілька серверів, це зменшує ризик спілкування з неякісно працюючим сервером.

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

Ось один папір , а інший . Я пам’ятаю, що читав у Google папері їхню реалізацію теж.


2

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

Скажімо, у вас довгий список завдань, деякі з яких можна виконувати паралельно, а деякі, які повинні виконуватись перед іншими. Ви можете розпочати всі завдання без залежностей, а потім дочекатися цього списку Promise.race(). Як тільки перше завдання буде виконано, ви можете розпочати будь-які завдання, які залежали від цього першого завдання, і Promise.race()знову ж таки з нового списку, поєднаного з незакінченими завданнями з початкового списку. Продовжуйте повторювати, поки всі завдання не будуть виконані.

Примітка. API Javascript ідеально не призначений для цього. Це майже мінімальний робочий мінімум, і вам доведеться додати зовсім небагато клею. Однак я можу сказати, що такі функції race()рідко використовуються для надмірності. Вони в першу чергу є для того, коли ви дійсно бажаєте результатів усіх обіцянок, але не хочете чекати, коли всі вони завершаться, перш ніж вживати наступних дій.


Проблема полягає в тому, що, принаймні, з Promise.race Javascript ви фактично запускаєте завдання щоразу, коли виконуєте метод гонки. Це не буде щодо незакінченого завдання, це буде новий набір завдань, не залежно від того, що було виконано раніше (якщо ви не реалізуєте цю логіку на рівні завдання). Оригінальний список забутий інакше, і залишається лише повернене значення першого завдання
Аделін

1
Обіцяння в Javascript запускаються охоче, коли new Promiseвикликається, а не перезапускаються, коли Promise.race()викликаються. Деякі втілення обіцянок ліниві, але охочі набагато частіше. Ви можете перевірити, створивши обіцянку на консолі, що входить до консолі. Ви побачите його журнали відразу. Тоді передайте цю обіцянку Promise.race(). Ви побачите, що він не ввійде знову.
Карл Білефельдт

Ах, це правда. Але afaik повернення вартості решти обіцянок, окрім першої, забуто, з promis.race
Аделін

Тому я сказав, що API не розроблений ідеально. Ви повинні десь зберігати оригінальний набір завдань у змінній.
Карл Білефельдт

1

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

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

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

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