nest+数据库连接在长时间无活动后重连

发布于:2024-10-15 ⋅ 阅读:(62) ⋅ 点赞:(0)

在使用 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/schedulecron 包:

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_timeoutinteractive_timeout 参数,或者 PostgreSQL 的 idle_in_transaction_session_timeout 参数。

通过以上方法,你可以有效地解决 NestJS 应用程序中数据库连接在长时间无活动后自动断开的问题。选择哪种方法取决于你的具体环境和需求。


网站公告

今日签到

点亮在社区的每一天
去签到