用例
在基于模式的多租户应用程序中,通常有一个具有多模式的数据库。一个模式是存储公共应用程序数据的主模式,一个是应用程序的每个租户的模式。每次向系统注册新客户时,都会在数据库中自动创建新的孤立架构。这意味着,架构是在运行时创建的,事先不知道。客户的架构是根据客户的域命名的。当请求进入系统时,将验证用户,并使用主架构上的数据选择架构。然后,大多数/所有后续数据库操作都转到特定于租户的模式。如您所见,我们想要使用的架构只有在运行时才知道。
问题
如何在运行时选择模式?我们正在使用postgres连接器。我们应该能够在运行时切换模式。
另一个问题是如何为不同的租户进行移民?
备注:
需要以请求作用域的方式设置db-模式,以避免为可能属于其他客户的其他请求设置模式。为整个连接设置架构不是一个选项。
发布于 2020-04-01 12:37:35
您可以在运行时创建DefaultCrudRepository ( CRUD存储库的默认实现,使用遗留的杂耍模型和数据源),这需要两个参数。
现在实例化具有所需设置的Datasource,包括要使用的模式,然后向DefaultCrudRepository实例提供模型和数据源,如下所示:
const ds = new PostgresDataSource({
connector: 'postgresql',
host: 'some host',
port: 'some port',
user: 'some user',
password: 'password',
database: 'database',
schema: 'schema for that particular tenant',
});
const repo = new DefaultCrudRepository(SomeModel, ds);
然后使用这个存储库执行find、create和其他方法。这个https://github.com/hitesh2067/dynamic-schema-example有一个示例实现
我已将模式作为查询param传递,但您可以使用任何其他方式提供模式。
更新的解决方案:-
现在回收站已经为应用程序上下文和请求上下文提供了中间件和更好的上下文分离。我们可以使用它动态地连接到任何数据源(希望在package.json中安装了连接器),并将其绑定到应用程序上下文中,然后将该绑定临时绑定到数据源,该数据源是由UserRepository (或您的多租户Repo)在请求上下文中指出的。
这方面的示例写在https://github.com/dev-hitesh-gupta/loopback4-multi-tenant-multi-datasource-example上
执行就像
const tenant = await this.getTenant(requestCtx);
if (tenant == null) return;
const tenantData = await this.tenantRepo.findById(tenant.id);
requestCtx.bind(CURRENT_TENANT).to(tenantData);
const tenantDbName = `datasources.multi-tenant-db.${tenantData.id}`;
// adding datasource if not present
if (!this.application.isBound(tenantDbName)) {
const tenantDb = new juggler.DataSource({
name: tenantDbName,
...tenantData.dbConfig,
});
this.application.bind(tenantDbName).to(tenantDb).tag('datasource');
}
// Pointing to a default datasource in request context
requestCtx
.bind('datasources.multi-tenant-db')
.toAlias(tenantDbName);发布于 2020-04-07 08:33:21
LoopBack团队的大家好
LoopBack 4还没有为多租户提供一流的支持。我打开了一个GitHub问题来讨论不同的可能解决方案,参见回环-下一个#5056。
一种选择是调整特定于模型的Repository类,以基于当前用户设置模式。这就需要在@loopback/repository中实现一个小的增强,因此这个解决方案目前还无法实现。我正在交叉张贴的相关部分,我的意见如下,见GitHub问题的完整上下文。
使用模式的轻量级租户隔离
在此设置中,身份验证层和所有租户共享相同的数据库名称,并使用相同的凭据(数据库用户)访问数据。我们在数据库中定义了1+N模式:第一个模式由身份验证层使用,另外我们为每个租户提供了一个模式。所有数据库查询都将使用相同的LB数据源,从而共享相同的连接池。
就实现而言,我们需要调整LB4模型在数据源中的注册方式。与其为所有用户创建相同的后台杂耍模型,我们还希望创建特定于租户的杂耍模型。
从概念上讲,这可以通过调整Repository构造函数来实现。
export class ProductRepository extends DefaultCrudRepository<
Product,
typeof Product.prototype.id
> {
constructor(
@inject('datasources.db') dataSource: juggler.DataSource,
@inject(SecurityBindings.USER) currentUser: UserProfile,
) {
super(
// model constructor
Product,
// datasource to use
dataSource,
// new feature to be implemented in @loopback/repository:
// allow repository users to overwrite model settings
{schema: currentUser.name},
);
}
}https://stackoverflow.com/questions/60680275
复制相似问题