Node 数据库连接池

在其他语言中 连接池可能要写很多东西才能实现,JAVA 可以说是最复杂的一个。
现在的话,我去了一个新的地方,主要是使用node来优化一下原来php做不到的性能优化,本来我是奇怪为什么不用swoole的,但是现在看来觉得的确用node的成本会比较低。

我们先看看node的数据库连接池是怎么实现的。

const mysql = require('mysql');

var time = new Date().getTime();

const pool = mysql.createPool({
    connectionLimit: 10,
    host: '192.168.30.xx',
    user: "xxx",
    password: '123456',
    database: 'liveroome'
});


for (let index = 0; index < 100000000; index++) {
    pool.getConnection(function (err, conn) {
        if (err) {
            return;
        }
        conn.query('SELECT * from users', function (err, result, fields) {
            if (err) throw err;
            conn.release();
        });
    });
}


console.log(new Date().getTime() - time);
Node 数据库连接池_第1张图片
image.png

区区几行代码就能实现,
这是一个查询 10亿 的并发查询 使用的时间是 65983 毫秒

在看看没有使用连接池的性能

const connection = mysql.createConnection({
    host: '192.168.30.xx',
    user: "xxx",
    password: '123456',
    database: 'liveroome'
});

connection.connect();
for (let i = 0; i < 100000000; i++) {
    connection.query('SELECT * from users', function (err, results, fields) {
    });
}

Node 数据库连接池_第2张图片
image.png

跑了很久 直接内存溢出

下面 看PHP
这个代码来着
https://juejin.im/entry/5a5dceea51882573467cfabe


 * createTime : 2018/1/16 14:32
 * description: Server.php - swoole-demo
 */
class Pool
{
    // 连接池数组 .
    protected $connections ;

    // 最大连接数
    protected $max ;

    // 最小连接数
    protected $min ;

    // 已连接数
    protected $count = 0 ;

    protected $inited = false ;

    // 单例
    private static $instance ;

    //数据库配置
    protected $config  = array(
        'host' => '127.0.0.1',
        'port' => 3306,
        'user' => 'root',
        'password' => 'rootpassword',
        'database' => 'swoole',
        'charset' => 'utf8',
        'timeout' => 2,
    );

    public function __construct()
    {
        //初始化连接是一个Spl队列
        $this->connections = new SplQueue() ;
        $this->max = 30 ;
        $this->min = 5 ;
        // 绑定单例
        self::$instance = & $this ;
    }

    // worker启动的时候 建立 min 个连接
    public function init()
    {
        if($this->inited){
            return ;
        }
        for($i = 0; $i < $this->min ; $i ++){
            $this->generate();
        }
        return $this ;
    }

    /**
     * 维持当前的连接数不断线,并且剔除断线的链接 .
     */
    public function keepAlive()
    {
        // 2分钟检测一次连接
        swoole_timer_tick( 1000 , function(){
            // 维持连接
            while ($this->connections->count() >0 && $next=$this->connections->shift()){
                $next->query("select 1" , function($db ,$res){
                    if($res == false){
                        return ;
                    }
                    echo "当前连接数:" . $this->connections->count() . PHP_EOL ;
                    $this->connections->push($db);
                });
            }
        });

        swoole_timer_tick(1000 , function(){
            // 维持活跃的链接数在 min-max之间
            if($this->connections->count() > $this->max) {
                while($this->max < $this->connections->count()){
                    $next = $this->connections->shift();
                    $next->close();
                    $this->count-- ;
                    echo "关闭连接...\n" ;
                }
            }
        });
    }

    // 建立一个新的连接
    public function generate($callback = null)
    {
        $db = new swoole_mysql ;
        $db->connect($this->config , function($db , $res) use($callback) {
            if($res == false){
                throw new Exception("数据库连接错误::" . $db->connect_errno . $db->connect_error);
            }
            $this->count ++ ;
            $this->addConnections($db);
            if(is_callable($callback)){
                call_user_func($callback);
            }
        });
    }

    // 连接推进队列
    public function addConnections($db)
    {
        $this->connections->push($db);
        return $this;
    }

    // 执行数据库命令 . 会判断连接数够不够,够就直接执行,不够就新建连接执行
    public function query($query , $callback)
    {
        if($this->connections->count() == 0) {
            $this->generate(function() use($query,$callback){
                $this->exec($query,$callback);
            });
        }
        else{
           $this->exec($query,$callback);
        }
    }
    // 直接执行数据库命令并且 callback();
    private function exec($query, $callback)
    {
        $db = $this->connections->shift();
        $db->query($query ,function($db , $result) use($callback){
            $this->connections->push($db);
            $callback($result);
        });
    }

    public static function getInstance()
    {
        if(is_null(self::$instance)){
            new Pool();
        }
        return self::$instance;
    }
}

$server = new swoole_http_server("0.0.0.0",9501);
$server->set([
    'worker_num' => 4 ,
]);
$server->on("WorkerStart",function($server , $wid){
    Pool::getInstance()->init()->keepAlive();
});
$server->on("request",function($request,$response){
    $pool = Pool::getInstance()->query("select * from users", function($res) use($response) {
        $response->end(json_encode($res));
    });
});
$server->start();

代码是挺长。。。
在业务不大的情况下 建议使用node,因为方便很多

你可能感兴趣的:(Node 数据库连接池)