2013年11月27日

Keep MongoDB connection in nodejs 筆記

因為是小 project 使用 native mongodb nodejs driver
首先,使用新的 MongoClient 取代 Db
雖然範例裡面都有乖乖 db.close() ,但是其實不需要這樣,
更好的方法是持續這個 mongodb connection ,並且讓需要 mongodb 的部分共用同一個 connection。
一開始我的寫法類似範例裡的方式
mongo = require '\mongodb' mongoClient = mongodb.MongoClient mongodbURI = 'mongodb://127.0.0.1:27017/test' route.get '/abc', (req, res) -> mongoClient.connect mongodbURI, (err, db) -> throw err if err db.collection('abc').insert({foo:'bar'}, (err, result) -> throw err if err console.log "succes insert abc" db.close() ) 這樣的配置 nginx - nodejs - mongodb 在第二天大量流量進來的時候會噴發
nginx: connect() failed (111: Connection refused) while connecting to upstream [Error: failed to connect to [localhost:27017]] 這個跟 localhost 或是 127.0.0.1 無關
由於 process 結束會自動斷掉 connection ,以下嘗試拿掉 db.close()
route.get '/abc', (req, res) -> mongoClient.connect mongodbURI, (err, db) -> throw err if err db.collection('abc').insert({foo:'bar'}, (err, result) -> throw err if err console.log "succes insert abc" ) 這樣 mongodb 會自動處理 mongo connection ,但是量大的時候依然會噴發 [initandlisten] connection accepted from 127.0.0.1:41822 #277824 (7998 connections now open) 失去 nginx - nodejs 可以處理 C10K problem 的優勢
嘗試改成一開始就建立 mongodb connection 並且不關閉,
使用mongodb 預設 maxPoolSize=5 mongoClient.connect mongodbURI, (err, db) -> throw err if err route.get '/abc', (req, res) -> db.collection('abc').insert({foo:'bar'}, (err, result) -> throw err if err console.log "succes insert abc" ) route.get '/def', (req, res) -> db.collection('def').insert({foo:'bar'}, (err, result) -> throw err if err console.log "succes insert def" ) 以上處理上千個併發沒問題, mongodb 會自動處理 connection pool,只需要依需求調整 maxPoolSize
實際上可以把 mongodb 提出來
mongo.coffee mongodb = require 'mongodb' mongoClient = mongodb.MongoClient mongodbURI = 'mongodb://127.0.0.1:27017/test' module.exports.init = (callback) -> mongoClient.connect mongodbURI, (err, db) -> console.log err if err console.log 'opened mongodb connection' callback(err, db)
server.coffee mongo.init (err, db) -> throw err if err ...
順代一提,Apache Benchmark ab test 連線數量多的時候連線數量並不準確,
像是 -n 1000 -c 10 可能實際上送了 1007 次 request 之類的