Что такое неблокирующий или асинхронный ввод / вывод в 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, обрабатывают запросы ввода-вывода или сети. Если ваш код читает из файла или базы данных, ваш код «блокирует» все, что происходит после его выполнения. В этот период ваша машина удерживает память и время обработки для потока, который ничего не делает .

Чтобы обслуживать другие запросы, пока поток остановлен, зависит от вашего программного обеспечения. То, что делает большинство серверных программ, - это создание большего количества потоков для удовлетворения дополнительных запросов. Это требует больше памяти и больше обработки.

Асинхронный неблокирующий пример

Асинхронные неблокирующие серверы, например, созданные в Node, используют только один поток для обслуживания всех запросов. Это означает, что экземпляр Node максимально использует один поток. Создатели разработали его исходя из того, что операции ввода-вывода и сетевых операций являются узким местом.

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

Джозеф
источник
5
Я не уверен, что понимаю ваш второй абзац в разделе Блокировка в PHP . Вы говорите, что «хотя PHP обычно блокирует ввод-вывод, это не так, потому что ОС автоматически создает потоки операций ввода-вывода»? Или вы говорите, что это не проблема в PHP, потому что PHP автоматически создает новый поток для каждого запроса, чтобы один заблокированный запрос не останавливал всю среду PHP? (Я предполагаю последнее ..)
dcow
6
Это последнее.
Иосиф
2
подождите, если это означает последнее, какие преимущества в том, что не блокирует ввод / вывод PHP (например, responsePHP или что-то еще) перед блокирующим. все еще путают
Суну Пинастика Фаджар
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

Пример кода

Уэйн Чиу
источник