目前為止,我們都是這樣處理請(qǐng)求的,比如:當(dāng)用戶(hù)訪問(wèn)某個(gè)文章頁(yè)的時(shí)候,系統(tǒng)會(huì)創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)連接,通過(guò)該連接到數(shù)據(jù)庫(kù)中查找并返回該文章的數(shù)據(jù),然后關(guān)閉該連接。但是當(dāng)我們的博客訪問(wèn)量巨大的時(shí)候,頻繁的創(chuàng)建和銷(xiāo)毀連接會(huì)產(chǎn)生非常大的系統(tǒng)開(kāi)銷(xiāo)。這個(gè)時(shí)候,我們就需要引入數(shù)據(jù)庫(kù)連接池了。
什么是連接池(connection pool)呢?維基百科中是這樣定義的:
connection pool is a cache of database connections maintained so that the connections can be reused when future requests to the database are required.
說(shuō)白了就是,我們一開(kāi)始就創(chuàng)建一沓數(shù)據(jù)庫(kù)連接,并保持長(zhǎng)連不斷開(kāi)。當(dāng)我們需要訪問(wèn)數(shù)據(jù)庫(kù)的時(shí)候,就去那一沓連接(俗稱(chēng)連接池)中拿來(lái)一個(gè)用,用完(對(duì)數(shù)據(jù)庫(kù)增刪改查完)后再把這條連接釋放到連接池中(依然不斷開(kāi))。這樣我們只在一開(kāi)始創(chuàng)建一沓數(shù)據(jù)庫(kù)連接時(shí)會(huì)有一些開(kāi)銷(xiāo),而這種開(kāi)銷(xiāo)總比頻繁的創(chuàng)建和銷(xiāo)毀連接小得多。
在 Node.js 中,我們可以使用 generic-pool 這個(gè)模塊幫助我們創(chuàng)建和管理數(shù)據(jù)庫(kù)連接池。
首先,在 package.json 中添加對(duì) generic-pool 的依賴(lài):
"generic-pool": "*"
并 npm install 安裝 generic-pool 模塊。
打開(kāi) db.js ,將:
module.exports = new Db(settings.db, new Server(settings.host, settings.port), {safe: true});
修改為:
module.exports = function() {
return new Db(settings.db, new Server(settings.host, settings.port), {safe: true, poolSize: 1});
}
這里我們導(dǎo)出一個(gè)函數(shù),每次調(diào)用該函數(shù)則創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)連接。
打開(kāi) post.js ,將:
var mongodb = require('./db'),
markdown = require('markdown').markdown;
修改為:
var Db = require('./db');
var markdown = require('markdown').markdown;
var poolModule = require('generic-pool');
var pool = poolModule.Pool({
name : 'mongoPool',
create : function(callback) {
var mongodb = Db();
mongodb.open(function (err, db) {
callback(err, db);
})
},
destroy : function(mongodb) {
mongodb.close();
},
max : 100,
min : 5,
idleTimeoutMillis : 30000,
log : true
});
以上就創(chuàng)建了一個(gè) mongodb 連接池,其中 name 指明該連接池的名字,create 指明創(chuàng)建一條數(shù)據(jù)庫(kù)連接的方法,并返回創(chuàng)建的連接,destroy 指明如何銷(xiāo)毀連接,max 指明連接池中最大連接數(shù),min 指明連接池中最小連接數(shù),idleTimeoutMillis 指明不活躍連接銷(xiāo)毀的毫秒數(shù),這里為 30000 即當(dāng)一條連接 30 秒處于不活躍狀態(tài)(即沒(méi)有被使用過(guò))時(shí)則銷(xiāo)毀該連接。log 指明是否打印連接池日志,這里我們選擇打印。
如何使用連接池呢?很簡(jiǎn)單。只需將所有:
mongodb.open(function (err, db) {
...
mongodb.close();
});
修改為:
pool.acquire(function (err, mongodb) {
...
pool.release(mongodb);
});
這里我們使用 pool.acquire 去連接池中獲取一條可用連接,使用完畢后通過(guò) pool.release 釋放該連接,而不是 close 掉。
讀者可自行完成剩余的修改工作。