Багато блокуючих одноразових неблокуючих працівників VS


9

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

Багато блокуючих працівників хороші тим, що:

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

Одномісний неблокуючий працівник хороший тим, що:

  • Використовує менше пам'яті.
  • Менш уразливі для ледачих клієнтів (які підключаються до сервера та надсилають заголовки повільно або взагалі не надсилають).

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

Редагувати (додаткові дослідження): Деякий ресурс, який я знайшов в Інтернеті ( Тисячі ниток та блокування вводу-виводу - старий спосіб написання Java-серверів знову новий (і набагато краще) Пол Тима) натякає, що блокування підходу, як правило, краще, але Я досі не знаю, як боротися з підробленими зв’язками.

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

PSS Я розділив логіку на кілька частин, і ця лише обробляє приймаючі заголовки HTTP. Не обробляє їх.


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

Відповіді:


4

Срібної кулі немає

На практиці це залежить ...

tl; dr - просте рішення, використовуйте nginx ...

Блокування:

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

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

AFAIK, використання багатопроцесорного підходу на блокуванні HTTP-сервера, як правило, є кращим, оскільки безпечніше / простіше керувати / відновлювати пам'ять безпечним чином. Збір сміття стає проблемою, коли відновлення пам'яті настільки ж просто, як і зупинка процесу. Для тривалих процесів (тобто демон) ця характеристика особливо важлива.

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

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

Неблокуючий:

Неблокування буде чимось на зразок Node.js або nginx. Вони особливо відомі тим, що масштабують значно більшу кількість з'єднань на вузол під навантаженням, що інтенсивно застосовується. В основному, як тільки люди потрапили на верхню межу того, з якими серверами на основі потоків / процесів можуть працювати, вони почали вивчати альтернативні варіанти. Це інакше відома як проблема C10K (тобто можливість обробляти 10000 одночасних з'єднань).

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

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

Навіть на сервері, на якому є лише один вузол, в програмі дуже часто входити один сервер на ядро ​​процесора для максимальної пропускної здатності.

Обидва:

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

У вашому випадку:

Якщо ви просто перевіряєте заголовки, але насправді не обробляєте запити, те, що ви, по суті, описуєте, є зворотним проксі. У такому випадку я б точно підходив до асинхронного підходу.

Я б запропонував переглянути документацію для вбудованого зворотного проксі-сервера nginx .

Убік:

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

Виявив, що при перемиканні між клієнтами код для збереження та відновлення значень / стану був важким

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

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

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