【问题标题】:NestJS stops working after a few requestsNestJS 在几次请求后停止工作
【发布时间】:2020-10-19 18:47:20
【问题描述】:

我遇到了一个严重的问题。 NestJS 在几次请求后停止工作。我正在使用邮递员进行特定的 API 调用,然后,在对同一条路由发出不到 10 个请求后,它变得非常慢,而且我每次都从邮递员那里得到超时。


ma​​in.ts:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import {Logger} from '@nestjs/common'
import * as rateLimit from 'express-rate-limit';
import { WrapContentInterceptor } from './dashboard/dashboard.interceptors';
const PORT = 5000
const TAG = 'main'
async function bootstrap() {
  const logger = new Logger(TAG)
  const app = await NestFactory.create(AppModule);
  // app.useGlobalInterceptors(new WrapContentInterceptor())
  app.enableCors()
  await app.listen(PORT);
  app.use(
    rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minutes
      max: 1000, // limit each IP to 100 requests per windowMs
    }),
  );
  logger.log(`listening port::${PORT}`)
}
bootstrap();

我遇到问题的控制器:

// some regular imports
@Controller('dashboard')
@UseGuards(AuthGuard()) // protecting routes
export class DashboardController {
    constructor(
        private dashboardService:DashboardService,

    ){}
   // other routes

    @Get('/cockpit/general-numbers') // route that i'm getting the issue
    async getNumbersForCockpit(
        @Query('desiredDate',ParseStringToDatePipe) desiredDay?:Date
    ):Promise<GeneralNumbersForCockpit>{
        this.logger.log(`getNumbersForCockpit::${desiredDay.toISOString()}`)
        let installation = await this.dashboardService.getInstallationsOfDay(desiredDay?desiredDay:undefined)
        let averageTicket = await this.dashboardService.getAverageTicketPlanFromInterval(
            desiredDay?getFirstDayOfMonth(desiredDay):undefined,
            desiredDay?desiredDay:undefined
        )
            
        return {
            averageTicket:averageTicket,
            installation:installation.result
        }
    }
}

Ps:我意识到另一件事: 这个错误发生在我在服务层使用纯 SQL 原始到在 Docker 容器上运行的 MariaDB 数据库的路由中。 例如在服务层: ```
async getData(dateField:Date=new Date()):Promise<SimpleNumericalData>{
    // this.logger.debug(`f::dateField:${dateField}`)
    this.logger.debug(`getData::dateField:${dateField.toISOString()}`)
    const queryRunner = this.connection.createQueryRunner()
    let res = await queryRunner.manager.query(`
        select count(*) as result from my_table
        where my_field ='I'
        and DATE(date_field) = DATE('${dateField.toISOString()}')    
    `)
    //await this.connection.close()
    // this.logger.debug(`Result:${JSON.stringify(res)}`)
    return {
        result:Number(res[0]['result'])
    }
}

【问题讨论】:

  • 你确定不是你的限速中间件?
  • 把限速中间件拿出来看看还会不会出现。
  • 我尝试删除限制速率中间件,但在 6 到 10 次调用后仍然发生

标签: javascript typescript mariadb nestjs typeorm


【解决方案1】:

我猜您的问题来自您使用数据库连接的方式。你创建了大约 6 或 10 个到 db 的连接,但你没有释放它们,mariadb 的连接池的默认限制是 10(我猜)。

最后,新的请求想创建新的连接,但它达到了限制,新的请求等待另一个连接被释放,但它一直在等待。

在这种情况下,您可以扩展限制(不是根本原因,但我认为知道这一点很好)。

ormconfig.json(或您创建数据库配置的位置)中的extra 下添加connectionLimit

{
  ...,
  "extra": { connectionLimit: 10, ... }
}

More information

您必须在查询完成(成功或错误)后立即释放您刚刚在getData 函数中创建的新连接:

...
...
await queryRunner.release()

注意:当你的查询抛出错误时,请注意,你可以使用 try/catch/finally

...
    let res = await queryRunner.manager.query(`
        select count(*) as result from my_table
        where my_field ='I'
        and DATE(date_field) = DATE('${dateField.toISOString()}')    
    `).finally(() => queryRunner.release())
...

【讨论】:

  • 非常感谢您的支持,我用不同的方法解决了这个问题。我在我的服务中从 Typeorm 创建一个 Connection 对象,所以我从 Typeorm lib 更改为 getConnection 的方法来创建 queryRunner。通过这种方法:从“typeorm”导入 {Connection} 以从“typeorm”导入 {getConnection},并使用该函数中的 queryRunner。但是非常感谢,我不知道这个 connectionLimit 标志和这个解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-20
  • 1970-01-01
  • 1970-01-01
  • 2012-12-13
  • 2013-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多