首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django +芹菜+ Apache mod_wsgi + Postgres +多个客户端的RabbitMQ应用程序

Django +芹菜+ Apache mod_wsgi + Postgres +多个客户端的RabbitMQ应用程序
EN

Stack Overflow用户
提问于 2020-08-13 13:48:42
回答 2查看 469关注 0票数 2

我有一个Django应用程序,它使用芹菜RabbitMQ和Apache mod_wsgi。目前都在一台服务器上。每个客户端都有自己的URL挂载,例如:

www.example.com/Client001

www.example.com/Client002

www.example.com/Client003

每个客户端都有自己的数据库和项目目录,并为其Django设置提供local_setting.py。

我正在使用监督管理芹菜工人+芹菜打每一个客户。

因为我有更多的客户,所以维护变得更费时。

我已经开始使用Docker来简化部署,并且可能会扩展到多个主机。

虽然很容易设置来为一个客户端运行一组服务,但我正在尝试为多个客户端找到易于管理的最佳方法,例如快速设置一个安装在主URL下的新客户端。

我认为Postgres数据库实例应该是共享的,以保存每个客户端数据库,就像现在一样。并拥有一个共享的NGIX实例来处理HTTP端。对于每个客户端,都使用一个Kubernetes Pod,包括:

  • Gunicorn将处理Django
  • 芹菜拍
  • 芹菜工
  • 用于静态文件的轻量级HTTP服务器。

所以问题是,这是一个好办法,还是有更好的方法来处理这件事?

我还想知道我是否应该沿着为每个客户端构建一个映像的路线前进,因为这可能更容易管理?

欢迎任何建议。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-08-18 06:35:32

我的建议是让一个代码库和一个服务器运行(或者运行同一个Django应用程序的多个服务器,而不需要基于客户端的任何定制)。主要原因是维护容易。您不希望多次进行更改以向多个客户端提供功能。

由于您已经有了Django应用程序,所以我认为最好使用该代码来适应上面给出的方法,尽量减少代码的更改。也就是说,您需要某种方法来处理连接到多个DB的多个客户端。我建议使用中间件和数据库路由器。比如:(基于这个片段的代码)。

代码语言:javascript
复制
import threading

request_cfg = threading.local()

class RouterMiddleware (object):
    def process_view( self, request, view_func, args, kwargs ):
        if 'client' in kwargs:
            request_cfg.client = kwargs['client']
            request.client = client 
            # Here, we are adding client info with request object.
            # It will make the implementation bit easier because
            # then you can access client information anywhere in the view/template.

    def process_response( self, request, response ):
        if hasattr( request_cfg, 'client' ):
            del request_cfg.client
        return response

class DatabaseRouter (object):
    def _default_db( self ):
        from django.conf import settings
        if hasattr( request_cfg, 'client' ) and request_cfg.client in settings.DATABASES:
            return request_cfg.client            
        else:
            return None

    def db_for_read( self, model, **hints ):
        return self._default_db()

    def db_for_write( self, model, **hints ):
        return self._default_db()

然后将它们添加到settings.py

代码语言:javascript
复制
DATABASES = {
    'default': {
        'NAME': 'user',
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'postgres_user',
        'PASSWORD': 's3krit'
    },
    'client1': {
        'NAME': 'client1',
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'postgres_user',
        'PASSWORD': 's3krit'
    },
    'client2': {
        'NAME': 'client2',
        'ENGINE': 'django.db.backends.postgresql',
        'USER': '_user',
        'PASSWORD': 'priv4te'
    }
}

DATABASE_ROUTERS = [
    'path.to.DatabaseRouter', 
]

MIDDLEWARE = [
    # middlewares
    'path.to.RouterMiddleware'
]

最后更新urls.py

代码语言:javascript
复制
urlpatterns = [
    path('<str:client>/admin/', admin.site.urls),
    path('<str:client>/', include('client_app.urls')),
    # and so on
]

这种方法的优点是无需为新客户端配置任何东西,只需在设置中添加一个新数据库并按照文档中的描述运行迁移。不需要配置反向代理服务器或其他任何东西。

现在,在处理芹菜中的任务时,您可以提供将使用哪个数据库来运行查询(参考文档)。下面是一个示例:

代码语言:javascript
复制
@app.task
def some_task():
    logger.info("-"*25)
    for db_name in settings.DATABASES.keys():
        Model.objects.using(db_name).filter(some_condition=True)
    logger.info("-"*25)
票数 1
EN

Stack Overflow用户

发布于 2020-08-18 05:09:33

处理客户端有三种方法:

  1. 孤立的方法:单独的数据库。每个租户都有自己的数据库。
  2. 半孤立的方法:共享数据库,单独的模式。为所有租户提供一个数据库,但每个租户有一个模式。
  3. 共享方法:共享数据库、共享架构。所有租户共享相同的数据库和架构。有一个主租户表,其中所有其他表都有一个指向外键的外键。

django-租客包使用第二种方法,并有一个用于客户端的子域,如client1.example.com、client2.example.com等。

我还使用了django-租户,为我创建的每个模型添加了一个Company模型外键。

django租户在postgres中提供了帮助,但是有不同的模式;开销更少。

添加Company必须在每个模型中实现,如果您使用的是基于类的视图,则应该使用中间件或混合器来处理。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63396649

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档