在 PM2 上同时阻止 运行 个请求
Blocking requests not running simultaneously on PM2
在我的 express 应用程序中,我在我的应用程序中定义了 2 个端点。一种用于 is-sever-up 检查,一种用于模拟阻塞操作。
app.use('/status', (req, res) => {
res.sendStatus(200);
});
app.use('/p', (req, res) => {
const { logger } = req;
logger.info({ message: 'Start' });
let i = 0;
const max = 10 ** 10;
while (i < max) {
i += 1;
}
res.send(`${i}`);
logger.info({ message: 'End' });
});
我正在使用 winston
进行日志记录,使用 PM2 使用以下命令进行集群
$ pm2 start bin/httpServer.js -i 0
它已经启动了 4 个实例。
现在,当我在不同的选项卡/p
、/p
、/status
按顺序访问路线时 在(请求 1 和请求 2)和(请求 2 和请求 3)之间有大约 1 秒的延迟,我希望在一段时间后得到请求 1 和请求 2 的响应,但是有大约 1 秒的延迟和请求响应3应该马上来。
实际:请求 3 的响应确实立即到来,但请求 1 和请求 2 发生了一些奇怪的事情。请求 2 甚至在请求 1 完成后才开始。这是我得到的日志。您可以看到请求 1 结束和请求 2 开始的时间戳。
{"message":"Start","requestId":"5c1f85bd-94d9-4333-8a87-30f3b3885d9c","level":"info","timestamp":"2020-12-28 07:34:48"}
{"message":"End","requestId":"5c1f85bd-94d9-4333-8a87-30f3b3885d9c","level":"info","timestamp":"2020-12-28 07:35:03"}
{"message":"Start","requestId":"f1f86f68-1ddf-47b1-ae62-f75c7aa7a58d","level":"info","timestamp":"2020-12-28 07:35:03"}
{"message":"End","requestId":"f1f86f68-1ddf-47b1-ae62-f75c7aa7a58d","level":"info","timestamp":"2020-12-28 07:35:17"}
为什么请求1和请求2没有同时启动(当然有1秒的延迟)?而且如果他们运行是同步的,为什么请求3立即响应而不是等待请求1和2完成?
这是因为header的连接在你的节点服务器默认响应的响应中是keep-alive
。因此,当您使用浏览器时,连接将被重用(curl 也可以模拟重用连接的情况)。这意味着多个请求在指定时间内由同一个实例提供服务。即使你有多个节点实例。
Note: You could see specified time in response header like this Keep-Alive: timeout=5
If you use browser, open network tab to see response headers.
If you use curl, add -v
options to see response headers
您可以尝试在终端中同时使用多个分隔的curl
命令。 分隔的curl
命令意味着连接不会被重用。因此,您将获得预期的结果。您可以在 /status
路由器中添加一个 console.log("status test")
。然后,使用 pm2 logs
查看哪个实例服务请求,如下格式(这些日志是通过使用浏览器访问端点产生的)。
0|server | status test
0|server | status test
0 表示第一个实例,当您使用浏览器访问端点时,您会看到这都是为请求提供服务的同一个实例。但是,如果你使用 curl
,你会发现这个数字总是在变化,这意味着每个请求都由不同的节点实例提供服务。
您可以看到我在终端中使用 curl 同时发送了两个请求。然后,不同的节点实例来服务请求。所以,console.log
的开始和结束时间是一样的。在这个例子中,我有 8 个事件循环,所以我可以同时处理 8 个长处理(同步代码)请求。
并且,您可以使用 curl
来模拟 keep-alive
的情况。然后,您会看到请求由同一个节点实例提供服务。
curl http://localhost:8080/status http://localhost:8080/status -v -H "Connection: keep-alive"
您还可以使用 connection close
查看请求由不同的节点实例提供服务。
curl http://localhost:8080/status http://localhost:8080/status -v -H "Connection: close"
你可以在这里看到不同之处。
如果你想在服务器端关闭连接,你可以使用下面的代码。
res.setHeader("Connection", "close")
这是我的测试代码。
const express = require("express")
const app = express();
const port = 8080;
app.use('/status', (req, res) => {
console.log("status tests");
res.sendStatus(200);
});
app.use('/p', (req, res) => {
console.log(new Date() + " start");
let i = 0;
const max = 10 ** 10;
while (i < max) {
i += 1;
}
res.send(`${i}`);
console.log(new Date() + " end");
});
app.listen(port, () => {
return console.log(`server is listening on ${port}`);
});
在我的 express 应用程序中,我在我的应用程序中定义了 2 个端点。一种用于 is-sever-up 检查,一种用于模拟阻塞操作。
app.use('/status', (req, res) => {
res.sendStatus(200);
});
app.use('/p', (req, res) => {
const { logger } = req;
logger.info({ message: 'Start' });
let i = 0;
const max = 10 ** 10;
while (i < max) {
i += 1;
}
res.send(`${i}`);
logger.info({ message: 'End' });
});
我正在使用 winston
进行日志记录,使用 PM2 使用以下命令进行集群
$ pm2 start bin/httpServer.js -i 0
它已经启动了 4 个实例。
现在,当我在不同的选项卡/p
、/p
、/status
按顺序访问路线时 在(请求 1 和请求 2)和(请求 2 和请求 3)之间有大约 1 秒的延迟,我希望在一段时间后得到请求 1 和请求 2 的响应,但是有大约 1 秒的延迟和请求响应3应该马上来。
实际:请求 3 的响应确实立即到来,但请求 1 和请求 2 发生了一些奇怪的事情。请求 2 甚至在请求 1 完成后才开始。这是我得到的日志。您可以看到请求 1 结束和请求 2 开始的时间戳。
{"message":"Start","requestId":"5c1f85bd-94d9-4333-8a87-30f3b3885d9c","level":"info","timestamp":"2020-12-28 07:34:48"}
{"message":"End","requestId":"5c1f85bd-94d9-4333-8a87-30f3b3885d9c","level":"info","timestamp":"2020-12-28 07:35:03"}
{"message":"Start","requestId":"f1f86f68-1ddf-47b1-ae62-f75c7aa7a58d","level":"info","timestamp":"2020-12-28 07:35:03"}
{"message":"End","requestId":"f1f86f68-1ddf-47b1-ae62-f75c7aa7a58d","level":"info","timestamp":"2020-12-28 07:35:17"}
为什么请求1和请求2没有同时启动(当然有1秒的延迟)?而且如果他们运行是同步的,为什么请求3立即响应而不是等待请求1和2完成?
这是因为header的连接在你的节点服务器默认响应的响应中是keep-alive
。因此,当您使用浏览器时,连接将被重用(curl 也可以模拟重用连接的情况)。这意味着多个请求在指定时间内由同一个实例提供服务。即使你有多个节点实例。
Note: You could see specified time in response header like this
Keep-Alive: timeout=5
If you use browser, open network tab to see response headers.
If you use curl, add-v
options to see response headers
您可以尝试在终端中同时使用多个分隔的curl
命令。 分隔的curl
命令意味着连接不会被重用。因此,您将获得预期的结果。您可以在 /status
路由器中添加一个 console.log("status test")
。然后,使用 pm2 logs
查看哪个实例服务请求,如下格式(这些日志是通过使用浏览器访问端点产生的)。
0|server | status test
0|server | status test
0 表示第一个实例,当您使用浏览器访问端点时,您会看到这都是为请求提供服务的同一个实例。但是,如果你使用 curl
,你会发现这个数字总是在变化,这意味着每个请求都由不同的节点实例提供服务。
您可以看到我在终端中使用 curl 同时发送了两个请求。然后,不同的节点实例来服务请求。所以,console.log
的开始和结束时间是一样的。在这个例子中,我有 8 个事件循环,所以我可以同时处理 8 个长处理(同步代码)请求。
并且,您可以使用 curl
来模拟 keep-alive
的情况。然后,您会看到请求由同一个节点实例提供服务。
curl http://localhost:8080/status http://localhost:8080/status -v -H "Connection: keep-alive"
您还可以使用 connection close
查看请求由不同的节点实例提供服务。
curl http://localhost:8080/status http://localhost:8080/status -v -H "Connection: close"
你可以在这里看到不同之处。
如果你想在服务器端关闭连接,你可以使用下面的代码。
res.setHeader("Connection", "close")
这是我的测试代码。
const express = require("express")
const app = express();
const port = 8080;
app.use('/status', (req, res) => {
console.log("status tests");
res.sendStatus(200);
});
app.use('/p', (req, res) => {
console.log(new Date() + " start");
let i = 0;
const max = 10 ** 10;
while (i < max) {
i += 1;
}
res.send(`${i}`);
console.log(new Date() + " end");
});
app.listen(port, () => {
return console.log(`server is listening on ${port}`);
});