Files
nxxmdata/backend/config/database-pool.js

270 lines
8.3 KiB
JavaScript
Raw Normal View History

/**
* 数据库连接池配置
* @file database-pool.js
* @description 配置和管理Sequelize数据库连接池
*/
const { Sequelize } = require('sequelize');
const { EventEmitter } = require('events');
const logger = require('../utils/logger');
const ormConfig = require('./orm-config');
// 从环境变量获取数据库连接参数
const DB_DIALECT = process.env.DB_DIALECT || 'mysql';
const DB_STORAGE = process.env.DB_STORAGE || './database.sqlite';
2025-09-12 20:08:42 +08:00
const DB_NAME = process.env.DB_NAME || 'nxxmdata';
const DB_USER = process.env.DB_USER || 'root';
2025-09-12 20:08:42 +08:00
const DB_PASSWORD = process.env.DB_PASSWORD || 'aiotAiot123!';
const DB_HOST = process.env.DB_HOST || '129.211.213.226';
2025-09-12 20:08:42 +08:00
const DB_PORT = process.env.DB_PORT || 9527;
// 数据库连接池事件发射器
class DatabasePoolEmitter extends EventEmitter {}
const poolEvents = new DatabasePoolEmitter();
// 默认连接池配置
const DEFAULT_POOL_CONFIG = {
max: parseInt(process.env.DB_POOL_MAX || '10'), // 最大连接数
min: parseInt(process.env.DB_POOL_MIN || '2'), // 最小连接数
acquire: parseInt(process.env.DB_POOL_ACQUIRE || '30000'), // 获取连接超时时间(毫秒)
idle: parseInt(process.env.DB_POOL_IDLE || '10000'), // 连接空闲多久后释放(毫秒)
evict: parseInt(process.env.DB_POOL_EVICT || '1000'), // 多久检查一次空闲连接(毫秒)
};
// 创建Sequelize实例
let sequelize;
if (DB_DIALECT === 'sqlite') {
sequelize = new Sequelize({
dialect: 'sqlite',
storage: DB_STORAGE,
logging: (msg) => logger.debug(msg),
benchmark: process.env.NODE_ENV !== 'production',
pool: DEFAULT_POOL_CONFIG,
define: ormConfig.defaultModelOptions
});
} else {
sequelize = new Sequelize(DB_NAME, DB_USER, DB_PASSWORD, {
host: DB_HOST,
port: DB_PORT,
dialect: DB_DIALECT,
logging: (msg) => logger.debug(msg),
benchmark: process.env.NODE_ENV !== 'production',
pool: DEFAULT_POOL_CONFIG,
define: ormConfig.defaultModelOptions,
dialectOptions: {
charset: 'utf8mb4',
supportBigNumbers: true,
bigNumberStrings: true,
dateStrings: true,
multipleStatements: process.env.DB_MULTIPLE_STATEMENTS === 'true'
},
timezone: '+08:00'
});
}
// 监听连接池事件 - 使用Sequelize实例的hooks
sequelize.addHook('afterConnect', (connection, config) => {
logger.info(`数据库连接已建立`);
poolEvents.emit('connect', connection);
});
sequelize.addHook('beforeDisconnect', (connection) => {
logger.info(`数据库连接即将断开`);
poolEvents.emit('disconnect', connection);
});
// 注意acquire和release事件在新版Sequelize中需要通过其他方式监听
// 这里我们使用定时器来监控连接池状态
setInterval(() => {
if (sequelize.connectionManager && sequelize.connectionManager.pool) {
const pool = sequelize.connectionManager.pool;
poolEvents.emit('poolStatus', {
size: pool.size || 0,
available: pool.available || 0,
using: pool.using || 0,
waiting: pool.waiting || 0
});
}
}, 30000); // 每30秒检查一次连接池状态
// 测试数据库连接
async function testConnection() {
try {
await sequelize.authenticate();
logger.info('数据库连接测试成功');
poolEvents.emit('connectionSuccess');
return { success: true, message: '数据库连接测试成功' };
} catch (error) {
logger.error('数据库连接测试失败:', error);
poolEvents.emit('connectionError', error);
return { success: false, message: error.message };
}
}
// 获取连接池状态
async function getPoolStatus() {
try {
const pool = sequelize.connectionManager.pool;
if (!pool) {
return { error: '连接池未初始化' };
}
// 获取连接池统计信息
const status = {
all: pool.size, // 所有连接数
idle: pool.idleCount, // 空闲连接数
used: pool.size - pool.idleCount, // 使用中的连接数
waiting: pool.pending, // 等待连接的请求数
max: pool.options.max, // 最大连接数
min: pool.options.min, // 最小连接数
acquire: pool.options.acquire, // 获取连接超时时间
idle: pool.options.idle, // 空闲超时时间
created: new Date().toISOString(), // 状态创建时间
utilization: (pool.size > 0) ? ((pool.size - pool.idleCount) / pool.size) * 100 : 0 // 利用率
};
poolEvents.emit('poolStatus', status);
return status;
} catch (error) {
logger.error('获取连接池状态失败:', error);
return { error: error.message };
}
}
// 监控连接池
async function monitorPool(interval = 60000) {
try {
const status = await getPoolStatus();
logger.debug('连接池状态:', status);
// 检查连接池利用率
if (status.utilization > 80) {
logger.warn(`连接池利用率过高: ${status.utilization.toFixed(2)}%`);
poolEvents.emit('highUtilization', status);
}
// 检查等待连接的请求数
if (status.waiting > 5) {
logger.warn(`连接池等待请求过多: ${status.waiting}`);
poolEvents.emit('highWaiting', status);
}
return status;
} catch (error) {
logger.error('监控连接池失败:', error);
return { error: error.message };
}
}
// 关闭连接池
async function closePool() {
try {
await sequelize.close();
logger.info('数据库连接池已关闭');
poolEvents.emit('poolClosed');
return { success: true, message: '数据库连接池已关闭' };
} catch (error) {
logger.error('关闭数据库连接池失败:', error);
return { success: false, message: error.message };
}
}
// 重置连接池
async function resetPool() {
try {
await closePool();
// 重新初始化连接池
sequelize.connectionManager.initPools();
// 测试新的连接池
const testResult = await testConnection();
if (testResult.success) {
logger.info('数据库连接池已重置');
poolEvents.emit('poolReset');
return { success: true, message: '数据库连接池已重置' };
} else {
throw new Error(testResult.message);
}
} catch (error) {
logger.error('重置数据库连接池失败:', error);
poolEvents.emit('poolResetError', error);
return { success: false, message: error.message };
}
}
// 优化连接池配置
async function optimizePool(config = {}) {
try {
// 获取当前状态
const currentStatus = await getPoolStatus();
// 计算新的配置
const newConfig = {
max: config.max || Math.max(currentStatus.max, Math.ceil(currentStatus.used * 1.5)),
min: config.min || Math.min(currentStatus.min, Math.floor(currentStatus.used * 0.5)),
acquire: config.acquire || currentStatus.acquire,
idle: config.idle || currentStatus.idle
};
// 确保最小连接数不小于1
newConfig.min = Math.max(newConfig.min, 1);
// 确保最大连接数不小于最小连接数
newConfig.max = Math.max(newConfig.max, newConfig.min);
// 应用新配置
await closePool();
// 更新连接池配置
sequelize.options.pool = newConfig;
// 重新初始化连接池
sequelize.connectionManager.initPools();
// 测试新的连接池
const testResult = await testConnection();
if (testResult.success) {
logger.info('数据库连接池已优化:', newConfig);
poolEvents.emit('poolOptimized', newConfig);
return { success: true, message: '数据库连接池已优化', config: newConfig };
} else {
throw new Error(testResult.message);
}
} catch (error) {
logger.error('优化数据库连接池失败:', error);
poolEvents.emit('poolOptimizationError', error);
return { success: false, message: error.message };
}
}
// 获取数据库表列表
async function getTablesList() {
try {
const [results] = await sequelize.query(
`SELECT TABLE_NAME FROM information_schema.TABLES
WHERE TABLE_SCHEMA = ?
ORDER BY TABLE_NAME`,
{ replacements: [DB_NAME] }
);
return results.map(row => row.TABLE_NAME);
} catch (error) {
logger.error('获取数据库表列表失败:', error);
return [];
}
}
// 导出模块
module.exports = {
sequelize,
testConnection,
getPoolStatus,
monitorPool,
closePool,
resetPool,
optimizePool,
getTablesList,
events: poolEvents
};