VonaJS多租户同时支持共享模式和独立模式
多实例/多租户
VonaJS 通过多实例的概念来支持多租户 SAAS 系统的开发。只需启动一个后端服务,即可支持多个实例同时运行
VonaJS 支持以下几种多实例/多租户模式:
共享模式:多个实例共享同一个数据库,通过实例Id字段隔离多实例之间的数据独立模式:每个实例都使用独立的数据库,从而满足大数据量的业务需求混合模式:在一个系统中同时支持共享模式和独立模式,从而可以精确指定某个实例使用共享数据库还是独立数据库
实例配置
1. 测试环境、开发环境
在测试环境和开发环境中,系统默认提供了一个缺省实例。同时提供了两个测试实例,用于演示如何使用共享模式和独立模式:
src/backend/config/config/config.test.ts
src/backend/config/config/config.dev.ts
// instances
config.instances = [
{ name: '', password: '', title: '', config: {} },
{ name: 'shareTest', password: '', title: '' },
{ name: 'isolateTest', password: '', title: '', id: 1000, isolate: true, isolateClient: 'isolateTest' },
];
- 实例清单
| 名称 | 说明 |
|---|---|
| empty | 缺省实例 |
| shareTest | 用于演示共享模式,具体而言,shareTest与empty共享同一个数据库 |
| isolateTest | 用于演示独立模式,具体而言,isolateTest使用独立的数据库 |
- 实例属性
| 名称 | 说明 |
|---|---|
| name | 实例名 |
| password | 实例中用户admin的初始密码,默认是123456 |
| title | 网站标题 |
| config | 实例的配置信息 |
| id | 当使用独立模式时,必须明确指定唯一的实例Id |
| isolate | 是否使用独立模式,默认为共享模式 |
| isolateClient | 当使用独立模式时,必须明确指定数据源 |
2. 生产环境
在生产环境,需要自行配置实例信息
src/backend/config/config/config.prod.ts
config.instances = [
{ name: '', password: '', title: '', config: {} },
{ name: 'vona', password: '', title: '', config: {} },
];
如何添加新实例
下面以实例shareTest为例,演示如何添加新实例:
1. 添加类型定义
src/backend/config/config/config.ts
declare module 'vona' {
export interface IInstanceRecord {
shareTest: never;
}
}
- 采用接口合并机制添加新实例的类型定义
2. 增加实例配置
在需要的 config 文件中添加实例配置,比如在测试环境配置新实例:
src/backend/config/config/config.test.ts
// instances
config.instances = [
{ name: 'shareTest', password: '', title: '' },
];
- 对于
独立模式,还需要配置数据源,此处从略
获取当前实例名的规则
当用户访问后端 Api 时,后端会自动根据规则获取当前实例名,然后根据实例名获取实例信息
1. 模块配置
多实例是由模块 a-instance 提供的核心能力,可以在 App config 中修改模块的配置:
src/backend/config/config/config.prod.ts
// modules
config.modules = {
'a-instance': {
getInstanceName: undefined,
headerField: 'x-vona-instance-name',
queryField: 'x-vona-instance-name',
},
};
| 名称 | 说明 |
|---|---|
| getInstanceName | 提供自定义函数,用于获取当前实例名 |
| headerField | 从request header中获取当前实例名,header key默认为x-vona-instance-name |
| queryField | 从request query中获取当前实例名,query key默认为x-vona-instance-name |
2. 规则次序
系统按以下次序,依次判断当前实例名,当获取到实例名时则停止判断流程
- 如果提供了
getInstanceName,则调用此函数 - 如果
queryField不为空,则从 request query 中获取 - 如果
headerField不为空,则从 request header 中获取 - 从域名中解析实例名
3. 如何从域名中解析实例名
比如,域名为https://cabloy.com,那么对应的实例名是cabloy。可以通过配置SERVER_SUBDOMAINOFFSET来修改计算规则
env/.env
# server
SERVER_SUBDOMAINOFFSET = 1
- 当
SERVER_SUBDOMAINOFFSET = 1时,域名与实例名对应关系如下:
| 域名 | 实例名 |
|---|---|
| cabloy.com | cabloy |
| store.cabloy.com | cabloy.store |
- 当
SERVER_SUBDOMAINOFFSET = 2时,域名与实例名对应关系如下:
| 域名 | 实例名 |
|---|---|
| cabloy.com | 空字符串 |
| store.cabloy.com | store |
使用多实例
1. 访问当前实例信息
// 当前实例名
const name = this.ctx.instanceName;
// 当前实例对象
const instance = this.ctx.instance;
// 当前实例Id
const iid = this.ctx.instance.id;
2. 使用Model操作数据库
由于多实例的数据是相互隔离的,因此在操作数据库时,需要指定实例Id。VonaJS 提供了非常强大的Model对象,从而可以透明的处理多实例
// create
await this.scope.model.student.insert({ name: 'Tom' });
// select
await this.scope.model.student.select();
// get
await this.scope.model.student.get({ id: 1 });
// update
await this.scope.model.student.update({ id: 1, name: 'Jimmy' });
// delete
await this.scope.model.student.delete({ id: 1 });
当我们使用 Model student操作数据时,系统会自动设置实例Id
3. 使用Query Builder操作数据库
如果使用builder()方法操作数据库,就需要自行添加实例Id
await this.scope.model.student.builder().where({
iid: this.ctx.instance.id,
name: 'Tom',
});
如果使用builderSelect()方法操作数据库,系统会自动添加实例Id
await this.scope.model.student.builderSelect().where({
name: 'Tom',
});
4. 使用原生Sql操作数据库
如果使用原生Sql操作数据库,就需要自行添加实例Id
await this.scope.model.student.query(
'select * from demoStudent where iid=?',
[this.ctx.instance.id],
);
await this.scope.model.student.queryOne(
'select * from demoStudent where iid=? and id=?',
[this.ctx.instance.id, 1],
);
Vona ORM已开源:https://github.com/vonajs/vona
VonaJS多租户同时支持共享模式和独立模式的更多相关文章
- 使用共享网卡的NAT模式配置VMware中的CentOS的上网功能
昨天写了一篇文章总结了前两天折腾VMware 10中的CentOS上网的问题,结果留下一下小瑕疵,就是视频教程中通过共享网卡使用NAT模式配置虚拟机的方法.今天在结合昨天的基础上终于弄明白了这个问题. ...
- Java设计模式(5)共享模式/享元模式(Flyweight模式)
Flyweight定义:避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类). 为什么使用共享模式/享元模式 面向对象语言的原则就是一切都是对象,但是如果真正使用起来,有时对象数可 ...
- Uber CEO博鳌论坛采访:看好中国市场共享经济的发展模式
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 如何使用共享网卡的NAT模式配置VMware12中的CentOS6.7的上网功能
1.首先共享网卡的NAT模式是通过win10中的VMnet8来通信的,如下双击VMnet8 2.点击[详细信息]查看VMnet8的IPV4地址为192.168.232.110,掩码为255.255.2 ...
- ASM:《X86汇编语言-从实模式到保护模式》第16章:Intel处理器的分页机制和动态页面分配
第16章讲的是分页机制和动态页面分配的问题,说实话这个一开始接触是会把人绕晕的,但是这个的确太重要了,有了分页机制内存管理就变得很简单,而且能直接实现平坦模式. ★PART1:Intel X86基础分 ...
- WCF实例上下文模式与并发模式对性能的影响
实例上下文模式 InstanceContextMode 控制在响应客户端调用时,如何分配服务实例.InstanceContextMode 可以设置为以下值: •Single – 为所有客户端调用分配一 ...
- Android设计模式之命令模式、策略模式、模板方法模式
命令模式是其它很多行为型模式的基础模式.策略模式是命令模式的一个特例,而策略模式又和模板方法模式都是算法替换的实现,只不过替换的方式不同.下面来谈谈这三个模式. 命令模式 将一个请求封装为一个对象,从 ...
- 初涉JavaScript模式 (7) : 原型模式 【三】
组合使用构造函数模式和原型模式 上篇,我们提到了原型模式的缺点,就是每个实例不能拥有自己的属性,因为纯原型模式所有的属性都是公开给每个实例的,故我们可以组合使用构造函数模式和原型模式.构造函数用来定义 ...
- 初涉JavaScript模式 (5) : 原型模式 【一】
什么是原型模式? 原型模式(prototype)是指用原型实例指向创建对象的种类,并且通过拷贝这些原型创建新的对象.--引自JavaScript设计模式 我们创建的每一个函数都有一个prototype ...
- 设计模式(十二): Flyweight享元模式 -- 结构型模式
说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面 ...
随机推荐
- Oracle中数值型及处理方法
数值型 理解精度 number类型的精度表示可以标识数据精确度的位数.对于数字13245.977,当精确到小数点后2位,数据为12345.98,此时精度为7.而当精确到小数点前2位,数据为12300, ...
- Python库积累之you-get库:网页视频与资源下载
↓↓↓欢迎关注我的公众号,在这里有数据相关技术经验的优质原创文章↓↓↓ you-get库是一个强大的视频网站下载工具,可以通过音视频网页的url链接直接下载包括视频,图片等媒体内容,从而解决一些网站视 ...
- CF1929D Sasha and a Walk in the City 题解
CF1929D Sasha and a Walk in the City 简单树形动态规划. 我们把选取到的点称为黑点,由题意得,一个合法的点集能使树中任意一条简单路径上的黑点数量不超过两个.也就是说 ...
- 前端开发系列007-基础篇之JavaScript引用类型
本文将介绍JavaScript中值类型和引用类型,两种类型的区别以及编码时候的注意点. 一.值类型和引用类型介绍 在javaScript语言基础这篇文章中已经简单介绍了JavaScript中的数据类型 ...
- raspberry ssh 允许 root 登录
参考链接 csdn
- HTML emoji 参考列表
emoji后第一个为十进制表示值,第二个为十六进制表示值,使用时任选一个即可,加上符号文字表示方式 如: 十进制 ⌚ 十六进制 ⌚ 8986 231A 8987 231B 9193 23E9 9194 ...
- 图片对嘴生成视频:HunyuanVideo-Avatar
之前几章有相应的介绍,一张图片和一个音频,生成一段对嘴视频. FLOAT: https://www.cnblogs.com/cj8988/p/18984186 (带表情,比较快,但是会裁剪为正方形尺寸 ...
- ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract).转换(Transform)和加载(Load)过程.提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转 ...
- Entities Graphics 和 GPU Skinning
Entities Graphics 是 Unity 官方提供的 DOTS 渲染方案: 包名:com.unity.entities.graphics 设计目标:让 ECS 实体也能拥有 Mesh + M ...
- 单片机+WiFi模块和主流物联网平台实现MQTT协议通信视频教程
单片机+WiFi模块和主流物联网平台实现MQTT协议通信视频教程 1.单片机+WiFi模块和阿里云物联网平台实现MQTT协议通信视频教程单片机+WiFi模块和阿里云物联网平台实现MQTT协议通信,阿里 ...