为什么 NodeJS 快递的 POST 处理程序没有被调用,但 RAM 上升了?



我使用的是NodeJs 8.11.3

我有两个应用程序:第一个提供了一个简单的Express‘helloworld API,另外还有一些库:

// API.js
const express = require('express')
const app = express()
var compression = require('compression')
var bodyParser = require('body-parser');
var helmet = require('helmet');
app.use(helmet());
app.use(compression());
app.use(bodyParser.json({ limit: '50mb' }));
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));

app.post('/', (req, res) => {
res.send('Hello World!');
console.log(`SENT in the FIRST PLACE at: ${req.body.event_datetime}, now is ` + new Date().toLocaleString());
});

app.listen(8000, () => console.log('Example app listening on port 8000!'))

第二个是API的客户端。客户端发送一个post请求,其中主体是3.5MB的JSON对象。

// client.js
const rp = require('request-promise');
function send_stuff(obj) {      
let options = {
uri: "http://xxxxx:8000/",
method: "POST",
headers: "headers": {
"Content-Type": "application/json"
},
body: JSON.stringify(obj)
}
return rp(options);
}
var fs = require('fs');
const content= fs.readFileSync("./big_file.txt").toString();
(async () => {    
for (let i = 0; i < 1000; ++i) {
send_stuff(
{
id: 1,
field: 1,
field2: 1,
big_content: content,
id_domain: 1,
event_datetime: new Date().toLocaleString(),
field3: -1,
field4: 1
}).then(r => {           
console.log('ok');           
}).catch(err => {           
console.error("API ERROR");
});
//await sleep(500);
}
})();
function sleep(ms){
return new Promise(resolve => setTimeout(resolve, ms) );
}

有两件事我不能完全理解:

  1. 在客户端的for循环结束之前,我看不到API应用程序接收到的任何数据包
  2. 在监视API的RAM消耗时,我注意到,直到应用程序开始处理请求,RAM消耗才会上升

问题:

关于1(,客户端是否可能因为for循环使事件循环冻结而无法发送数据包?

关于2(API的RAM是否可能继续上升,因为来自客户端的数据包实际上来的非常慢,这是因为它们试图发送3.5MB的请求体,因此在数据包完成之前无法调用API中的POST处理程序?

"1。我看不到API应用程序收到的任何数据包,直到客户端的for循环结束">

浏览器中的JavaScript解释器是作为单个线程实现的。这实际上意味着,在浏览器中一次只能发生一件事,而其他操作或事件则在所谓的Execution Stack中排队。

在启动所有异步操作的同时,for循环会立即运行到完成。我看到在您的代码中有一个await的注释部分。我不明白你为什么在sleep中使用wait,因为它没有任何作用。await使用promise,因此它非常适合与进行API调用的函数一起使用。当您使用await时,您将serialize异步操作一个接一个地运行,而不是并行运行。

在你的例子中,它将是这样的:

(async () => {    
for (let i = 0; i < 1000; ++i) {
//THIS IS SERIALIZING send_stuff operation.
await send_stuff(
{
id: 1,
field: 1,
field2: 1,
big_content: content,
id_domain: 1,
event_datetime: new Date().toLocaleString(),
field3: -1,
field4: 1
}).then(r => {           
console.log('ok');           
}).catch(err => {           
console.error("API ERROR");
});
}
})();

通过这样做,您应该看到您的后端接收到for循环中每个incrementPOST调用。

如果不需要await,则for循环将在Execution Stack拾取asynchronous calls之前完成。这是因为for循环将形成current execution context。您是对的,current execution context的事件循环已冻结。我建议阅读本文以了解更多信息-https://blog.lavrton.com/javascript-loops-how-to-handle-async-await-6252dd3c795

"2.监控API的RAM消耗我注意到,直到应用程序开始处理请求,RAM消耗才会上升。">

重要的是要了解XHR的幕后情况,以回答这个问题。POST在浏览器中实现为两步过程。(Mozilla是个例外。他们只需一步就能降低TAT(。在第一步中,发送头,然后发送数据。这些操作中的每一个都将消耗一些RAM,尽管它应该是最小的。这要复杂得多,因为它涉及缓存,而且每个浏览器实现处理cookie的方式也有所不同。

除非网络服务器/服务器端代码施加限制,否则传输的数据大小将变得无关紧要(假设您的互联网连接良好(。CCD_ 17被序列化为CCD_。来回传输大量文本会影响异步解析。GZIP压缩可能对发送数据前压缩和接收响应后解压缩数据所需的RAM量产生轻微影响。

若您选择压缩数据,在请求发布到服务器之前,预计RAM使用量会增加,同样,在收到响应后,预计RAM的使用量会激增。

希望这能有所帮助。

最新更新