Загрузка…
Загрузка…
First, let's understand I/O. I/O stands for Input/Output. In the context of a server, this typically refers to operations that involve interacting with things outside of the CPU and memory. Common examples include:
Теперь давайте посмотрим на «блокировку» и «неблокировку»:
Blocking I/O (Traditional Model): Imagine you're a single waiter in a very busy restaurant.
Неблокирующий ввод-вывод (модель Node.js): Теперь представьте, что вы сверхэффективный официант (Node.js).
libuv
, библиотека C++) и продолжает выполнение остальной части кода JavaScript. Когда операция ввода-вывода завершается, функция «обратного вызова» помещается в очередь для последующего выполнения.
Пример кода (неблокирующий ввод-вывод):
Рассмотрим чтение файла. Если бы это было блокировкой, программа остановилась бы до тех пор, пока файл не будет полностью прочитан. В Node.js это неблокируется:
console.log("1. Program starts.");
// This is an I/O operation: reading a file.
// Node.js will *not* wait here. It delegates the task
// and moves on immediately. The function inside `readFile`
// will run *later* when the file is ready.
const fs = require('fs');
fs.readFile('my-file.txt', 'utf8', (err, data) => {
if (err) {
console.error("Error reading file:", err);
return;
}
console.log("3. File content loaded:", data.length, "bytes.");
});
console.log("2. Program continues (file might not be read yet).");
// Expected output order:
// 1. Program starts.
// 2. Program continues (file might not be read yet).
// 3. File content loaded: ... (This appears *after* 2, even though its call was before 2)Это показывает, что Node.js не останавливается и не ждет
fs.readFile
завершить; он продолжает выполнение следующей строки кода и обратного вызова для
readFile
выполняется позже.
Node.js выполняет код JavaScript в одном потоке. Это означает, что в любой момент времени у него есть только одна «линия выполнения». Итак, как же ему удается одновременно обрабатывать тысячи соединений с неблокирующим вводом-выводом? Ответ — Цикл событий.
Представьте себе Event Loop как неутомимого консьержа или центральную диспетчерскую систему:
Как это работает с неблокирующим вводом-выводом:
libuv
), который управляет пулом потоков для этих тяжелых задач ввода-вывода. 3. Единственный поток JavaScript теперь может свободно обрабатывать другие входящие запросы или выполнять другой синхронный код. 4. Когда ОС завершает операцию ввода-вывода,
libuv
уведомляется. 5.
libuv
затем помещает функцию обратного вызова (предоставленную вами для операции ввода-вывода) в очередь задач цикла событий. 6. Когда одиночный поток JavaScript становится бездействующим (т. е. завершает выполнение всего выполняющегося в данный момент синхронного кода), цикл событий извлекает этот обратный вызов из очереди и выполняет его.
Этот эффективный танец позволяет Node.js выглядеть многопоточным с точки зрения производительности, даже если ваш код JavaScript выполняется в одном потоке.
Операция привязана к вводу-выводу, когда время, необходимое для завершения, в первую очередь определяется тем, как долго она ожидает операций ввода-вывода (например, ответов сети, чтения с диска или запросов к базе данных).
Модель неблокирующего ввода-вывода и цикла событий значительно улучшает операции ввода-вывода в Node.js, потому что:
Ключевой вывод для интервью: что означает «неблокирующий ввод-вывод»?
