node js express 应用程序中的并发以使用 setTimeout 获取请求
Concurrency in node js express app for get request with setTimeout
Console log Image
const express = require('express');
const app = express();
const port = 4444;
app.get('/', async (req, res) => {
console.log('got request');
await new Promise(resolve => setTimeout(resolve, 10000));
console.log('done');
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
如果我同时点击 get request http://localhost:4444 三次,那么它 returning 日志如下
got request
done
got request
done
got request
done
由于进程线程外部的节点事件循环和回调队列,它不应该return以下面的方式输出吗? (也许我错了,但需要对节点内部有一些了解)和节点中的外部 api 请找到附图
Javascript Run time environment
got request
got request
got request
done
done
done
它正在返回这样的响应:
Node.js 是事件驱动语言。要了解并发性,您应该查看节点如何执行此代码。 Node 是一种单线程语言(但在内部它使用多线程),它在请求到来时接受它们。在这种情况下,Node 接受请求并为 promise 分配回调,然而,在等待事件循环执行回调的同时,它将接受尽可能多的请求(例如内存,cpu 等)。由于事件循环中有 setTimeout 队列,所有这些回调都将在那里注册,一旦计时器完成,事件循环将耗尽其队列。
单线程事件循环模型处理步骤:
客户端向Node.js服务器发送请求。
Node.js 内部维护一个有限的(可配置的)线程池来为客户端请求提供服务。
Node.js 接收这些请求并将它们放入称为“事件队列”的队列中。
Node.js 内部有一个组件,称为“事件循环”。之所以得此名,是因为它采用了无限循环的方式接收请求并进行处理。
事件循环仅使用单线程。它是 Node JS 平台处理模型的主要核心。
事件循环检查任何客户端请求是否放置在事件队列中。如果没有,则无限期等待传入请求。
如果是,则从事件队列中提取一个客户端请求
开始处理客户请求
如果客户端请求不需要任何阻塞 IO 操作,则处理所有内容,准备响应并将其发送回客户端。
如果该客户端请求需要一些阻塞 IO 操作,例如与数据库、文件系统、外部服务交互,那么它将采用不同的方法
检查内部线程池的线程可用性
选择一个线程并将此客户端请求分配给该线程。
该线程负责获取该请求、处理它、执行阻塞 IO 操作、准备响应并将其发送回事件循环
你可以在这里查看更多details(解释得很好)。
感谢https://whosebug.com/users/5330340/phani-kumar
我知道它阻塞的原因了。我在 chrome 中对此进行了测试。我从 chrome 浏览器发出获取请求,当我在 firefox 中尝试相同时,它按预期工作。
原因是因为这个
Chrome 锁定缓存并在再次请求相同资源之前等待查看一次请求的结果。
Chrome stalls when making multiple requests to same resource?
Console log Image
const express = require('express');
const app = express();
const port = 4444;
app.get('/', async (req, res) => {
console.log('got request');
await new Promise(resolve => setTimeout(resolve, 10000));
console.log('done');
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
如果我同时点击 get request http://localhost:4444 三次,那么它 returning 日志如下
got request
done
got request
done
got request
done
由于进程线程外部的节点事件循环和回调队列,它不应该return以下面的方式输出吗? (也许我错了,但需要对节点内部有一些了解)和节点中的外部 api 请找到附图 Javascript Run time environment
got request
got request
got request
done
done
done
它正在返回这样的响应:
Node.js 是事件驱动语言。要了解并发性,您应该查看节点如何执行此代码。 Node 是一种单线程语言(但在内部它使用多线程),它在请求到来时接受它们。在这种情况下,Node 接受请求并为 promise 分配回调,然而,在等待事件循环执行回调的同时,它将接受尽可能多的请求(例如内存,cpu 等)。由于事件循环中有 setTimeout 队列,所有这些回调都将在那里注册,一旦计时器完成,事件循环将耗尽其队列。
单线程事件循环模型处理步骤:
客户端向Node.js服务器发送请求。
Node.js 内部维护一个有限的(可配置的)线程池来为客户端请求提供服务。
Node.js 接收这些请求并将它们放入称为“事件队列”的队列中。
Node.js 内部有一个组件,称为“事件循环”。之所以得此名,是因为它采用了无限循环的方式接收请求并进行处理。
事件循环仅使用单线程。它是 Node JS 平台处理模型的主要核心。
事件循环检查任何客户端请求是否放置在事件队列中。如果没有,则无限期等待传入请求。
如果是,则从事件队列中提取一个客户端请求
开始处理客户请求
如果客户端请求不需要任何阻塞 IO 操作,则处理所有内容,准备响应并将其发送回客户端。
如果该客户端请求需要一些阻塞 IO 操作,例如与数据库、文件系统、外部服务交互,那么它将采用不同的方法
检查内部线程池的线程可用性
选择一个线程并将此客户端请求分配给该线程。
该线程负责获取该请求、处理它、执行阻塞 IO 操作、准备响应并将其发送回事件循环
你可以在这里查看更多details(解释得很好)。
感谢https://whosebug.com/users/5330340/phani-kumar
我知道它阻塞的原因了。我在 chrome 中对此进行了测试。我从 chrome 浏览器发出获取请求,当我在 firefox 中尝试相同时,它按预期工作。
原因是因为这个
Chrome 锁定缓存并在再次请求相同资源之前等待查看一次请求的结果。
Chrome stalls when making multiple requests to same resource?