Що таке неблокуючий або асинхронний введення / виведення в Node.js?


136

Що стосується двигунів JavaScript на стороні сервера, що таке блокування вводу / виводу або асинхронного вводу / виводу? Я вважаю, що це згадується як перевага перед реалізаціями на сервері Java.


3
Корисно подумати над тегами скриптів у середовищі браузера, щоб зрозуміти цю концепцію. Закас про це має чудову статтю - перших кількох розділів має бути достатньо, щоб пояснити концепцію блокування: nczonline.net/blog/2010/08/10/what-is-a-non-blocking-script
netpoetica

Відповіді:


317

Синхронний проти асинхронний

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

Синхронний: 1,2,3

alert(1);
alert(2);
alert(3);

Асинхронний: 1,3,2

alert(1);
setTimeout(() => alert(2), 0);
alert(3);

Блокування проти Неблокування

Блокування стосується операцій, які блокують подальше виконання, поки ця операція не закінчиться. Неблокування відноситься до коду, який не блокує виконання. У наведеному прикладі localStorageце операція блокування, оскільки вона зупиняє виконання для читання. З іншого боку, fetchце незаблокуюча операція, оскільки вона не затримується alert(3)від виконання.

// Blocking: 1,... 2
alert(1);
var value = localStorage.getItem('foo');
alert(2);

// Non-blocking: 1, 3,... 2
alert(1);
fetch('example.com').then(() => alert(2));
alert(3);

Переваги

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

Синхронний, блокуючий приклад

Прикладом синхронних, блокуючих операцій є те, як деякі веб-сервери, такі як Java або PHP, обробляють IO або мережеві запити. Якщо ваш код читається з файлу або бази даних, ваш код "блокує" все після його виконання. У цей період ваша машина затримує пам'ять і обробляє час для потоку, який нічого не робить .

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

Асинхронний, неблокуючий приклад

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

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


5
Я не впевнений, що я розумію ваш другий абзац у розділі Блокування в PHP . Ви говорите це: "Хоча PHP зазвичай блокується на IO, це не відбувається, тому що ОС автоматично передає потоки операцій вводу-виводу".? Або ви говорите, що це не проблема в PHP, оскільки PHP автоматично створює нову нитку для кожного запиту, щоб один заблокований запит не зупиняв усе середовище PHP? (Я здогадуюсь останнього ..)
dcow

6
Це останнє.
Йосип

2
зачекайте, якщо це означає останній, які переваги не блокує PHP вводу-виводу (наприклад, reactPHP або щось інше) над блокуючим. все ще плутати
Суну Пінастіка Фаджар

5
@CharlieParker Так. Операція асинхронізації працює паралельно вашому коду. Але зворотний виклик, який "повертається" до результатів операції асинхронізації, ставиться в чергу для виконання в основному коді, коли основний код не зайнятий.
Йосиф

2
@CharlieParker Ось публікація, яка детальніше розповідає про внутрішні механізми асинхронного механізму.
Йосиф

7
var startTime = new Date().getTime();
var getEndTime = () => {
    var tempEndTime = new Date().getTime();
    var second = (tempEndTime - startTime)/1000
    return `took ${second} sec...to finish\n`
}

console.log('1: start App', getEndTime())
setTimeout(()=>{
    console.log('2: setTimeout', getEndTime())
}, 1000)
console.log('3: End App', getEndTime())

// console -> Process Order:  1 -> 3 -> 2

Приклад коду

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