如何在Express框架下每次请求后关闭MySQL连接?
优化Express+MySQL连接管理的最佳实践
嘿,我看到你现在的Express路由结构是这样的:
import express from 'express'; import health from './health'; import surface from './surface'; const router = express.Router(); router.use('/health', health); router.use('/surface', surface); router.get('*', (req, res) => { res.status(404); res.json({ message: 'Unknown API endpoint' }); }); export default router;
而且每个子路由里都是单独创建MySQL连接,在res.send()前关闭——这种做法虽然能保证连接不泄漏,但在高并发场景下性能拉胯,还容易出问题。我来给你分享下更专业的做法:
换用连接池才是正确姿势
MySQL官方包本身就支持连接池,简单说就是预先创建一批连接放在“池子”里,请求过来时拿一个用,用完放回池子,不用直接销毁。这样能大幅降低连接创建销毁的开销,还能控制并发连接数,避免把数据库打崩。
第一步:单独整个数据库连接池模块
新建个db.js文件,专门管理连接池:
import mysql from 'mysql'; // 配置你的数据库信息,记得换成自己的 const pool = mysql.createPool({ host: '你的数据库地址', user: '数据库用户名', password: '数据库密码', database: '要连接的库名', connectionLimit: 10, // 池子最多放10个连接,根据服务器配置调整 waitForConnections: true, // 没连接时等着,别直接报错 queueLimit: 0 // 等待队列不限长,按需调整 }); export default pool;
第二步:子路由里复用连接池
比如修改你的health.js,不用每次新建连接了:
import express from 'express'; import pool from './db'; // 举个health路由的例子 export default express.Router().get('/', (req, res) => { // 从池子拿连接 pool.getConnection((err, connection) => { if (err) { return res.status(500).json({ message: '拿数据库连接失败', error: err }); } // 执行你的SQL查询 connection.query('SELECT 1 AS health_check', (queryErr, results) => { // 重点!用完一定要把连接放回池子,不然池子会被掏空 connection.release(); if (queryErr) { return res.status(500).json({ message: '数据库查询炸了', error: queryErr }); } res.json({ message: 'API健康', db_status: '正常', data: results }); }); }); });
第三步:原主路由文件不用改
你原来的主路由代码完全可以保留,因为我们只是替换了子路由内部的数据库连接逻辑。
为啥不推荐每次创建销毁连接?
- 性能浪费:每次创建TCP连接要三次握手,销毁要四次挥手,高并发下这些开销会让接口响应慢到离谱。
- 连接数爆了:如果突然来了几百个请求,每个都新建连接,很容易超过MySQL的
max_connections配置,直接导致新请求连不上数据库。
额外小技巧:用Async/Await简化代码
如果你讨厌回调嵌套,可以用Node的util.promisify把MySQL的回调API转成Promise风格,写起来更清爽:
import express from 'express'; import util from 'util'; import pool from './db'; // 把getConnection和query转成Promise const getConn = util.promisify(pool.getConnection).bind(pool); const runQuery = util.promisify(pool.query).bind(pool); export default express.Router().get('/', async (req, res) => { try { // 直接用await执行查询,连释放连接都不用管——runQuery会自动处理 const results = await runQuery('SELECT 1 AS health_check'); res.json({ message: 'API健康', db_status: '正常', data: results }); } catch (err) { res.status(500).json({ message: '出问题了', error: err.message }); } });
内容的提问来源于stack exchange,提问作者Dave Stein
相关产品推荐
相关产品推荐

