使用每个数据库一个租户的方式为Django提供多租户支持。
项目描述
提供基于每个数据库只有一个租户概念的简单多租户解决方案。
此应用程序仍处于实验阶段,但作者已在生产中使用。欢迎贡献和讨论。
背景
多租户是支持来自同一应用程序服务器的多个不同数据集的能力。每个数据集通常映射到一个客户(租户),并与其他租户数据部分或全部分区。
可能的方案包括
隔离方法:每个租户一个单独的数据库。
半隔离方法:共享数据库,每个租户具有单独的命名空间(PostgreSQL模式)或表名/前缀。
共享方法:所有租户使用单个数据库。每个表都有一个列标识该行数据的租户。
此应用程序支持两个后端,MySQL和PostgreSQL
使用MySQL,此应用程序实现了隔离方法的变体,每个租户都有自己的数据库,但它们的连接详情是共享的(如密码、数据库用户)。
对于PostgreSQL,此应用程序实现了一种半隔离方法,每个租户都有自己的模式,并且连接详情通过公共模式共享。
django-db-multitenant使得将专为单个租户设计的Django应用程序与多个租户一起使用成为可能(甚至很容易)。
操作
主要技术如下
当第一个请求到达时,从请求对象中确定所需的租户,并将其保存到线程局部存储中。
在请求的后续过程中,当获取数据库游标时,对所需租户发出MySQL的USE <租户数据库名>或PostgreSQL的SET search_path TO <租户名> SQL命令。
第一步通过实现一个映射器类来完成。您的映射器接受一个请求对象,并返回一个数据库名称或租户名称,使用您喜欢的任何逻辑(翻译主机名、检查HTTP头等)。映射器结果保存在线程局部存储中以供以后使用。
第二步确定所需数据库或模式是否已经被选择,如果是,则跳过。这是通过使用一个薄的数据库后端包装器实现的,该包装器是针对MySQL和PostgreSQL的,必须设置在settings.DATABASES中作为后端。
使用方法
1. 安装
安装django-db-multitenant(或将它添加到您的setup.py中)。
$ pip install django-db-multitenant
2. 实现映射器
您必须实现一个db_multitenant.mapper的子类,它从请求中确定数据库名称和缓存前缀。
为了帮助您编写映射器,仓库中包含了映射器示例,这些示例从URL中提取主机名以确定租户名称(例如,在https://foo.example.com/bar/中,foo将是租户名称)
MySQL映射器,它直接使用主机名的一部分作为数据库名称。
PostgreSQL映射器,它使用主机名的一部分作为搜索路径(模式)。PostgreSQL允许复杂的设置,例如共享公共表(例如,公共账户),请参阅映射器中的注释以获取更多详细信息。
Redis映射器,它使用主机名查找租户,如果未识别则抛出404。
请随意复制一个示例映射器到您的项目中,然后调整它以满足您的需求。
3. 更新settings.py
通过指定您的实现的全限定路径来设置多租户映射器(在此示例中,mapper是文件mapper.py的名称)
MULTITENANT_MAPPER_CLASS = 'myapp.mapper.TenantMapper'
将多租户中间件作为列表中的第一个中间件(在Django 1.10之前,您必须使用MIDDLEWARE_CLASSES设置)
MIDDLEWARE = [
'db_multitenant.middleware.MultiTenantMiddleware',
....
]
更改您的数据库后端为多租户包装器
DATABASES = {
'default': {
'ENGINE': 'db_multitenant.db.backends.mysql',
'NAME': 'devnull',
}
}
注意:对于MySQL,NAME是无用的,但由于当前的限制,必须存在命名的数据库。它可以空且只读。
或者对于PostgreSQL
DATABASES = {
'default': {
'ENGINE': 'db_multitenant.db.backends.postgresql',
'NAME': 'mydb',
}
}
可选地,将多租户辅助函数KEY_FUNCTION添加到您的缓存定义中,这将导致缓存键以mapper.get_cache_prefix的值作为前缀
CACHES = {
'default' : {
'LOCATION': '127.0.0.1:11211',
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'KEY_FUNCTION': 'db_multitenant.cache.helper.multitenant_key_func'
}
}
4. 测试
如果您的应用程序的租户名称是从URL中提取的(如提供的映射器示例所示),您可以在/etc/hosts中添加一个主机,如foo.example.com,将其重定向到您的本地主机服务器。
您应该将 foo.example.com 添加到 Django 设置中的 ALLOWED_HOSTS 列表,并尝试通过浏览器使用 http://foo.example.com:8000 访问您的应用程序。
映射器的示例提供了有关创建租户区域的方法信息。
管理命令
为了使用正确的租户执行管理命令(如 migrate),请在 settings.py 文件的末尾注入以下小技巧:
from db_multitenant.utils import update_from_env
update_from_env(database_settings=DATABASES['default'],
cache_settings=CACHES['default'])
如果您没有在设置中设置 CACHES,并且您不打算使用缓存系统,则无需将 cache_settings 参数传递给函数。
然后您可以在命令行上导出 TENANT_DATABASE_NAME(用于 MySQL)或 TENANT_NAME(用于 PostgreSQL)以及 TENANT_CACHE_PREFIX,例如
$ TENANT_DATABASE_NAME=example.com ./manage.py migrate
别忘了首先创建数据库(MySQL)或所需的模式(PostgreSQL)。
就是这样。因为 django-db-multitenant 没有定义任何模型,所以无需将其添加到 INSTALLED_APPS 中。
优点和局限性
对于像多租户这样的数据建模问题,并没有一种一刀切解决方案(请参阅“替代方案”)。
优点
兼容性:您的 Django 应用程序不需要对多租户有意识。数据库级别的工具(如 mysqldump 或 pgdump)只需正常工作。
隔离:一个租户一个数据库,这意味着租户数据不会相互混合(除非您与 PostgreSQL 共享表)。
简洁:您的应用程序模式不需要包含“租户”外键关系。
应该与 Django 1.6 连接持久性和连接池很好地工作。
局限性
非正统。Django 不期望这种动态数据库连接的篡改,可能存在意外的错误。
隔离有限。由于所有租户都使用相同的 DB 凭证,映射器(或应用程序中的任何其他地方)中的错误可能导致数据损坏。
仍然需要在 settings.DATABASE 中指定有效的数据库,以便在首次与 MySQL 建立连接时使用(这最终应该得到修复)。
开销:请求可能增加一个额外的查询(MySQL 的 USE <db_name> 语句或 PostgreSQL 的 SET search_path TO <tenant_name>)。
替代方案和进一步阅读
django-tenant-schemas 使用 PostgreSQL 模式实现了一种半隔离的方法(并受到本项目以及上述“概述”部分的启发)。
致谢和许可
版权所有 2013 mike wakerly (opensource@hoho.com)
根据 Apache License 2.0 许可(“许可证”);除非您遵守许可证,否则不得使用此文件。您可以在以下位置获得许可证副本:
https://apache.ac.cn/licenses/LICENSE-2.0
除非适用法律要求或书面同意,否则根据许可证分发的软件按“原样”分发,不提供任何明示或暗示的保证。有关许可证的具体语言管辖权限和限制,请参阅许可证。
项目详情
下载文件
下载适用于您的平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。
源代码分发
构建分发
django-db-multitenant-0.3.2.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 26dd8cc52aee9039736b8b800fd180663e33d00bf61c30ac89c5a1d0781a363b |
|
MD5 | 00b537b8f9ddeef43518e5d8fec7cfc1 |
|
BLAKE2b-256 | 3d5a39854a8121bffdc36e4cea9a81ab86e77ed003f598f174663caad105c465 |
django_db_multitenant-0.3.2-py2.py3-none-any.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | afe3bf2d212651e34fc2b7ddf33b8b67a966695267ae53e6b2d46c3c1c473af9 |
|
MD5 | deec2282d635944e95e927a892667705 |
|
BLAKE2b-256 | ce6e12b26ead2e06ade3a5ef04f53de0347c2407ac4aac9e0d5ac758ebe070be |