一、连接池

1. 在Web开发中,建立一个数据库连接的开销相对来说还是很大的,为每个请求创建一个甚至多个连接会对高流量网站造成不必要的额外负担,也会导致性能下降

2. 解决方案是在内部缓存池里维护数据库连接,当某连接不再需要时,它会被放回连接池里,这样就能立刻为下一个进入的请求服务了

3. Node推崇"一个模块,一个功能"的理念,所以,Node开发者在数据层之上应使用通用的连接池( generic-pool)模块来进行数据库连接服务

4. generic-pool模块会重用已有的连接,尽可能地防止因为创建新的数据库连接而带来的开销,而且这个模块可以用在任何数据库上

5. Node 连接池的优雅之处在于,它可以表示任何持久化的资源(如会话缓存,甚至是硬件接口)

二、使用MySQL连接池

const mysql = require('mysql')
const genericPool = require('generic-pool')

/**
 * 当客户尝试获取一个连接时,
 * 如果没有已经打开的连接,
 * 连接池会调用创建函数
 * 如果一个连接闲置太久了
 * 由 idleTimeoutMillis 属性来指定空闲间隔,以毫秒来计算
 * 它会被销毁并且释放内存资源
 */ 

/**
 * Step 1 - Create pool using a factory object
 */
const factory = {
  create: function() {
    const db = mysql.createConnection({
        host: '127.0.0.1',
        user: 'test',
        password: '*3!0CcEf',
        database: 'upandrunning',
    })
    db.connect()
    return db
  },
  destroy: function(client) {
    client.end()
  }
}
 
const opts = {
  max: 10, // maximum size of the pool
  min: 2 // minimum size of the pool
}

const myPool = genericPool.createPool(factory, opts)
 
/**
 * Step 2 - Use pool in your code to acquire/release resources
 */
 
// acquire connection - Promise is resolved
// once a resource becomes available
const resourcePromise = myPool.acquire()
 
resourcePromise
  .then(function(client) {
    client.query("SELECT * FROM users", [], function(error, results, field) {
        if(error){
            throw error
        }else{
            console.log(results)
        }        
        // return object back to pool
        myPool.release(client)
    })
  })
  .catch(function(err) {
    // handle error - this is generally a timeout or maxWaitingClients
    // error
    console.log(err)
  })
 
/**
 * Step 3 - Drain pool during shutdown (optional)
 */
// Only call this once in your application -- at the point you want
// to shutdown and stop using this pool.
myPool.drain().then(function() {
  myPool.clear()
})