node-mysql中的连接池代码学习

node-mysql是一个node.js下的mysql驱动,前段时间在处理连接池的问题上遇到了连接不释放的疑难杂症,虽已解决,但仍需总结经验避免下次重蹈覆辙。下面是node-mysql中的连接池的部分代码,我加入了详细日志,以作备忘之用。

/**
 * 在连接池中获取Connection
 * @param cb
 * @returns {*}
 */
Pool.prototype.getConnection = function (cb) {
    //本地加的日志
    console.log("getConnection _allConnections.length: %j, _freeConnections.length: %j", this._allConnections.length, this._freeConnections.length);

    //池关闭检查
    if (this._closed) {
        return process.nextTick(function () {
            return cb(new Error('Pool is closed.'));
        });
    }

    var connection;
    //检查可用Connection,大于0直接从池中出栈并返回
    if (this._freeConnections.length > 0) {
        connection = this._freeConnections.shift();
        return process.nextTick(function () {
            return cb(null, connection);
        });
    }

    //检查连接数是否超过上限(默认10),没有超过则创建(真正的CreateConnection)
    if (this.config.connectionLimit === 0 || this._allConnections.length < this.config.connectionLimit) {
        connection = new PoolConnection(this, { config: this.config.connectionConfig });

        //新创建的连接入栈池中
        this._allConnections.push(connection);

        //验证新创建的Connection是否可用
        return connection.connect(function (err) {
            if (this._closed) {
                return cb(new Error('Pool is closed.'));
            }
            if (err) {
                return cb(err);
            }

            this.emit('connection', connection);
            return cb(null, connection);
        }.bind(this));
    }

    //检查是否允许排队等待(默认True),False时直接抛错
    if (!this.config.waitForConnections) {
        return process.nextTick(function () {
            return cb(new Error('No connections available.'));
        });
    }

    //检查排队人数是否超过上限(默认0,无限)
    if (this.config.queueLimit && this._connectionQueue.length >= this.config.queueLimit) {
        return cb(new Error('Queue limit reached.'));
    }

    //开始排队
    this._connectionQueue.push(cb);
};

/**
 * 释放Connection
 * @param connection
 */
Pool.prototype.releaseConnection = function (connection) {
    var cb;
    //非连接池模式处理
    if (!connection._pool) {
        //如果有人排队
        if (this._connectionQueue.length) {
            //出栈一个排队回调
            cb = this._connectionQueue.shift();
            //调用getConnection返回Connection给予回调使用
            process.nextTick(this.getConnection.bind(this, cb));
        }
    }
    /**
     *连接池模式处理 有人排队
     */
    else if (this._connectionQueue.length) {
        cb = this._connectionQueue.shift();
        //将释放的connection直接给予排队列表的第一个人使用
        process.nextTick(cb.bind(null, null, connection));
    }
    //连接池模式处理 无人排队
    else {
        //将释放的connection加入可用连接数组,待使用
        this._freeConnections.push(connection);
        //我本地加的日志
        console.log("releaseConnection _allConnections.length: %j, _freeConnections.length: %j", this._allConnections.length, this._freeConnections.length);
    }
};
posted @ 2014-02-19 11:43  冯翔  阅读(2173)  评论(1编辑  收藏  举报