快速路线,数据库访问和NodeJS:最好的方法是什么?

时间:2016-04-21 13:26:43

标签: node.js express websocket node-mysql

我目前正在使用NodeJs,Express,WebSocket和node-mysql开发应用程序。目前,这是全球性的想法:

服务器有登录路由,如下所示:

var configuration = require("./configuration");
var db = require("./database");
var Response = require("./models/response");

var express = require('express');
var app = express();
var server = require("http").Server(app);
var io = require("socket.io")(server);
var bodyParser = require('body-parser');

var jwt = require("jsonwebtoken");
var socketJwt = require('socketio-jwt');

app.use(function(req, res, next)
{
    res.header("Access-Control-Allow-Origin", "http://localhost:8080");
    res.header('Access-Control-Allow-Credentials', true);

    next();
});

app.use(bodyParser.urlencoded({ extended: true }))

app.post('/login', function(req, res)
{
    db.player
        .login(req.body.username, req.body.password)
        .then(function(result)
        {
            var profile = {
                id: result.d[0].id_player,
                name: req.body.username,
                email: 's.sougnez@areaprog.com'
            };

            jwt.sign(profile, configuration.jwtSecret, { expireInMinutes: 60 * 5 }, function(token)
            {
                res.json(new Response({ token: token }));
            });
        },
        function(err)
        {
            res.status(err.getStatus()).json(err);
        });
});

io
    .on('connection', socketJwt.authorize({
        secret: configuration.jwtSecret,
        timeout: 2000
    }))
    .on('authenticated', function(socket)
    {
    });

server.listen(8081);

“db”模块用于连接和查询mysql数据库。以下是此文件的主要概念:

var mysql = require("mysql");
var configuration = require("../configuration");

var Promise = require("promise");
var Response = require("../models/response");

var con = null;

function connect(handleConnection, connection)
{
    return new Promise(function(resolve, reject)
    {
        if (handleConnection !== false)
        {
            con = mysql.createConnection(configuration.db);

            con.connect(function(err)
            {
                if (err)
                {
                    reject(err);

                    return;
                }

                con.beginTransaction(function(err)
                {
                    if (err)
                    {
                        reject(err);

                        return;
                    }

                    resolve();
                });
            })
        }
        else
        {
            con = connection;

            resolve();
        }
    });
}

function commit(handleConnection)
{
    ...
}

function executeNonQuery()
{
    ...
}

function executeQuery(query, args)
{
    ...
}

function hasRow()
{
    ...
}

function lastId()
{
    ...
}

function rollback(handleConnection)
{
    ...
}

module.exports.commit = commit;
module.exports.connect = connect;
module.exports.executeNonQuery = executeNonQuery;
module.exports.executeQuery = executeQuery;
module.exports.hasRow = hasRow;
module.exports.lastId = lastId;
module.exports.rollback = rollback;

module.exports.player = require("./player").init(this);

最后,我们有了“播放器”模块:

var Promise = require('promise');

var player = (function()
{
    var db = null;

    var init = function(database)
    {
        db = database;

        return this;
    };

    var login = function(name, pass, handleConnection, connection)
    {
        return new Promise(function(resolve, reject)
        {
            var data = null;

            db
                .connect(handleConnection, connection)
                .then(function()
                {
                    var query = 'SELECT `id_player`, `language`, `password`, `salt`, `failed_attempt`, `last_ip`, UNIX_TIMESTAMP(`blocked_until`) AS `blocked_until` \
                         FROM `players` \
                         WHERE `name` = ?';

                    var params = [ name ];

                    return db.executeQuery(query, params);
                })
                .then(function(result)
                {
                    if (result.d.length === 0)
                    {
                        result.setError('Invalid username');

                        throw result;
                    }

                    data = result;

                    return db.commit();
                })
                .then(function()
                {
                    resolve(data);
                })
                .catch(function(err)
                {
                    db
                        .rollback(handleConnection)
                        .then(function()
                        {
                            reject(err);
                        });
                });
        });
    };

    return {
        init: init,
        login: login
    }
}());

module.exports = player;

好的,实际上,一切都按预期工作。我打开页面,点击“登录”,然后调用上面代码的路径“/ login”,授予访问权限并创建websocket连接。整个代码是开始的,可能会有变化,但昨天,在阅读NodeJs的帖子时,我意识到db模块是一个单例,所以我想知道......

这是一个有效的架构吗?如果两个用户同时连接怎么办,我不会冒第二个用户调用的“db”的“connect”函数覆盖第一个用户调用初始化的变量“con”的风险吗?昨天我尝试在登录过程中设置了一个long for循环,我注意到第二个用户调用正在等待第一个用户调用=>通常,我不会有冲突问题,但在这种情况下,这是否意味着如果网站上有很多用户,我服务器的性能会非常糟糕?

此外,正如我所说,我将使用WebSockets,这也将使用数据库模块,所以如果我有很多用户,服务器通常会阻止用户处理以前用户的查询,不是吗?

最后,我真的对db模块犹豫不决。将它保留为单例是否正确或是否应为其创建类型并为每个数据库请求创建此类型的新对象?

这些问题非常“具体”,我真的不知道在谷歌上找什么来寻找答案,所以我在这里:-)

非常感谢您的回答

0 个答案:

没有答案