Node.js中的非阻塞或异步I/O是什么?

时间:2022-10-19 18:28:24

In the context of Server Side Javascript engines, what is non-blocking I/O or asynchronous I/O? I see this being mentioned as an advantage over Java server side implementations.

在服务器端Javascript引擎的上下文中,什么是非阻塞I/O或异步I/O?我认为这是优于Java服务器端实现的优点。

2 个解决方案

#1


239  

Synchronous vs Asynchronous

Synchronous execution usually refers to code executing in sequence. Asynchronous execution refers to execution that doesn't run in the sequence it appears in the code. In the following example, the synchronous operation causes the alerts to fire in sequence. In the async operation, while alert(2) appears to execute second, it doesn't.

同步执行通常是指按顺序执行的代码。异步执行是指在代码中出现的序列中不运行的执行。在下面的示例中,同步操作会按顺序触发警报。在async操作中,虽然alert(2)似乎执行了第二个,但它没有。

Synchronous: 1,2,3

同步:1、2、3

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

Asynchronous: 1,3,2

异步:1、3、2

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

Blocking vs Non-blocking

Blocking refers to operations that block further execution until that operation finishes. Non-blocking refers to code that doesn't block execution. In the given example, localStorage is a blocking operation as it stalls execution to read. On the other hand, fetch is a non-blocking operation as it does not stall alert(3) from execution.

阻塞是指在操作结束之前阻止进一步执行的操作。非阻塞是指不阻塞执行的代码。在给定的例子中,localStorage是一个阻塞的操作,因为它会让执行过程被读取。另一方面,fetch是一个非阻塞操作,因为它不会停止警告(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);

Advantages

One advantage of non-blocking, asynchronous operations is that you can maximize the usage of a single CPU as well as memory.

非阻塞、异步操作的一个优点是,您可以最大限度地使用单个CPU和内存。

Synchronous, blocking example

An example of synchronous, blocking operations is how some web servers like ones in Java or PHP handle IO or network requests. If your code reads from a file or the database, your code "blocks" everything after it from executing. In that period, your machine is holding onto memory and processing time for a thread that isn't doing anything.

同步、阻塞操作的一个例子是,Java或PHP中的一些web服务器如何处理IO或网络请求。如果您的代码从一个文件或数据库中读取,那么您的代码“阻塞”了执行之后的所有内容。在这段时间内,您的机器将占用内存和处理时间,而线程没有执行任何操作。

In order to cater other requests while that thread has stalled depends on your software. What most server software do is spawn more threads to cater the additional requests. This requires more memory consumed and more processing.

为了满足其他请求,而线程的停顿取决于您的软件。大多数服务器软件做的是产生更多的线程来满足额外的请求。这需要更多的内存消耗和更多的处理。

Asynchronous, non-blocking example

Asynchronous, non-blocking servers - like ones made in Node - only use one thread to service all requests. This means an instance of Node makes the most out of a single thread. The creators designed it with the premise that the I/O and network operations are the bottleneck.

异步的、非阻塞的服务器——就像在节点中做的一样——只使用一个线程来服务所有的请求。这意味着节点的实例最大限度地利用了单个线程。创建者设计它的前提是I/O和网络操作是瓶颈。

