【问题标题】:NestJS Request Scoped Multitenancy for Multiple DatabasesNestJS 请求多个数据库的范围多租户
【发布时间】:2019-10-28 05:01:26
【问题描述】:

希望使用 NestJS 6 的新请求注入范围功能实现多租户 NestJS 解决方案。

对于任何给定的服务,我认为我可以这样做:

@Injectable({scope: Scope.REQUEST})
export class ReportService implements OnModuleInit { ... }

然后,在构造函数中,根据请求确定租户,连接到适当的数据库,并为新连接实例化存储库。

我想知道这是否是最直接的方法?

除了更新每个服务之外,是否可以将连接提供者和范围 覆盖到请求中?

【问题讨论】:

    标签: multi-tenant nestjs


    【解决方案1】:

    这就是我们最终要做的......

    1. 创建一个简单的全局TenancyModule 绑定到请求范围:

    tenancy.module.ts

    import { Global, Module, Scope } from '@nestjs/common';
    import { REQUEST } from '@nestjs/core';
    import { getConnection } from 'typeorm';
    
    const connectionFactory = {
      provide: 'CONNECTION',
      scope: Scope.REQUEST,
      useFactory: (req) => {
        const tenant = someMethodToDetermineTenantFromHost(req.headers.host);
        return getConnection(tenant);
      },
      inject: [REQUEST],
    };
    
    @Global()
    @Module({
      providers: [connectionFactory],
      exports: ['CONNECTION'],
    })
    export class TenancyModule {}
    
    1. 将特定请求的'CONNECTION' 注入模块服务,从中检索存储库:

    user.service.ts

    ...
    @Injectable({scope: Scope.REQUEST})
    export class UserService {
      private readonly userRepository: Repository<User>;
    
      constructor(@Inject('CONNECTION') connection) {
        this.userRepository = connection.getRepository(User);
      }
    

    【讨论】:

    • 这适用于具有多个数据库的多租户,不适用于具有多个架构的一个数据库
    • 我缺少有关连接本身的部分,您能否提供示例何时传递数据库连接详细信息?例如。租户 = 同一主机中的不同数据库。 @nurikabe
    • @jdnicholllsc,它也适用于多个架构,因为您还可以在设置连接时更改架构。
    • @WinterTime 您在调用 getConnection 时传递了所有数据库连接详细信息,请参阅 TypeORM API 文档。在 nurikabe 的代码中,他似乎只是在传递租户 ID“字符串”,这是错误的,他需要在此处传递整个连接配置,例如方案或数据库名称设置为租户..
    • @B12Toaster 在什么时候我必须加载所有连接设置才能调用 getConnection (tenat) 以按名称获取连接。这部分我没看懂
    【解决方案2】:

    我建议将@nurikabe 的方法与请求范围工厂提供程序和请求范围服务一起使用。 Nestjs 本身也有类似的工厂示例in the docs

    但为了完整起见,还有另一种方法:您也可以使用中间件并将连接附加到请求对象,如this answer 中所述,类似问题。但是,通过中间件将连接之类的东西附加到请求是绕过 DI 机制,并通过使其行为类似于提供连接的服务容器来疏远请求对象 - 因此应该首选工厂方法。

    【讨论】:

      【解决方案3】:

      最好将连接作为提供者(来自工厂)注入,而不是将其附加到请求中。

      请注意,这两种方法都将不可避免地导致正在创建的连接数量增加。这可能会导致性能问题,即使使用连接池也是如此。因此,这种方法(每个租户一个连接)只有在租户数量相对较少时才真正有效。

      this article 中完整记录了使用多模式方法的一种方法。

      【讨论】:

        猜你喜欢
        • 2021-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多