Що було б краще для одночасних завдань на node.js? Волокна? Веб-працівники? або Нитки?


111

Я наткнувся на node.js десь тому і мені це дуже подобається. Але незабаром я з’ясував, що їй не вистачає можливості виконувати завдання, що вимагають процесора. Отже, я почав гуглінг і отримав такі відповіді, щоб вирішити проблему: Волокна, веб-працівники та нитки (потік-а-гого). Тепер, який з них використовувати, є плутанина, і одна з них, безумовно, повинна бути використана - для того, щоб зрозуміти, у чому мета сервера, який просто входить в IO і нічого іншого? Необхідні пропозиції!

ОНОВЛЕННЯ:

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

Отже, саме про це я і думав. Чи гарна ця ідея? Я трохи новачок у всьому цьому процесі та темах, тому не маю жодного досвіду в цьому. Будь ласка, поділіться своєю думкою.

Дякую. :)


Зверніть увагу: Робітники - це специфікація браузера, а не функція Javascript.
FredTheWebGuy

Ну, я це бачу. Моє запитання стосувалося node.js - коду сервера, а не про сторону клієнта!
Parth Thakkar

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

Відповіді:


331

Вузол має зовсім іншу парадигму, і як тільки він буде правильно зафіксований, легше побачити цей різний спосіб вирішення проблем. У додатку Node (1) вам ніколи не потрібно кілька потоків, оскільки у вас є інший спосіб робити те саме. Ви створюєте кілька процесів; але це дуже сильно відрізняється, ніж, наприклад, як працює Prefork mpm веб-сервера Apache.

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

- Гей, Хасане, я гадаю, ти або новачок, або дуже стара школа з часів мого Діда !!! Чому б вам не створити деякі теми і зробити це набагато швидше?

- О, у нас є лише одне ядро ​​процесора.

-- І що? Створіть людину нитки, зробіть це швидше!

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

- Гаразд добре, я бачу, ти бідний. Давайте використовуємо мій комп'ютер, він має 32 ядра!

- Нічого собі, ти чудовий мій дорогий друг, дуже дякую. Я ціную це!

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

Для використання декількох ядер нам потрібно знайти спосіб розділити свою роботу на шматки, з якими ми можемо оброблятись паралельно. Якби не Вузол, ми використовували б для цього потоки; 32 нитки, по одній для кожного ядра процесора. Однак, оскільки у нас є Node, ми створимо 32 процеси у Node.

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

- Гей, Хасане, ти все ще працюєш однонитковим? Що з тобою, чоловіче? Я щойно надав тобі те, що ти хотів. У вас більше немає виправдань. Створіть теми, змусьте її працювати швидше.

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

- Чому б вам не створити теми?

- Вибачте, я не думаю, що це корисно. Ви можете взяти комп’ютер, якщо хочете?

- Ні гаразд, я крутий, я просто не розумію, чому ви не використовуєте теми?

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

- Гаразд, дайте мені знати, якщо вам потрібен інший комп’ютер. : с

Якщо я створять 33 процеси, а не 32, планувальник операційної системи буде призупиняти потік, запускати інший, робити паузу після деяких циклів, запускати інший ще раз ... Це зайве накладні витрати. Я не хочу цього. Насправді в системі з 32 ядрами я навіть не хотів би створити рівно 32 процеси, 31 може бути приємніше . Тому що не тільки мій додаток буде працювати в цій системі. Залишити трохи місця для інших речей може бути добре, особливо якщо у нас 32 кімнати.

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

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

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

-- Так? Вузол для цього не годиться?

- Вузол ідеально підходить для цього, навіть якщо нитки можуть бути хорошими. Що стосується створення потоку / процесу накладних витрат; на речі, які ви багато повторюєте, кожна мілісекунда рахується. Однак я створюю лише 32 процеси, і це займе небагато часу. Це станеться лише один раз. Це не матиме ніякого значення.

- Коли тоді я хочу створити тисячі ниток?

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

- Хоч вузол інший? Правильно?

