对多租户的Django应用的最佳架构 [英] optimal architecture for multitenant application on django

查看:351
本文介绍了对多租户的Django应用的最佳架构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在盘算着正确的/最佳的方式来创建基于多租户应用程序
在Django的。

I've been brooding over the right/optimal way to create a multitenancy application based on Django.

一些解释:


  • 的应用,可以由几个住户使用(tenant1,tenant2,...,)。

  • Application can be used by several tenants (tenant1, tenant2, ...,).

所有租户个人数据必须保证对其他租户(及其用户)。

All tenant-individual data has to be secured against access of other tenants (and their users).

可选的租户可以创建应用程序对象的其他自定义字段。

Optionally tenants can create additional custom-fields for application-objects.

当然,底层硬件的限制在一个体系的住户数量。

Of course, underlying hardware limits number of tenants on one "system".

1)通过例如分离每个租户子域和底层使用特定租户的数据库

1) Separating each tenant by e.g. sub-domain and using tenant-specific databases in the underlying layer

2)在模型中使用的一些租户ID为租户数据库中的数据分开

2) Using some tenant-ID in the model to separate the tenant-data in the database

我想有关部署流程,系统部件的性能(Web服务器(S),数据库服务器(S),工作节点上,...)

I am thinking about deployment-processes, performance of the system-parts (web-server(s), database-server(s), working-node(s),...)

什么是最佳的设置?在哪里赞成的和反对的?

What would be the best setup ? Where are the pro's and con's?

你怎么想的?

推荐答案

我们建立了一个多租户平台使用下面的架构。我希望你能找到一些有用的线索。

We built a multitenancy platform using the following architecture. I hope you can find some useful hints.


  • 每个租户获取子域(t1.example.com)

  • 使用URL重写的Django应用程序的请求被改写为类似example.com/t1

  • 所有URL定义的东西pfixed像 $ P $(R'^(P< tenant_id>?[\\ W \\ - ] +)

  • A <一个href=\"https://docs.djangoproject.com/en/1.3/topics/http/middleware/#writing-your-own-middleware\">middleware流程和消耗tenant_id并将其添加到请求(例如request.tenant ='T1')

  • 现在,你必须在每个视图提供当前租户不指定tenant_id参数每个视图

  • 在某些情况下,你没有可用的请求。我由tenant_id结合到当前线程(类似于当前语言解决了这个问题使用 threading.local

  • 创建装饰(如承租人意识到 login_required ),中间件或工厂,以保护意见,并选择合适的机型

  • 关于给我用了两个不同的方案数据库:

    • 设置多个数据库和配置<一href=\"https://docs.djangoproject.com/en/dev/topics/db/multi-db/#automatic-database-routing\">routing根据目前的租户。我用这个第一,但约一年后,切换到一个数据库。究其原因有以下几条:

      • 我们并不需要一个高安全的解决方案将数据分隔

      • 不同的租户使用的几乎所有的同款

      • 我们必须管理大量的数据库(并没有建立一个简单的升级/迁移过程)

      • Each tenant gets sub-domain (t1.example.com)
      • Using url rewriting the requests for the Django application are rewritten to something like example.com/t1
      • All url definitions are prefixed with something like (r'^(?P<tenant_id>[\w\-]+)
      • A middleware processes and consumes the tenant_id and adds it to the request (e.g. request.tenant = 't1')
      • Now you have the current tenant available in each view without specifying the tenant_id argument every view
      • In some cases you don't have the request available. I solved this issue by binding the tenant_id to the current thread (similar to the current language using threading.local )
      • Create decorators (e.g a tenant aware login_required), middlewares or factories to protect views and select the right models
      • Regarding to the databases I used two different scenarios:
        • Setup multiple databases and configure a routing according to current tenant. I used this first but switched to one database after about one year. The reasons were the following:
          • We didn't need a high secure solution to separate the data
          • The different tenants used almost all the same models
          • We had to manage a lot of databases (and didn't built an easy update/migration process)

          关于我们使用以下安装环境:

          Regarding the environment we use the following setup:

          • Nginx
          • uWSGI
          • PostgreSQL
          • Memcached

          从我的角度来看这个设置具有以下亲的和反对的:

          From my point of view this setup has the following pro's and con's:

          临:


          • 一个应用程序实例知道目前的租户

          • 项目的大部分地区没有与租户的具体问题来打扰

          • 所有租户之间共享实体简单的解决方案(例如消息)

          魂斗罗:


          • 一个相当大的数据库

          • 一些非常相似的表,由于模型继承

          • 不固定数据库层上

          当然,最好的架构在很大程度上取决于你的要求租户数,你的模型的增量,安全要求等。

          Of course the best architecture strongly depends on your requirements as number of tenants, the delta of your models, security requirements and so on.

          更新:当我们回顾我们的架构,我建议的的重写URL作为点2-3所示。我认为,一个更好的解决方案是把 tenant_id 作为一个请求头,并提取(4点)的 tenant_id 出喜欢的东西 request.META.get('TENANT_ID',无)请求。这样,你得到的中性URL和它更容易使用Django的内置函数(如 {%网址...%} 反向() )或外部应用程序。

          Update: As we reviewed our architecture, I suggest to not rewrite the URL as indicated in point 2-3. I think a better solutions is to put the tenant_id as a Request Header and extract (point 4) the tenant_id out of the request with something like request.META.get('TENANT_ID', None). This way you get neutral URLs and it's much easier to use Django built-in functions (e.g. {% url ...%} or reverse()) or external apps.

          这篇关于对多租户的Django应用的最佳架构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