node.js - 我们正面临 Nodejs 响应时间问题
问题描述
当我们达到大约 100 个在线用户时,我们正面临 Nodejs 响应时间问题,我们的响应时间达到 10 秒。我认为有一个混乱的代码使我的应用程序运行缓慢。有没有办法在我的 nodejs 应用程序上追踪问题(在我的应用程序变慢的女巫代码上)?我正在使用 nodejs、expressjs、mongodb 和 nginx
NGINX:
upstream http_backend {
server 127.0.0.1:8087;
keepalive 32;
}
server {
listen 80;
listen [::]:80;
server_name cdn.amjilt.com;
return 301 https://$server_name$request_uri;
}
server {
listen 7070;
listen [::]:7070;
server_name cdn.amjilt.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name cdn.amjilt.com;
ssl on;
ssl_certificate /etc/nginx/cert/media/media.crt;
ssl_certificate_key /etc/nginx/cert/media/media.key;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
client_max_body_size 500M;
client_body_buffer_size 500M;
proxy_buffer_size 16M;
proxy_buffers 24 8M;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
location /images{
root /home/ubuntu/projects/amjilt_media/static;
}
location /tmp{
root /home/ubuntu/projects/amjilt_media/static;
}
location /images/uploads{
root /home/ubuntu/projects/amjilt_media/static;
}
location /images/avatar{
root /home/ubuntu/projects/amjilt_media/static;
}
location /api/video/show{
expires off;
proxy_buffering off;
chunked_transfer_encoding on;
proxy_pass http://http_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
location /api/video/mobile{
expires off;
proxy_buffering off;
chunked_transfer_encoding on;
proxy_pass http://http_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
location /api/pdf/show{
expires off;
proxy_buffering off;
chunked_transfer_encoding on;
proxy_pass http://http_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
location / {
proxy_pass http://localhost:8087;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
# gzip
gzip_types text/css text/less text/plain text/xml application/xml application/json application/javascript;
gzip on;
}
路由器:
let flname = '../../..' + video.path;
var file = path.resolve(__dirname, flname);
fs.stat(file, function(err, stats) {
if (err) {
winston.error('/video/show/:id fs.stat error ',err);
if (err.code === 'ENOENT') {
// 404 Error if file not found
res.status(404).json({msg: 'log.n_request'});
}
res.status(404).json({msg: 'log.n_request'});
}
var range = req.headers.range;
if (!range) {
var stat_ = fs.statSync(file)
var header = {
'Content-Length': stat_.size,
'Content-Type': (!req.useragent.isSafari ? token : 'mp4'),
}
res.writeHead(200, header)
var stream = fs.createReadStream(file)
.on("open", function () {
stream.pipe(res);
}).on("error", function (err) {
res.end(err);
});
}else{
var positions = range.replace(/bytes=/, "").split("-");
var start = parseInt(positions[0]);
if(isNaN(start)){
start = 0;
}
var total = stats.size;
var end = positions[1] ? parseInt(positions[1]) : (start+102400);
if(isNaN(end)){
end = start+102400;
}
if(total <= end){
end = total-1;
}
var chunksize = (end - start) + 1;
res.writeHead(206, {
"Content-Range": "bytes " + start + "-" + end + "/" + total,
"Accept-Ranges": "bytes",
"Content-Length": chunksize,
"Content-Type": "video/mp4"
});
var stream = fs.createReadStream(file, {start: start, end: end})
.on("open", function () {
stream.pipe(res);
}).on("error", function (err) {
res.end(err);
});
}
});
解决方案
您必须删除fs.statSync()
. 这会阻塞事件循环,因此您的服务器每次运行时都会一次处理一个请求。而且,事实证明,您可以完全删除调用,因为您已经fs.stat()
在函数的前面调用了同一个文件并且可以使用这些结果。
我还在发送错误后添加了几个返回语句,因为您不希望在发送错误后执行其余代码:
let flname = '../../..' + video.path;
var file = path.resolve(__dirname, flname);
fs.stat(file, function(err, stats) {
if (err) {
winston.error('/video/show/:id fs.stat error ',err);
if (err.code === 'ENOENT') {
// 404 Error if file not found
res.status(404).json({msg: 'log.n_request'});
return;
}
res.status(404).json({msg: 'log.n_request'});
return;
}
var range = req.headers.range;
if (!range) {
var header = {
'Content-Length': stats.size,
'Content-Type': (!req.useragent.isSafari ? token : 'mp4'),
}
res.writeHead(200, header)
var stream = fs.createReadStream(file)
.on("open", function () {
stream.pipe(res);
}).on("error", function (err) {
res.end(err);
});
}else{
var positions = range.replace(/bytes=/, "").split("-");
var start = parseInt(positions[0]);
if(isNaN(start)){
start = 0;
}
var total = stats.size;
var end = positions[1] ? parseInt(positions[1]) : (start+102400);
if(isNaN(end)){
end = start+102400;
}
if(total <= end){
end = total-1;
}
var chunksize = (end - start) + 1;
res.writeHead(206, {
"Content-Range": "bytes " + start + "-" + end + "/" + total,
"Accept-Ranges": "bytes",
"Content-Length": chunksize,
"Content-Type": "video/mp4"
});
var stream = fs.createReadStream(file, {start: start, end: end})
.on("open", function () {
stream.pipe(res);
}).on("error", function (err) {
res.end(err);
});
}
});
推荐阅读
- c - 用 0 初始化一个整数与不在 C 中初始化它
- javascript - 如何将 Rails 视图的 javascript 代码放入 assets/javascript 文件夹?
- javascript - 当 input[type="date"] 成为焦点时如何显示日历弹出窗口
- rust - 为什么我需要 mod 关键字来访问 Rust 相同级别的文件中的结构?
- jquery - 当服务器端数据发生变化时自动更新 jQuery DataTables
- javascript - d3fc.js d3fc JavaScript 中线条系列的设置类
- python - 梯度下降算法,梯度步进函数
- bash - 排序在 bash 中无法正常工作
- maven - 为什么某些 maven 依赖项以颜色显示并且没有得到解决?
- php - 令牌未在 mysql db 中更新