在使用 NestJS 开发应用程序时,如果遇到数据库连接在长时间无活动后自动断开的问题,可以采取几种策略来解决这个问题。以下是一些常见的方法:
1. 使用连接池
NestJS 通常与 TypeORM 或 Sequelize 等 ORM 工具一起使用,这些工具都支持连接池。你可以配置连接池以保持连接活跃。
TypeORM 配置
如果你使用的是 TypeORM,可以在 ormconfig.json
或 .env
文件中配置连接池选项。例如:
{
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "your_username",
"password": "your_password",
"database": "your_database",
"synchronize": true,
"logging": false,
"pool": {
"max": 10, // 最大连接数
"min": 2, // 最小连接数
"idleTimeoutMillis": 30000, // 连接空闲超时时间(毫秒)
"acquireTimeoutMillis": 60000, // 获取连接的超时时间(毫秒)
"createRetryIntervalMillis": 100, // 创建连接的重试间隔(毫秒)
"connectionLimit": 10 // 连接限制
}
}
Sequelize 配置
如果你使用的是 Sequelize,可以在配置文件中设置连接池选项。例如:
import { Sequelize } from 'sequelize';
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
dialect: 'mysql',
pool: {
max: 10, // 最大连接数
min: 0, // 最小连接数
acquire: 30000, // 获取连接的超时时间(毫秒)
idle: 10000 // 连接空闲超时时间(毫秒)
}
});
2. 发送心跳查询
通过定期发送心跳查询来保持连接活跃。你可以在 NestJS 中使用定时任务来实现这一点。
使用 @nestjs/schedule
模块
首先安装 @nestjs/schedule
和 cron
包:
npm install @nestjs/schedule cron
然后在你的模块中导入 ScheduleModule
并配置一个定时任务:
import { Module, OnApplicationBootstrap } from '@nestjs/common';
import { ScheduleModule, CronExpression } from '@nestjs/schedule';
import { DataSource } from 'typeorm'; // 如果使用 TypeORM
@Module({
imports: [ScheduleModule.forRoot()],
})
export class AppModule implements OnApplicationBootstrap {
constructor(private dataSource: DataSource) {}
onApplicationBootstrap() {
this.dataSource.query('SELECT 1'); // 初始心跳
}
@Cron(CronExpression.EVERY_5_MINUTES)
handleCron() {
this.dataSource.query('SELECT 1').then(() => {
console.log('Heartbeat sent to the database');
}).catch((err) => {
console.error('Failed to send heartbeat to the database:', err);
});
}
}
3. 应用程序级别的重连机制
在应用程序级别添加重连机制,当检测到连接断开时自动重新建立连接。这通常需要捕获异常并尝试重新连接。
你可以在服务层或中间件中添加重连逻辑:
import { Injectable, OnModuleInit } from '@nestjs/common';
import { DataSource } from 'typeorm';
@Injectable()
export class DatabaseService implements OnModuleInit {
private reconnectAttempts = 0;
private maxReconnectAttempts = 5;
constructor(private dataSource: DataSource) {}
async onModuleInit() {
await this.dataSource.initialize();
this.dataSource.on('error', (err) => this.handleConnectionError(err));
}
private async handleConnectionError(err: any) {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
console.error(`Database connection error: ${err.message}. Attempting to reconnect...`);
await this.dataSource.destroy();
await this.dataSource.initialize();
this.reconnectAttempts = 0; // 重置重连尝试次数
} else {
console.error(`Max reconnect attempts reached. Exiting...`);
process.exit(1); // 或者其他处理方式
}
}
}
4. 调整数据库服务器配置
如前所述,你也可以调整数据库服务器的配置,例如 MySQL 的 wait_timeout
和 interactive_timeout
参数,或者 PostgreSQL 的 idle_in_transaction_session_timeout
参数。
通过以上方法,你可以有效地解决 NestJS 应用程序中数据库连接在长时间无活动后自动断开的问题。选择哪种方法取决于你的具体环境和需求。