- Так, саме. Тут справді світить Вузол. Як і потік набагато легший, ніж процес, виклик функції набагато легший, ніж потік. Вузол викликає функції замість створення потоків. У прикладі веб-сервера кожен вхідний запит викликає виклик функції.

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

- Ви абсолютно праві, як функціонують функції, одна за одною, ніколи дві паралельно. Я маю на увазі, що в одному процесі одночасно працює лише одна область коду. Планувальник ОС не приходить і призупиняє цю функцію та переходить на іншу, якщо тільки вона не призупиняє процес, щоб приділити час іншому процесу, а не іншому потоку в нашому процесі. (2)

- Тоді як процес може обробляти 2 запити одночасно?

- Процес може обробляти десятки тисяч запитів одночасно, якщо наша система має достатньо ресурсів (оперативна пам'ять, мережа тощо). КІЛЬКА РОЗВИТКУ цих функцій.

- Хм, чи варто мені зараз хвилюватись?

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

- Це звучить занадто складно?

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

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

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

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

Синхронний шлях:

Open File
Repeat This:    
    Read Some
    Do the work

Асинхронний шлях:

Open File and Do this when it is ready: // Our function returns
    Repeat this:
        Read Some and when it is ready: // Returns again
            Do some work

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

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


(1) Якщо ви не створюєте бібліотеки іншими мовами, такими як C / C ++, тоді ви все одно не створюєте теми для поділу завдань. Для такої роботи у вас є дві нитки, одна з яких буде продовжувати спілкування з Node, а інша виконувати справжню роботу.

(2) Насправді кожен процес у вузлі має декілька потоків з тих же причин, про які я згадував у першій виносці. Однак це зовсім не так, як 1000 ниток роблять подібні роботи. Ці додаткові потоки призначені для таких речей, як прийняття подій вводу-виводу та обробка міжпроцесорних повідомлень.

ОНОВЛЕННЯ (як відповідь на гарне запитання в коментарях)

@ Марк, дякую за конструктивну критику. У парадигмі Node у вас ніколи не повинно бути функцій, які займають занадто багато часу, якщо всі інші виклики в черзі не розроблені для запуску один за одним. У випадку обчислювально дорогих завдань, якщо ми дивимось картину в повному обсязі, ми бачимо, що це не питання "Чи слід використовувати нитки чи процеси?" але питання "Як можна добре розподілити ці завдання на підзадачі, щоб ми могли їх виконувати паралельно, використовуючи кілька ядер процесора в системі?" Скажімо, ми обробимо 400 відеофайлів у системі з 8 ядрами. Якщо ми хочемо обробляти один файл за один раз, тоді нам потрібна система, яка буде обробляти різні частини одного і того ж файлу, і, можливо, багатопотокова однопроцесова система буде легше побудувати та ще ефективніше. Ми все ще можемо використовувати для цього Node, запускаючи кілька процесів і передаючи повідомлення між ними, коли необхідний обмін державою / спілкування. Як я вже говорив раніше, багатопроцесорний підхід з Node єа також багатопотоковий підхід у подібних завданнях; але не більше того. Знову ж таки, як я вже говорив раніше, ситуація, що Node світиться, полягає в тому, що у нас ці завдання надходять як вхід до системи з декількох джерел, оскільки збереження багатьох з'єднань одночасно набагато легше у Node порівняно з потоком на з'єднання або процесом на з'єднання система.

Що стосується setTimeout(...,0)дзвінків; іноді може бути потрібна перерва під час трудомісткого завдання, щоб дозволити дзвінки в черзі мати свою частку обробки. Поділ завдань різними способами може врятувати вас від цього; але все-таки це насправді не хак, це лише спосіб роботи черг на події. Крім того, використовувати process.nextTickдля цієї мети набагато краще, оскільки коли ви використовуєте setTimeout, обчислення та перевірку пройденого часу знадобиться, тоді process.nextTickяк ми просто хочемо: "Ей, завдання, поверніться до кінця черги, ви використали свою частку! "


9
Дивовижний! Чорт дивовижний! Мені сподобалось, як ти відповів на це запитання! :)
Parth Thakkar

