Nodejs mkdirP 模組導致CPU佔用高的問題

foreverpx發表於2015-05-21

Nodejs mkdirP 模組導致CPU佔用高的問題

近期將nodejs專案部署到伺服器上並啟動時,發現node程式的cpu佔用率在40%左右,當時表示非常不解,剛啟動的服務並沒有執行什麼需要大量消耗cpu的邏輯,且此時還未有請求傳送到伺服器端。

鑑於這種情況,只能猜測是某段程式在初始化一些東西的時候異常,所以才導致了這種情況。

經過對程式碼的排查後,最終鎖定出為題的程式碼塊如下:

router.use(multer({
    dest: config.uploadDir,
    limits:{
        fileSize : config.fileSizeLimit, //bytes , == 50M
        files : 1
    },
    rename:function(fieldname, filename) {
        return uuid.v1() + "_" + filename + "_" + Date.now();
    },
    onFileUploadStart: function (file) {
        console.log(file.originalname + ' is starting ...');
    },
    onError: function (error, next) {
        winston.error(error);
        next(error);
    }
}));

初看這段程式碼怎麼也不相信它會佔用這麼高的CPU,所以最大的嫌疑就是multer模組的初始化了,於是進入原始碼看看。

multer初始化部分原始碼:

  var dest;

  if (options.dest) {
    dest = options.dest;
  } else {
    dest = os.tmpdir();
  }

  mkdirp(dest, function(err) { if (err) throw err; });

  var rename = options.rename || function(fieldname, filename) {
    var random_string = fieldname + filename + Date.now() + Math.random();
    return crypto.createHash('md5').update(random_string).digest('hex');
  };

這段程式碼最有嫌疑的不是mkdirP(建立目標資料夾)就是crypto的md5了,那麼一個一個排除。首先只是註釋掉mkdirP,重啟node,發現cpu基本為0了,所以能斷定問題出在mkdirP上了。

單憑這句mkdirp(dest, function(err) { if (err) throw err; });也看不出什麼東西,所以還是得繼續進入mkdirP的實現。

mkdirP在建立資料夾的原始碼中有這麼一段:

function mkdirP (p, mode, f, made) {
    //此處省略幾行
    fs.mkdir(p, mode, function (er) {
        if (!er) {
            made = made || p;
            return cb(null, made);
        }
        switch (er.code) {
            case 'ENOENT':
                mkdirP(path.dirname(p), mode, function (er, made) {
                    if (er) cb(er, made);
                    else mkdirP(p, mode, cb, made);
                });
                break;
            default:
                fs.stat(p, function (er2, stat) {

                    if (er2 || !stat.isDirectory()) cb(er, made)
                    else cb(null, made);
                });
                break;
        }
    });

看到case ‘ENOENT’時就有點端倪了,在建立資料夾失敗後,又調了mkdirP,這樣如果第一次出問題了,那不就不停的嘗試建立了。如果是這樣,那麼肯定是傳入的路徑出了問題。回頭檢查config裡面的路徑時,發現路徑在部署配置的時候斜槓的方向寫反了:

config.path = 'c:\aa\aa';

正確的應該是:

config.path = 'c:\\aa\\aa';
or
config.path = 'c://aa//aa';

幾經周折終於解決了問題,nodejs的路還很長,走,吃飯去……

文章作者:forevercjl
文章原文連結:http://blog.csdn.net/ForeverCjl/article/details/45895795
轉載請註明出處。

相關文章