2020年12月8日 星期二

Important things for Node.js Serverless or general application use MySQL Connection

 這是職場觀察記,我多次看到了一些很神奇的 Node.js 連接 MySQL 寫法,最後在上線的時候,會在過一陣子後炸掉,甚至在 Serverless 中毀滅。


createConnection 的錯誤

問題其實不在 createConnection 本身,而是機器對 MySQL 連線之後,隔一段時間就會做 Connection Refuse,所以,給定下列 js code,可以看出淺在的風險:

const mysql = require('mysql')


const db = mysql.createConnection({
    host: 'localhost',
    user: '...',
    password: '...',
    database: '...',
})

db.connect(function (err) {
    if (err) {
        throw err
    }
    console.log('DB connection success')
})

global.db = db


然後對於使用 MVC 程式碼,大致上是這麼使用 剛才的 global db:


// Anonymous xxx function
exports.XXXXX = (req, res) => {
    db.query(`SELECT * FROM OOO- WHERE xxx = XXX`, (err, res) => {
        if (err) {
            console.log(err.message)
            return
        }
    })
}


然後,這個結果就是在上線啟動的數小時後,產生一些錯誤訊息:

events.js:292
      throw er; // Unhandled 'error' event
      ^
Error: read ECONNRESET
    at TCP.onStreamRead (internal/stream_base_commons.js:209:20)
Emitted 'error' event on Connection instance at:
...........................................
  errno: -104,
  code: 'ECONNRESET',
  syscall: 'read',
  fatal: true
---

此時,建議的解決方案,是把 global.db 換成 dbpool 作法:

:

const mysql = require('mysql')


const dbpool = mysql.createPool({
    host: 'localhost',
    user: '...',
    password: '...',
    database: '...',
})


global.dbpool = dbpool


然後,在使用上,可以這麼做:


// Anonymous xxx function
exports.XXXXX = (req, res) => {
    dbpool.getConnection((_err1, db) => { // 從池中撈出連線
      db.query(`SELECT * FROM OOO- WHERE xxx = XXX`, (err, res) => {
      	  db.release() // 如果沒有要繼續 query,就把連線 release
          if (err) {
              console.log(err.message)
              return
          }
      })
    })
}


需要注意的是 db.release 是在接下來沒有要繼續 query 的時候,要去做的連線重設,假如有多層的 db.query,記得要把 release 放在最後一個 callback 中。


不過在怎樣建議, export.XXXXX 應該要是使用 async 的做法,不過不在本文章討論範圍內。


AWS Serverless 連線問題

當使用第一個 createConnection 這種方法後,在 Deploy 到 AWS 會出現使用啟動 API 的前 6 秒會回應,之後就再也沒回應了,是因為 createConnection 在 connect 會直接卡住 runtime 6 秒,可是問題是 serverless 本身運作機制就不是給你卡 6 秒的,所以自然就會掛掉,那麼啟動 serverless 時,使用 pool 的方式,自然會是還可以的解決方案。 








沒有留言:

張貼留言

© Mac Taylor, 歡迎自由轉貼。
Background Email Pattern by Toby Elliott
Since 2014