48
Звичайно :) Я не можу повірити, що там є надзвичайно злі люди, які голосують за цю статтю відповіді! Запитувач називає це "Чорт дивно!" і автор книги пропонує мені писати на своєму веб-сайті, побачивши це; але деякі генії там знижують голоси. Чому б ти не поділишся своєю яскравою інтелектуальною якістю і не прокоментуєш її замість того, щоб підступно і підступно голосувати, так? Чому щось приємне вас так турбує? Чому ви хочете не допустити, щоб щось корисне охопило інших людей, які дійсно можуть отримати від цього користь?
hasanyasin

9
Це не зовсім справедлива відповідь. Що з обчислювально дорогими завданнями, де ми не можемо "швидко закінчити" функціональний дзвінок? Я вважаю, що деякі люди використовують setTimeout(...,0)для цього деякі хаки, але використовувати окрему нитку в цьому сценарії, безумовно, було б краще?
1313

3
@hasanyasin Це найкраще пояснення щодо вузла, який я знайшов поки що! :)
Венемо

7
@ Марк Загалом, якщо це обчислювально дорого, є варіанти / модулі для працівників протекторів / процесів ... Взагалі для таких типів речей я використовую Чергу повідомлень і мають робочі процеси, які обробляють завдання на час із черги та відпрацюйте це завдання. Це також дозволяє масштабувати декілька серверів. У рамках цих ліній Substack має безліч модулів, спрямованих на забезпечення та масштабування, яке ви можете переглянути.
Tracker1

34

(Оновлення 2016: Веб-працівники переходять у io.js - роздріб Node.js Node.js v7 - див. Нижче).

(Оновлення 2017 року: веб-працівники не збираються в Node.js v7 чи v8 - див. Нижче).

(Update 2018: веб - працівники будуть йти в Node.js Node v10.5.0 - см . Нижче)

Деякі роз’яснення

Прочитавши відповіді вище, я хотів би зазначити, що у веб-працівників немає нічого, що суперечить філософії JavaScript взагалі та Node зокрема щодо одночасності. (Якби це було, це не було б обговорено навіть WHATWG, а тим більше реалізовано в браузерах).

Ви можете думати про веб-працівника як про легку мікропослугу, до якої можна отримати асинхронний доступ. Держава не поділяється. Жодних проблем із блокуванням не існує. Блокування немає. Синхронізація не потрібна. Як і коли ви використовуєте послугу RESTful у своїй програмі Node, ви не переживаєте, що вона зараз "багатопоточна", тому що служба RESTful не в тій же нитці, що і ваш власний цикл подій. Це просто окремий сервіс, до якого ви отримуєте доступ асинхронно, і саме це має значення.

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

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

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

Однопоточний цикл подій ідеально підходить для операцій, пов'язаних з входом / виводом. Це не так добре для операцій, пов'язаних з процесором, особливо тривалих. Для цього нам потрібно породжувати більше процесів або використовувати нитки. Керувати дочірніми процесами та міжпроцесовим зв’язком портативним способом може бути досить складно, і це часто сприймається як надмірна робота для простих завдань, тоді як використання потоків означає вирішення блокувань та проблем синхронізації, які дуже важко зробити правильно.

Найчастіше рекомендується розділити тривалі операції, пов'язані з процесором, на більш дрібні завдання (на зразок прикладу в розділі "Оригінальна відповідь" моєї відповіді на прискорити setInterval ), але це не завжди практично і не використовує більше ніж одне ядро ​​процесора.

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

Вузлові модулі

Є кілька модулів, які повинні додати веб-працівників у вузол:

