最近使用的ghost框架开发一个科技博客项目。项目运行几天后,发现内存占用达到了5G多。 ** 用户量上升,系统只能奔溃了 ** 花了点时间追查内存问题。
发现每次请求,内存在增加
用express 重现问题
- 用express 搭建一个最简单的web项目,
- 用 pm2 启动和查看内存状况
pm2 monit
- 用request库,不断请求静态资源文件 style.css,或者直接请求 主页 http://127.0.0.1:3001/
var request = require('request');
var count = 0;
function req(){
count ++;
request('http://127.0.0.1:3001/stylesheets/style.css', function (error, response, body) {
if (!error && response.statusCode === 200) {
//console.log(body) // Print the google web page.
console.log(count);
setTimeout(req(),500);
}
});
}
req();
内存直线上升,关闭req请求后,内存也不释放,难道一定要手动global.gc 么
线上的项目是怎么管理内存的
- 你的服务器是不是对每个请求用新建Buffer来打开和输出style.css
- 静态文件应该加入缓存策略
@tulayang 那应该怎么缓存呢? 使用简单的express 开启的web服务器 ,重复请求一个 css文件 内存也会不停上升,如果请求主页 /index ,内存同样上升,就算上升了,为什么v8 引擎不会自动去回收这些内存呢
我也遇到这个问题 专门新建一个express 的空白项目,每次访问都会增加一点内存 用的是node 0.10.29版本 不知道是不是版本的问题
首先这样的静态文件不应该直接走express server,用nginx什么的最好,其次为什么不用stream。。。
@kissliux 静态文件缓存,只需要判断请求头“If-Last-Modified”的时间,和响应头"Last-Modified"的时间差是否在设定范围。 这个牵扯到HTTP底层的东西。 不会写的话可以使用nginx代理静态文件。
@tulayang 简单应用中,使用的是:app.use(express.static(path.join(__dirname, ‘public’)));
确实线上的项目 所有静态资源要走CDN,让nginx去代理。 估计内存的还是 nodejs的问题
@kissliux 如果你是nginx代理,nodejs程序中的静态路由肯定是得不到访问的。如果是nodejs处理了静态文件,那就很可能是nginx的server和location没有写好。
至于内存,如果是因为请求文件导致的,我怀疑程序中有不停的new Buffer来建立内存暂存文件,Buffer是不遵循js自动回收内存的。
@ycloud 确实,就是这个问题。 我的 V 0.10.28 ,估计还是node的问题 stackoverflow 上面也有这个问题了, http://stackoverflow.com/questions/22507667/nodejs-expressjs-memory-leak
It’s impossible to do larger projects if a simple static server like this uses too much ram.
@AdoHe 恩 要改成nginx , nodejs 做静态服务器还是费力
@tulayang 看看二楼说的问题。 一个最简单那的express 也会出现这样的问题。不停地刷新页面,就能看到内存一直增加 ,并且还不会被回收
。。。。 我是用的nginx做的代理,静态文件直接访问了,然后动态的转发到nodejs的端口,http://blog.gaoqixhb.com
我用的阿里云的centos,才1G内存,完全没事额…
服务器操作系统、Node.js和Express的版本是什么?
能不能写个重现问题的最小用例,托管在github.com上?这样,大家就可以clone下来,仔细研究下。
用以下代码请一个 24kb 的 style.css 文件12W次,内存稳定在112MB。 虽然内存会上升,但是会稳定在一个值。nodejs 还是不错的
var request = require('request');
var async = require('async');
var count = 0;
async.forever(
function(next) {
request('http://localhost:3001/stylesheets/style.css', function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(count++);
}
next();
});
},
function(err) {
}
);
setTimeout(req(),500);
应该是你这句的问题吧。req()执行之后并无返回,于是创建定时器。然后继续执行请求。继续创建定时器。
你一个请求完成的时间应该在500ms以内。然后定时器不停创建。
改为
setTimeout(req, 500);
就解决了。