每次请求,内存直线上升的问题
发布于 6个月前 作者 shanelau 530 次浏览

最近使用的ghost框架开发一个科技博客项目。项目运行几天后,发现内存占用达到了5G多。 ** 用户量上升,系统只能奔溃了 ** 花了点时间追查内存问题。

发现每次请求,内存在增加

用express 重现问题

  1. 用express 搭建一个最简单的web项目,
  2. 用 pm2 启动和查看内存状况
pm2 monit
  1. 用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 么

线上的项目是怎么管理内存的

14 回复
  1. 你的服务器是不是对每个请求用新建Buffer来打开和输出style.css
  2. 静态文件应该加入缓存策略

@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);

就解决了。

回到顶部