Node.js 服務連接 MongoDB 處理最佳實踐

關於如何處理 node.js 服務連接 MongoDB,我查閱了大量中英文資料,發現並沒有太適合我所期望的能力的方案,因此經過一番官方文檔的研究,總結了以下的連接 MongoDB 的方法(使用目前 Node.js 平臺最常用的 MongoDB ODM mongoose),斗膽稱之爲『最佳實踐』,希望能夠拋磚引玉,得到大家更專業的解答。
話不多說,先上代碼:

const mongoose = require('mongoose')
const config = require('./config')


if (process.env.NODE_ENV === 'development') {
  mongoose.set('debug', true)    /* A */
}

mongoose.set('bufferCommands', false)  /* B */

function connectMongoDB(address) {
  try {
    mongoose.connect(address, { 
      useNewUrlParser: true,
      bufferMaxEntries: 0   /* B */
      autoReconnect: true   /* C, default is true, you can ignore it */
      poolSize: 5           /* D, default is 5, you can ignore it */
    })
    
    const db = mongoose.connection
    db.on('error', (error) => {
      console.log(`MongoDB connecting failed: ${error}`)
    })
    db.once('open', () => {
      console.log('MongoDB connecting succeeded')
    })
    return db
  } catch (error) {
    console.log(`MongoDB connecting failed: ${error}`)
  }
}

const mongoInstance = connectMongoDB(config.database.mongo)
module.exports = {
    mongoInstance
}

這套連接方法能夠滿足以下需求,當然,這也是從我的服務需要滿足的需求中總結而來的:

  1. 開發環境下能夠打印詳細的數據庫操作信息
  2. 與數據庫斷開連接後,所有涉及到數據庫讀寫操作的命令均會立即返回錯誤,而不會等待重連進而造成接口超時
  3. 服務啓動併成功與數據庫建立連接後,如果數據庫出現問題造成連接中斷,服務會自動嘗試重連直到連接成功
  4. 無需手動處理連接數

我們逐條來看每個需求對應的配置:

  1. 見註釋 A,在開發環境中設置 'debug' 爲 true,數據庫將會把集合方法和參數打印到控制檯。
  2. 見兩處註釋 B,這裏貼一段 mongoose 文檔中對 bufferMaxEntries 的解釋:
bufferMaxEntries - The MongoDB driver also has its own buffering mechanism that kicks in when the driver is disconnected. Set this option to 0 and set bufferCommands to false on your schemas if you want your database operations to fail immediately when the driver is not connected, as opposed to waiting for reconnection.
核心意思就是將 bufferMaxEntries 設爲 0 同時將 bufferCommands 設爲 false,可以讓驅動在未連接到數據庫的時候,操作立即返回失敗,而不是一直在等待重連。個人認爲,這種方式相比一直等待數據庫重連直到響應超時體驗要更佳一點。
  1. 見註釋 C,這實際上是 mongoose 的默認設置,其連接數據庫時的 config 參數 autoReconnect 默認爲 true,其含義見文檔:
autoReconnect - The underlying MongoDB driver will automatically try to reconnect when it loses connection to MongoDB. Unless you are an extremely advanced user that wants to manage their own connection pool, do not set this option to false.
如果非高級用戶,就不要去改變這個參數了。
  1. 見註釋 D。對於 MongoDB 連接池的問題,建議是不要去手動處理。mongoose 自己會維護一個默認最大數量爲 5 的連接池,只有當你發現有一些慢查詢可能阻塞快查詢時才應該考慮增大 poolSize。當然,這個數字不能設置得過大,MongoDB 默認是一個連接啓動一個線程來服務,連接太多線程數切換系統開銷會很大。

當然,以上這套『最佳實踐』還存在一個不足:如果服務初次啓動後未能成功連接數據庫(比如數據庫此時處於宕機狀態),則服務不會嘗試重連數據庫。解決方法也不是沒有,就是比較雞肋:在 mongoose 連接的 'error' 事件監聽回調函數中嘗試重連。但是需要設置最大重試次數,否則會發生內存泄露。比較雞肋的原因是,如果首次連接沒有成功,短時間內嘗試重連幾次貌似也無濟於事。因此,使用這套連接方式務必要注意數據庫保持可連接狀態。或者讀者們如果有更好的解決方案,也希望能不吝賜教。

完。

本文首發於我的博客(點此查看),歡迎關注。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章