NestJS 请求范围的多租户支持,适用于多个数据库。

5
我希望使用NestJS 6的新请求注入范围功能实现多租户NestJS解决方案。
对于任何给定的服务,我认为我可以像这样做:
@Injectable({scope: Scope.REQUEST})
export class ReportService implements OnModuleInit { ... }

然后,在构造函数中,从请求中确定租户,连接到适当的数据库,并为新连接实例化存储库。
我在想这是否是最直接的方法?
而不是更新每个服务,是否有可能覆盖连接提供程序并将其范围限定为请求?
3个回答

12

以下是我们最终所做的事情...

  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);
  }

1
这适用于具有多个数据库的多租户,而不适用于具有多个模式的单个数据库。 - jdnichollsc
1
@jdnichollsc,它也可以处理多个模式,因为您在设置连接时还可以更改模式。 - Felix K.
1
@WinterTime,当您调用getConnection时,需要传递所有数据库连接细节,请参阅TypeORM API文档。在nurikabe的代码中,他似乎只传递了租户ID“string”,这是错误的,他需要在此处传递整个连接配置,例如将方案或数据库名称设置为租户。 - Felix K.
@jdnichollsc 当使用 createConnection (为租户创建连接)时,TypeORM 在幕后存储连接实例,并且对 getConnection(和工厂)的后续调用将再次返回相同的连接实例,因此您只需一次创建连接,而不是在每个请求中都创建连接。因此,您每个租户只需创建一个连接,而不是每个请求都创建连接。但是,您可能会遇到单个服务器上有太多连接的内存问题,不幸的是,无法为现有连接切换模式(请参见 https://dev59.com/clMH5IYBdhLWcg3w9mB9)。 - Felix K.
1
@B12Toaster,在调用getConnection(tenat)按名称获取连接之前,我必须加载所有连接设置的哪个点。我不理解这部分。 - Ger
显示剩余5条评论

3
我建议使用@nurikabe的方法,使用请求范围的工厂提供程序和请求范围的服务。Nestjs本身在文档中也有一个类似的工厂示例 但为了完整起见,还有另一种方法:您也可以使用中间件并将连接附加到请求对象上,如此答案所述,与类似的问题。但是,通过中间件连接诸如连接之类的东西来绕过DI机制,并使请求对象像交付连接的服务容器一样行事,因此应首选工厂方法。

0

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

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

使用多模式方法之一的完整文档记录在this article中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接