【问题标题】:What is non-blocking or asynchronous I/O in Node.js?Node.js 中的非阻塞或异步 I/O 是什么?
【发布时间】:2012-05-21 03:57:42
【问题描述】:

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

【问题讨论】:

标签: node.js asynchronous nonblocking serverside-javascript


【解决方案1】:

同步与异步

同步执行通常是指代码按顺序执行。异步执行是指不按照它在代码中出现的顺序运行的执行。在以下示例中,同步操作会导致警报按顺序触发。在异步操作中,虽然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);

优势

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

同步、阻塞示例

同步阻塞操作的一个示例是一些 Web 服务器(如 Java 或 PHP 中的 Web 服务器)如​​何处理 IO 或网络请求。如果您的代码从文件或数据库中读取,则您的代码会“阻止”执行后的所有内容。在此期间,您的机器正在为一个线程不做任何事情保留内存和处理时间。

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

异步、非阻塞示例

异步、非阻塞服务器——就像在 Node 中制作的服务器——只使用一个线程来服务所有请求。这意味着 Node 实例充分利用了单个线程。创作者设计它的前提是 I/O 和网络操作是瓶颈。

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

【讨论】:

  • 我不确定我是否理解您在 PHP 中的阻塞 下的第二段。你是说,“虽然 PHP 通常会阻塞 IO,但它不会因为操作系统自动线程 IO 操作。”?或者,您是说这在 PHP 中不是问题,因为 PHP 会自动为每个请求创建一个新线程,因此一个被阻止的请求不会停止整个 PHP 环境? (我猜是后者..)
  • 等等,如果是指后者,非阻塞 I/O PHP(如 reactPHP 或其他)比阻塞 I/O 有什么优势。还是很困惑
  • @SunuPinasthikaFajar PHP 本身是同步的,但服务器软件允许它为每个请求线程化,因此看起来一个请求没有阻塞另一个请求。 React 允许 PHP 单独以异步方式运行。
  • @CharlieParker 是的。异步操作与您的代码并行运行。但是当主代码不忙时,“返回”到异步操作结果的回调会在主代码中排队等待执行。
  • @CharlieParker Here's a post 更多地介绍了异步机制的内部结构。
【解决方案2】:
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

【讨论】:

    猜你喜欢
    • 2018-04-06
    • 2011-09-16
    • 2017-11-14
    • 2022-01-09
    • 1970-01-01
    • 2020-07-16
    • 2013-08-22
    • 2015-09-01
    相关资源
    最近更新 更多