Подтвердить что ты не робот

Вычисление необходимой памяти для n пулов соединений для mongodb, работающих в node.js приложении

Я пытаюсь профилировать производительность моего приложения node.js, использующего mongodb, в настоящее время настроенного для использования 50 пулов соединений. Используя Blazemeter, я пытаюсь выполнить тест, который отправляет 1000 смоделированных пользователей в мою конечную точку. Запуск на меньшем экземпляре amazon ec2 (4 процессора и 7,5 ГБ памяти, производительность, казалось, была связана с процессором). Когда я начал переходить на более крупную машину с по меньшей мере 8 процессорами, работающими в режиме кластера pm2, похоже, что у mongodb заканчивается память. Когда тест достигает примерно 300-500 моделируемых пользователей, процесс mongo завершится неудачно:

т.е. Я получаю сообщение об ошибке из всех запросов db, и я видел следующее сообщение, когда пытаюсь запустить оболочку mongo:

2015-10-26T23:34:56.657+0000 warning: Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused
2015-10-26T23:34:56.658+0000 Error: couldn't connect to server 127.0.0.1:27017 (127.0.0.1), connection attempt failed at src/mongo/shell/mongo.js:146
exception: connect failed

В первый раз, когда это произошло, я также обнаружил следующую ошибку в журнале монго:

exception in initAndListen: 10309 Unable to create/open lock file: /var/lib/mongodb/mongod.lock errno:13 Permission denied Is a mongod instance already running?, terminating

В следующих тестах я видел только описанное выше поведение, но не видел ошибок в журнале mongo.

При выполнении этих тестов монго обычно заканчивается использованием около 80% системной памяти перед сбоем.

Вот только mongo-запросы, используемые этой конечной точкой:

    utility.getNextId(db, "projects", function(err, counter) {
    var pid = counter.seq;
    var newProject = {
        name: projectName,
        path: "/projects/"+user.name+"/"+projectName,
        created: utility.now(),
        modified: utility.now(),
        uid: user.uid,
        pid: pid,
        ip: ip
    }

    // Hierarchy of cloned projects
    if( parentPid )
        newProject.parent = parentPid;

    db.collection("projects").insert(newProject, function(err, inserted) {
        db.collection("users").update(
            {uid: user.uid},
            {$addToSet: { projects:pid }},
            function(err,_) {
                callback(err, newProject);
            }
        );
    });
});
};

exports.getNextId = function(db, name, callback) {
db.collection("counters").findAndModify(
    {_id:name},
    [["_id","asc"]],
    {$inc : {"seq":1}},
    {upsert:true, new:true},
    function(err, object) {
        callback(err, object);
    }
);
};

Большая часть этого тестирования была выполнена на amazon ec2 m4.4xlarge (16 бит и 64 ГБ оперативной памяти).

Является ли размер пула соединений размером от 50 до больших для машины с 64 ГБ ОЗУ? Я бы не подумал. Есть ли хороший способ рассчитать объем памяти, необходимый для n пулов соединений? Является ли моя проблема с запросами, которые я делаю?

EDIT: Вот скриншот, показывающий монгостат прямо как монго, рухнувший на Amazon ec2 m4.4xlarge с 16cpus и 64GB RAM

введите описание изображения здесь

Мы создаем БД mongo наверху, для чего требуется другое:

var mongo = require("mongodb");
var flash = require("connect-flash");
var session = require("express-session");
var auth = require("basic-auth");
var admin = require("./admin.js");

var mongoServer = new mongo.Server("localhost", 27017, {auto_recconnect:true, poolSize: 50});
var db = new mongo.Db("aqo", mongoServer, {safe:true});
var busboy = require('connect-busboy');

db.open(function(err,db) {
    if(err)
        console.warn("mongo-open err:",err);
});

EDIT: Вот мои индексы для коллекции пользователей:

[
{
    "v" : 1,
    "key" : {
        "_id" : 1
    },
    "name" : "_id_",
    "ns" : "aqo.users"
},
{
    "v" : 1,
    "key" : {
        "uid" : 1
    },
    "name" : "uid_1",
    "ns" : "aqo.users"
}
]
4b9b3361

Ответ 1

Хотя размер пула 50 невелик для машины с 64 ГБ ОЗУ, 800 конечно. Это потому, что у вас есть 16 экземпляров вашего процесса node, работающего по 50 штук. Номер по умолчанию для максимальных подключений - 80% от доступных дескрипторов файлов. Если вы используете Linux, значение по умолчанию равно 1024, так что у вас уже открыто почти максимальное количество подключений. Кроме того, каждое соединение имеет накладные расходы ~ 10 МБ, поэтому вы используете около 8 ГБ для подключения в одиночку. Это, очевидно, не идеально.

В идеале вы должны как можно больше использовать эти соединения в своем пуле соединений. Итак, начните тестирование нагрузки, установив для параметра poolSize значение по умолчанию 5. (т.е. На самом деле 16 * 5 = 80). Вы можете доверять pm2, чтобы красиво обрабатывать нагрузку в круговом режиме, и что пул 5 для каждого экземпляра должен быть отлично и дать вам оптимальную производительность. В случае, если 5 недостаточно, поднимитесь немного, пока не найдете что-то подходящее.

Ответ 2

У вас есть большое количество прочитанных в очереди читаемых файлов, и не многие из них успешно читаются. Я предполагаю, что uid в коллекции users не имеет индекса (как вы запрашиваете _id в другом месте, а Mongo автоматически индексирует это).

Также похоже, что вы используете Mongo как автономный сервер, он предназначен для запуска в виде наборов реплик, я не уверен, какие проблемы это вызовет, но я предполагаю, что они не провели много испытаний единственный экземпляр Mongo, работающий самостоятельно, поэтому могут быть проблемы с памятью.