关于连接池的问题

关于连接池的问题

02:33左右老师说会爆内存,因为每次请求都会走dataSourceFactory,都会new 一个 DataSource,会创建数据库连接池

源码里真没对这块进行处理吗。。。不可能吧。。。不说多了,就并发几十个请求, 真这样一个再怎么普通的应用内存也早蹦了,
应该在new DataSource(options).initialize()里自己就做了dataSource的复用

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

2回答

已经处理了,在源码实现里面 dataSource 创建后是保存到一个提供者里面去了,提供者会被 nestjs 管理默认是一个单例对象,后面所有通过 @InjectRepository(实体类) 注入仓库操作数据库内部都是通过 inject(令牌) 来获取到这个单例连接对象来操作数据库的。这节完全不用看。

Brian 2024-06-01 11:24:27

你可以继续看,把视频看完~~


应该在new DataSource(options).initialize()里自己就做了dataSource的复用——明确的说,没有。


官方只是对单库或者多库的场景下,使用AppShutDown生命周期方法进行清理:


  async onApplicationShutdown(): Promise<void> {
    const dataSource = this.moduleRef.get<DataSource>(
      getDataSourceToken(this.options as DataSourceOptions) as Type<DataSource>,
    );
    try {
      if (dataSource && dataSource.isInitialized) {
        await dataSource.destroy();
      }
    } catch (e) {
      this.logger.error(e?.message);
    }
  }



下面是分析过程,1. typeorm的initialize,直接throw了,又没有返回实例,按照数据操作逻辑,应该是操作完成之后,自己断开,所以不需要维护。

https://img1.sycdn.imooc.com/climg/665a913a09d81af715671588.jpg


但是,现在人写代码比较“懒”,一般不会自己主动destroy或者connect,所以才需要加一个连接池来维护:


下面是nestjs/typeorm的 initialize:

https://img1.sycdn.imooc.com/climg/665a916b09ccc28d17761198.jpg

官方待办:移除“dataSource.initialize”条件(保留以支持向后兼容性)


        let dataSource: DataSource;
        if (!options.autoLoadEntities) {
          dataSource = await createTypeormDataSource(
            options as DataSourceOptions,
          );
        } else {
          let entities = options.entities;
          if (Array.isArray(entities)) {
            entities = entities.concat(
              EntitiesMetadataStorage.getEntitiesByDataSource(dataSourceToken),
            );
          } else {
            entities =
              EntitiesMetadataStorage.getEntitiesByDataSource(dataSourceToken);
          }
          dataSource = await createTypeormDataSource({
            ...options,
            entities,
          } as DataSourceOptions);
        }

你再像上看看 dataSource 这个变量是一个本地变量,只缓存了entites实体类,并没有缓存datasource。


每次都是在调用:

          dataSource = await createTypeormDataSource({
            ...options,
            entities,
          } as DataSourceOptions);


每次调用 createDataSourceFactory 都会根据提供的 optionsdataSourceFactory 生成一个新的或定制的 DataSource 实例


从哪里可以看出来 ?你可以连接一下数据库,看看连接池的变化就知道了~~~


参考Prisma部分的示例:https://class.imooc.com/lesson/3119#mid=78698


  • 完全没有必要,官方 dataSource 数据库连接对象是安排到一个提供者里面的,提供者默认都是单例被 nestjs 所管理。为什么 @InjectRepository 基于实体可以操作数据库?本质就是通过 Inject 拿到了那个数据源单例对象。一个数据源只能根据一个数据库配置对象来操作一个数据库,如果我有2个数据库,那一定有2套连接数据库的配置交给2个数据源来连接操作数据库。

    完全不需要自己手动来管理这个 DataSource 数据库连接对象, nestjs 已经单例化了

    请问描述的是否正确?

    8天前
  • // 定义一个 Nest 提供者(Provider),用于创建和提供 DataSource 实例const dataSourceProvider = {
      // 1. 令牌(Token):用于标识这个提供者,Nest 靠它来注入
      provide: getDataSourceToken(options as DataSourceOptions),
    
      // 2. 工厂函数:真正创建 DataSource 实例的地方
      //    这个函数 **只在应用启动时执行一次**,因为是单例 Provider
      useFactory: async (typeOrmOptions: TypeOrmOptions) => {
        // 判断是否配置了数据源名称(多数据源场景:mysql / postgres 区分)
        if (options.name) {
          // 如果有 name,把 name 合并到配置里
          return await this.createDataSourceFactory(
            {
              ...typeOrmOptions, // 数据库配置(host、port、user 等)
              name: options.name, // 数据源名称(多数据源必须)
            },
            options.dataSourceFactory, // 用户自定义的 dataSourceFactory(没有就是默认)
          );
        }
    
        // 3. 单数据源场景(没有配置 name)
        //    直接调用工厂,创建 DataSource 实例
        return await this.createDataSourceFactory(
          typeOrmOptions, // 数据库配置
          options.dataSourceFactory, // 用户传入的 dataSourceFactory(没有则用官方默认)
        );
      },
    
      // 4. 注入依赖:把 useFactory 需要的参数(数据库配置)注入进来
      //    这些配置来自你写的 useFactory 返回值
      inject: [TYPEORM_MODULE_OPTIONS],};


    8天前
  • 每次调用 createDataSourceFactory  的确是创建了一个 dataSource 数据库源,但这个工厂函数的调用时机是被 nestjs 所管理的成一个提供者的,单例无须担心有性能问题。一个数据库连接源根据一份配置连接并操作一个数据库。我建议优化一下吧

    8天前
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
前端高级工程师-大前端
  • 参与学习       324    人
  • 解答问题       408    个

全新打造“技术成长&职业破局”双高体系,深度打通“全栈 + 全流程 +多端+ 提效+AI赋能”,递进式锤炼思维与高阶技能,高效实现能力跃迁,助力成为“驾驭全局,深广兼备,打通多端全栈”的高级工程师

了解课程
请稍等 ...
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师