Я не використовував жодного з них, але у мене є два швидких спостереження, які можуть бути актуальними: станом на березень 2015 року, node-webworker востаннє оновлювався 4 роки тому, а node-webworker-niti востаннє оновлено місяць тому. Також я бачу на прикладі використання node-webworker-niti, що ви можете використовувати функцію замість імені файлу як аргумент конструктору Worker, який, здається, може викликати тонкі проблеми, якщо він буде реалізований за допомогою потоків, що розділяють пам'ять (якщо тільки функції використовуються лише для свого методу .toString (), інакше вони компілюються в іншому середовищі, і в цьому випадку це може бути добре - мені доведеться глибше заглянути до цього, просто поділившись своїми спостереженнями тут).

Якщо є який-небудь інший відповідний проект, який реалізує API веб-працівників у Node, залиште коментар.

Оновлення 1

Я не знаю , що ще під час написання , але між іншим один день , перш ніж я писав цю відповідь Web Workers були додані в io.js .

( io.js - роздріб Node.js - див. Чому io.js вирішив розвідати інтерв'ю InfoWorld з Mikeal Rogers для Node.js для отримання додаткової інформації.)

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

Оновлення 2

У оновленнях 1 та моєму твіті я мав на увазі запит на виклик io.js № 1159, який зараз переспрямовує на Node PR № 1159, який був закритий 8 липня та замінений на Node PR # 2133 - який досі відкритий. Існує певна дискусія, яка ведеться під тими запитами на виклики, які можуть надати ще деяку інформацію про стан веб-працівників у io.js / Node.js.

Оновлення 3

Остання інформація - дякую NiCk Newman за те, що він розмістив її в коментарях: Є працівники: перше виконання програми Петка Антонов від 6 вересня 2015 року, які можна завантажити та випробувати в цьому дереві . Дивіться коментарі NiCk Newman для детальної інформації.

Оновлення 4

Станом на травень 2016 року останні коментарі щодо ще відкритого PR № 2133 - робітники: початкова реалізація була 3 місяці. 30 травня Матей Морейра попросив мене опублікувати оновлення цієї відповіді в коментарях нижче, і він попросив поточний статус цієї функції в коментарях PR.

Перші відповіді в PR-дискусії були скептичними, але пізніше Бен Нордхуїс написав, що " З'єднання цього в тій чи іншій формі є в моєму списку todo для v7".

Усі інші коментарі здаються другими, і з липня 2016 року здається, що веб-робітники повинні бути доступні в наступній версії Node , версії 7.0, яка планується випустити на жовтень 2016 року (не обов'язково у формі цього точного PR).

Дякуємо Матей Морейрі за те, що він це вказав у коментарях та пожвавив дискусію на GitHub.

Оновлення 5

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

Оновлення 6

Станом на січень 2017 року навряд чи веб-працівники об'єднаються в Node.js.

Запит на витяг № 2133 працівників: початкова реалізація Петкою Антоновим з 8 липня 2015 року була остаточно закрита Бен Нордхісом 11 грудня 2016 року, який прокоментував, що "підтримка багатопотокової передачі додає занадто багато нових режимів відмови для недостатньої користі" та "ми також може досягти цього, використовуючи більш традиційні засоби, такі як спільна пам'ять та більш ефективна серіалізація ".

Для отримання додаткової інформації дивіться коментарі до PR 2133 на GitHub.

Ще раз дякую Матей Морейрі за те, що він це вказав у коментарях.

Оновлення 6

Я радий повідомити, що кілька днів тому в червні 2018 року веб-працівники з’явились у Node v10.5.0 як експериментальна функція, активована --experimental-workerпрапором.

Для отримання додаткової інформації дивіться:

🎉🎉🎉 Нарешті! Я можу зробити 7-е оновлення до своєї 3-річної відповіді на стек-переповнення, де я стверджую, що нарізання а-ля веб-працівників не проти філософії Node, лише цього разу кажу, що ми нарешті це отримали! 😜👍


1
@NiCkNewman Дякую Я бачу, що оригінальний запит на виклик в io.js закритий і замінений на інший - дещо обговорення в запиті про запити коментарів щодо GitHub, можливо, ви зможете знайти там якусь інформацію. Дивіться: Оновлення 2 у моїй відповіді.
rsp

1
Так, схоже, вони щойно виправили останню проблему з libuv. Цікаво, коли я можу взятись за модуль. Не можу дочекатися! Дякую за зберігання нас оновленими ~ Edit: Просто отримав инициализирован: github.com/petkaantonov/io.js/commit / ... Там ми йдемо, він йде!
NiCk Newman

1
Так, це в прямому ефірі. (Офіційно ще не реалізовано), але ви можете завантажити джерело тут: github.com/petkaantonov/io.js/tree/… і скласти, якщо ви хочете перевірити його! Я роблю це зараз ~
NiCk Newman

1
@NiCkNewman Дякую за нову інформацію - я додав її до відповіді.
rsp

1
Чи можете ви, будь ласка, оновити нас щодо стану реалізації Node.js workers? Останні коментарі в PR # 2133 - з лютого; розробники, мабуть, зіткнулися з проблемою, і немає коментарів, які б свідчили про її вирішення.
Матей Морейра

8

Я родом зі старої школи думки, де для швидкого використання програмного забезпечення ми використовували багатопотокові. Останні 3 роки я використовую Node.js і великий прихильник цього. Як Хасанясін детально пояснив, як працює вузол і поняття асинхронної функціональності. Але дозвольте додати сюди мало речей.

Ще в старі часи з поодинокими ядрами та меншими тактовими частотами ми намагалися різними способами зробити так, щоб програмне забезпечення працювало швидко та паралельно. у дні DOS, які ми використовуємо для запуску однієї програми за один раз. Тоді як у Windows ми почали разом запускати кілька програм (процесів). Такі поняття, як превентивні та непередбачені (або кооперативні), де тестуються. тепер ми знаємо, що преференція стала відповіддю для кращого багатопроцесорного завдання на одноядерних комп'ютерах. Поряд з'явилися концепції процесів / завдань та переключення контексту. Чим поняття нитки ще більше зменшує тягар перемикання контексту процесу. Нитка, де створена як легка альтернатива нересту нових процесів.

Так вам подобається або не сигнальна нитка, або не багатоядерна або одноядерна, ваші процеси будуть виграні і час відрізаний ОС.

Nodejs - це єдиний процес і забезпечує механізм асинхронізації. Тут завдання відправляються в лежачу ОС для виконання завдань, поки ми чекаємо в циклі подій, щоб завдання закінчилося. Як тільки ми отримуємо зелений сигнал від ОС, ми виконуємо все, що нам потрібно робити. Тепер певним чином це співпраця / непередбачувана багатозадачність, тому ми ніколи не повинні блокувати цикл подій протягом дуже тривалого періоду часу. Інші розумні, ми дуже швидко погіршимо наш додаток.
Тож якщо коли-небудь виникає завдання, яке блокує характер або вимагає багато часу, нам доведеться розкласти його на превентивний світ ОС та потоків. є хороші приклади цього в документації libuv . Крім того, якщо ви читаєте документацію далі ви виявите , що FileI / O обробляється в потоках в node.js .

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

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

Я знаю, що відповідь hasanyasin є прийнятою, але для мене теми будуть існувати незалежно від того, що ви говорите або як ви ховаєте їх за скриптами, по-друге, ніхто просто не розбиває речі на потоки лише для швидкості, в основному це робиться для блокування завдань. І нитки знаходяться в задній кістці Node.js, тому перед повним забиванням багатопотокової передачі правильно. Також потоки відрізняються від процесів, і обмеження наявності процесів у вузлах на ядро ​​точно не стосується кількості потоків, потоки - це як підзавдання процесу. насправді нитки не виграли; не з’являться у вашому менеджері завдань Windows або верхній команді linux. знову вони набирають меншої ваги, а потім переробляють


Асинхронний код - це не величезна інновація (насправді ми мали це десятиліттями), а багатопоточність - це не якась застаріла технологія, яку потрібно замінити. Вони різні інструменти з різними компромісами, і насправді їх можна навіть добре поєднувати. Кожен раз, коли ви запускаєте node-cluster, ви насправді запускаєте кілька "потоків" (процесів у цьому випадку, але те ж саме можна досягти з потоками та бути ще більш легким). Або візьміть Erlang або Go, які можуть запускати тисячі зелених ниток ...
Hejazzman

Я думаю, що головне, що нам не вистачає, - це те, що процес в ОС завжди буде здійснюватися превентивно, щоб забезпечити справедливість. Також з декількома процесорами ви можете мати фактичне паралельне виконання коду, але навіть тоді ви матимете перевагу. Асинхронна робота також виконується ОС в деяких процесах.
limplash

4

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


3
тільки для вашої інформації веб-працівники були (частково) адаптовані на node.js. І доступні як node-workersпакет. Подивіться на це: github.com/cramforce/node-worker
Parth Thakkar

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

@ParthThakkar: Цей проект не торкався протягом 3 років (2, коли ви опублікували), і не пройшов його через 0.0.1.
1313

@Mark: Причина мого невігластва в тому, що я ще не є професійним програмістом. Чорт, я навіть не в університеті. Я все ще є середньою школою, яка постійно читає про програмування - окрім того, що керує роботою школи. Отже, мені віддалено неможливо мати знання про всі подібні проблеми. Я щойно опублікував те, що знав ...
Parth Thakkar

@Mark: Хоча вам було приємно зазначити це про історію проекту. Такі речі подбатимуть у моїх майбутніх відповідях !! :)
Parth Thakkar

3

worker_threadsбуло реалізовано та відправлено за прапором у node@10.5.0. Це все-таки початкова реалізація, і потрібно докласти більше зусиль, щоб зробити їх більш ефективним у майбутніх випусках. Варто спробувати найновіше node.


2

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

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

Для роботи з асинхронним програмуванням у вашому коді (як, уникнення вкладених пірамід зворотного виклику) компонент [Майбутнє] в бібліотеці Fibers - гідний вибір. Я б також запропонував вам перевірити Asyncblock, який базується на волокнах . Волокна приємні, тому що вони дозволяють приховати зворотний виклик, дублюючи стек, а потім перескакуючи між стеками на одному потоці за необхідності. Економить вам клопоту справжніх ниток, надаючи при цьому переваги. Мінус полягає в тому, що сліди стека можуть стати трохи дивними при використанні Fibers, але вони не надто погані.

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


Що ж, я спочатку думав про вашу пропозицію - про кластери. Але проблема в цьому полягає в їхніх накладних витратах - новий екземпляр v8 повинен ініціалізуватися кожного разу, коли новий процес розщедриться (~ 30 мс, 10 МБ). Отже, ви не можете створити їх багато. Це взято безпосередньо з документів вузла: Ці дочірні Вузли (про дочірніх процесів) все ще нові екземпляри V8. Припускайте щонайменше 30 мс запуску та 10 Мб пам'яті для кожного нового Вузла. Тобто ви не можете створити їх багато тисяч.
Parth Thakkar

1
Це саме ідея кластеру. Ви запускаєте одного працівника на ядро ​​процесора. Більше, швидше за все, непотрібне. Навіть інтенсивні завдання процесора відмінно спрацюють з асинхронним стилем. Однак якщо вам справді потрібні повнорозмірні потоки, ви, ймовірно, повинні повністю перейти на інший сервер.
genericdave

1

Можливо, ще трохи інформації про те, які завдання ви виконуєте, допоможе. Чому вам потрібно (як ви згадували у своєму коментарі до відповіді genericdave) потрібно створити їх багато тисяч? Звичайний спосіб робити подібні речі в Node - це запустити робочий процес (використовуючи вилку або якийсь інший метод), який завжди працює і може бути переданий для використання повідомлень. Іншими словами, не запускайте нового працівника кожен раз, коли вам потрібно виконати будь-яке завдання, яке ви робите, а просто надішліть повідомлення вже працюючому працівнику і отримайте відповідь, коли це буде виконано. Чесно кажучи, я не можу побачити, що запуск багатьох тисяч фактичних потоків також був би дуже ефективним, ви все ще обмежені вашими процесорами.

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

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