When requests arrive at the server, they are serviced one at a time. However, when the code serviced needs to query the DB for example, it sends the callback to a second queue and the main thread will continue running (it doesn't wait). Now when the DB operation completes and returns, the corresponding callback pulled out of the second queue and queued in a third queue where they are pending execution. When the engine gets a chance to execute something else (like when the execution stack is emptied), it picks up a callback from the third queue and executes it.

当请求到达服务器时,它们一次服务一个。但是,当代码serviced需要查询数据库时,它会将回调发送给第二个队列,主线程将继续运行(它不会等待)。现在,当DB操作完成并返回时,对应的回调从第二个队列中退出,并在等待执行的第三个队列中排队。当引擎有机会执行其他操作时(比如当执行堆栈清空时),它从第三个队列中获取一个回调并执行它。

#2


3  

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

Node.js中的非阻塞或异步I/O是什么?

#1


239  

Synchronous vs Asynchronous

Synchronous execution usually refers to code executing in sequence. Asynchronous execution refers to execution that doesn't run in the sequence it appears in the code. In the following example, the synchronous operation causes the alerts to fire in sequence. In the async operation, while alert(2) appears to execute second, it doesn't.

同步执行通常是指按顺序执行的代码。异步执行是指在代码中出现的序列中不运行的执行。在下面的示例中,同步操作会按顺序触发警报。在async操作中,虽然alert(2)似乎执行了第二个,但它没有。

Synchronous: 1,2,3

同步:1、2、3

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

Asynchronous: 1,3,2

异步:1、3、2

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

Blocking vs Non-blocking

Blocking refers to operations that block further execution until that operation finishes. Non-blocking refers to code that doesn't block execution. In the given example, localStorage is a blocking operation as it stalls execution to read. On the other hand, fetch is a non-blocking operation as it does not stall alert(3) from execution.

阻塞是指在操作结束之前阻止进一步执行的操作。非阻塞是指不阻塞执行的代码。在给定的例子中,localStorage是一个阻塞的操作,因为它会让执行过程被读取。另一方面,fetch是一个非阻塞操作,因为它不会停止警告(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);

Advantages

One advantage of non-blocking, asynchronous operations is that you can maximize the usage of a single CPU as well as memory.

非阻塞、异步操作的一个优点是,您可以最大限度地使用单个CPU和内存。

Synchronous, blocking example

An example of synchronous, blocking operations is how some web servers like ones in Java or PHP handle IO or network requests. If your code reads from a file or the database, your code "blocks" everything after it from executing. In that period, your machine is holding onto memory and processing time for a thread that isn't doing anything.

同步、阻塞操作的一个例子是,Java或PHP中的一些web服务器如何处理IO或网络请求。如果您的代码从一个文件或数据库中读取,那么您的代码“阻塞”了执行之后的所有内容。在这段时间内,您的机器将占用内存和处理时间,而线程没有执行任何操作。

In order to cater other requests while that thread has stalled depends on your software. What most server software do is spawn more threads to cater the additional requests. This requires more memory consumed and more processing.

为了满足其他请求,而线程的停顿取决于您的软件。大多数服务器软件做的是产生更多的线程来满足额外的请求。这需要更多的内存消耗和更多的处理。

Asynchronous, non-blocking example

Asynchronous, non-blocking servers - like ones made in Node - only use one thread to service all requests. This means an instance of Node makes the most out of a single thread. The creators designed it with the premise that the I/O and network operations are the bottleneck.

异步的、非阻塞的服务器——就像在节点中做的一样——只使用一个线程来服务所有的请求。这意味着节点的实例最大限度地利用了单个线程。创建者设计它的前提是I/O和网络操作是瓶颈。

When requests arrive at the server, they are serviced one at a time. However, when the code serviced needs to query the DB for example, it sends the callback to a second queue and the main thread will continue running (it doesn't wait). Now when the DB operation completes and returns, the corresponding callback pulled out of the second queue and queued in a third queue where they are pending execution. When the engine gets a chance to execute something else (like when the execution stack is emptied), it picks up a callback from the third queue and executes it.

当请求到达服务器时,它们一次服务一个。但是,当代码serviced需要查询数据库时,它会将回调发送给第二个队列,主线程将继续运行(它不会等待)。现在,当DB操作完成并返回时,对应的回调从第二个队列中退出,并在等待执行的第三个队列中排队。当引擎有机会执行其他操作时(比如当执行堆栈清空时),它从第三个队列中获取一个回调并执行它。

#2


3  

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

Node.js中的非阻塞或异步I/O是什么?