多数据库连接管理
多数据库连接管理
Mongoose作为Node.js中最流行的MongoDB ODM,提供了灵活的多数据库连接机制。实际项目中经常需要同时操作多个数据库实例,比如主从分离、分片集群或跨业务数据库访问等情况。
基本连接配置
创建单个数据库连接是基础场景,Mongoose通过mongoose.connect()
实现:
const mongoose = require('mongoose');
const mainDB = mongoose.createConnection('mongodb://localhost:27017/main');
mainDB.on('connected', () => {
console.log('Main DB connected');
});
mainDB.on('error', (err) => {
console.error('Main DB connection error:', err);
});
多数据库连接则需要创建多个独立的connection实例。每个connection维护自己的连接池、模型定义和事务状态:
const userDB = mongoose.createConnection('mongodb://localhost:27017/users');
const productDB = mongoose.createConnection('mongodb://localhost:27017/products');
连接池优化
Mongoose默认每个连接池大小为5,高并发场景需要调整:
const options = {
poolSize: 10, // 连接池大小
bufferMaxEntries: 0, // 禁用缓冲
connectTimeoutMS: 30000,
socketTimeoutMS: 45000
};
const analyticsDB = mongoose.createConnection(
'mongodb://cluster1.example.com:27017/analytics',
options
);
不同业务场景建议采用差异化配置:
- 高频查询:增大poolSize
- 批量写入:保持较小poolSize但增加timeout
- 报表数据库:设置readPreference=secondaryPreferred
模型绑定机制
在多数据库环境下,模型必须绑定到特定connection:
// 错误做法 - 模型会绑定到默认mongoose实例
// const User = mongoose.model('User', userSchema);
// 正确做法
const User = userDB.model('User', userSchema);
const Product = productDB.model('Product', productSchema);
动态模型注册方案:
function createModel(conn, modelName, schema) {
if (conn.models[modelName]) {
return conn.models[modelName];
}
return conn.model(modelName, schema);
}
const Order = createModel(orderDB, 'Order', orderSchema);
跨数据库事务
MongoDB 4.2+支持跨库事务,但需要特殊处理:
const session = await mainDB.startSession();
session.startTransaction();
try {
const user = await User.create([{ name: 'Alice' }], { session });
await Product.updateOne(
{ sku: '123' },
{ $inc: { stock: -1 } },
{ session: session }
);
await session.commitTransaction();
} catch (error) {
await session.abortTransaction();
throw error;
} finally {
session.endSession();
}
连接状态监控
生产环境需要实时监控各连接状态:
function monitorConnections() {
const connections = [mainDB, userDB, productDB];
connections.forEach(conn => {
console.log(`${conn.name} state:`, conn.readyState);
// 0: disconnected
// 1: connected
// 2: connecting
// 3: disconnecting
});
}
setInterval(monitorConnections, 60000);
故障处理策略
网络波动时的重连机制:
function setupReconnect(conn, url) {
conn.on('disconnected', () => {
console.log(`Disconnected from ${conn.name}`);
setTimeout(() => conn.openUri(url), 5000);
});
}
setupReconnect(userDB, 'mongodb://localhost:27017/users');
多租户架构实现
SaaS应用中常见的多租户方案:
class TenantManager {
constructor() {
this.tenantConnections = new Map();
}
getTenantDB(tenantId) {
if (this.tenantConnections.has(tenantId)) {
return this.tenantConnections.get(tenantId);
}
const conn = mongoose.createConnection(
`mongodb://cluster.example.com/${tenantId}`,
{ maxPoolSize: 5 }
);
this.tenantConnections.set(tenantId, conn);
return conn;
}
}
性能优化技巧
- 连接预热:
async function warmupConnection(conn) {
await conn.collection('test').findOne({});
}
- 读写分离配置:
const readReplica = mongoose.createConnection('mongodb://replica1.example.com,replica2.example.com/db', {
readPreference: 'secondary',
replicaSet: 'rs0'
});
- 连接生命周期管理:
process.on('SIGINT', async () => {
await Promise.all([
mainDB.close(),
userDB.close(false), // forceClose=false
productDB.close(true) // forceClose=true
]);
process.exit(0);
});
测试环境策略
自动化测试中的隔离方案:
beforeEach(async () => {
testDB = mongoose.createConnection(
'mongodb://localhost:27017/test',
{ poolSize: 1 }
);
await testDB.dropDatabase();
});
afterEach(async () => {
await testDB.close();
});
配置最佳实践
推荐的生产环境配置模板:
const productionConfig = {
autoIndex: false, // 生产环境禁用自动索引
bufferCommands: false, // 禁用缓冲
connectTimeoutMS: 30000,
socketTimeoutMS: 45000,
family: 4, // 强制IPv4
keepAlive: true,
keepAliveInitialDelay: 300000,
maxPoolSize: 10,
minPoolSize: 2,
retryReads: true,
retryWrites: true,
serverSelectionTimeoutMS: 5000,
heartbeatFrequencyMS: 10000
};
const prodDB = mongoose.createConnection(
'mongodb+srv://prod.example.com/main',
productionConfig
);
高级连接模式
- 动态路由连接:
function routeConnection(user) {
return user.region === 'EU' ?
euDB :
asiaDB;
}
- 连接代理模式:
class DBProxy {
constructor() {
this.primary = primaryDB;
this.secondary = secondaryDB;
}
query(options) {
return options.readOnly ?
this.secondary :
this.primary;
}
}
- 混合云连接方案:
const hybridDB = mongoose.createConnection([
'mongodb://on-premise.example.com:27017/db',
'mongodb://cloud-cluster.example.com:27017/db'
], {
replicaSet: 'hybridSet',
readPreference: 'nearest'
});
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:处理连接错误与重连机制
下一篇:全局配置与最佳实践