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

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

问题描述



一些解释:




  • 应用程序可由多个租户(tenant1,tenant2,...)使用。


  • 所有租户个人资料必须得到其他租户(及其用户)的访问保护。



  • 当然,底层硬件限制一个系统上的租户人数。




1)子域和在底层中使用特定于租户的数据库



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



我正在考虑部署过程,系统部件(Web服务器,数据库服务器,工作节点)的性能。 。)



什么是最好的设置?你的意思是什么?



你怎么看?

解决方案

p>我们使用以下架构构建了一个多租户平台。我希望您能找到一些有用的提示。





关于环境,我们使用以下设置:





从我的角度来看,这个设置有以下pro和con:



Pro:




  • 一个应用实例知道现在的租户

  • 项目的大部分部分不必考虑租户的具体问题

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



Contra:




  • 一个相当大的数据库

  • 由于模型继承而导致的一些非常相似的表

  • 不保护数据库层



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

更新:在我们审查了我们的架构时,建议不要重写URL,如第2-3点所示。我认为一个更好的解决方案是将 tenant_id 作为一个请求头并提取(点4) tenant_id 请求与 request.META.get('TENANT_ID',无)等。这样你就可以获得中立的URL,而且使用Django内置函数(例如 {%url ...%} reverse() )或外部应用程序。


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

Some explanation:

  • 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) Separating each tenant by e.g. sub-domain and using tenant-specific databases in the underlying layer

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

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?

What do you think?

解决方案

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

  • 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)
    • Use one database with some simple mapping tables for i.e. users and different models. To add additional and tenant specific model fields we use model inheritance.

Regarding the environment we use the following setup:

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

Pro:

  • One application instance knowing the current tenant
  • Most parts of the project don't have to bother with tenant specific issues
  • Easy solution for sharing entities between all tenants (e.g. messages)

Contra:

  • One quite large database
  • Some very similar tables due to the model inheritance
  • Not secured on the database layer

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

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天全站免登陆