2

我有我的 Django 网站,目前由两台机器提供服务,使用负载均衡器。我想从一台机器上维护与用户相对应的会话。我知道我可以将负载均衡器配置为使用粘性会话,这样来自用户的所有请求都将由同一台服务器提供服务。但我想使用会话变量来实现相同的目的。

这就是我如何将该会话变量存储在一个集中式数据库中,任何服务器都可以从中访问该用户的会话,因此任何服务器都可以使用该会话变量存储来服务它。但我无法理解流程以及如何在 Django 中实现相同的流程。

所以我的问题是如何将会话保存在用户的数据库中,以便任何服务器能够访问它并相应地服务请求。在这种情况下,那些 login() 和 logout 将如何工作?

我也有多个数据库。我打算将一个用于用户身份验证和其他东西,另一个用于与网站相关的数据存储。或者任何人都可以至少向我解释如何实现这一目标的流程。

4

1 回答 1

5

我假设您已经扩展了您的系统,并且目前您正在使用负载平衡器从两台机器上为您的网站提供服务。您想知道,在不使用粘性会话的情况下,我们如何为会话维护服务器和客户端之间的连接。

同样在您所说的评论中,您可能拥有多个数据库,这些数据库可以提供不同的服务,也可以托管在某个远程位置。此外,由于您已指定您的数据库之一将处理与用户相关的内容和其他与网站相关的内容。

首先,我想给你一个关于如何实现这一点的工作流程:

  • 在您的 setting.py 文件中指定多个数据库。
  • 每个任务都有一个集中的数据库
  • 使用 using 参数指定您在保存任何数据时引用的数据库之一(如果未指定路由器)。
  • 最好使用路由器而不是每次都手动指定数据库。
  • 请记住,用户身份验证和会话,您不必将其显式存储在数据库中,一旦您在 setting.py 文件中指定它,django 就会处理它。因为您的所有服务器机器都将连接到同一个数据库以进行身份​​验证和其他东西。
  • 您的所有服务器都将使用相同的集中式数据库来存储客户端和服务器之间的 HTTP 连接的会话变量,从而维护状态。

因此,这是您如何实现相同目标的简要概述。现在让我们在代码中看到这一点。

在 setting.py 文件中指定多个数据库

指定要在DATABASES字典中使用的所有数据库。当您没有明确指定要将数据保存到的数据库时使用默认值,所有其他内容都将使用默认值进行读写。如果您明确要为每个数据库指定,则需要小心始终指定要用于存储/检索的数据库。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'app_data',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': 'XXXX',
    },
    'auth_db': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'auth_db',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': 'XXXX',
    },
}

为用户和网站相关内容明确指定不同的数据库

DATABASES = {
    'default': {},
    'auth_db': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'auth_db',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': 'XXXX',
    },
    'customers': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'customers',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': 'XXXX',
    }
}

Django 要求定义一个默认的数据库条目,但如果不使用参数字典,可以将其留空。在这种情况下,您必须明确指定在保存数据时将使用哪个数据库,或者您可以指定ROUTER相同的数据库。

如果您尝试访问您尚未在 DATABASES 中定义的数据库setting,Django 将引发django.db.utils.ConnectionDoesNotExist异常。

同步数据库

管理命令一次对migrate一个数据库进行操作。默认情况下,它在default数据库上运行,但通过提供--database选项,您可以告诉它同步不同的数据库。

例子 :

$ python manage.py migrate --database=users
$ python migrate --database=customers

路由来自不同数据库的用户身份验证和网站相关数据

using我们希望自动处理它,而不是每次都使用参数指定数据库的名称。我们需要处理路由。首先,我们需要一个知道将 auth 和 contenttypes 应用程序的查询发送到 auth_db 的路由器

class AuthRouter:
    """
    A router to control all database operations on models in the
    auth and contenttypes applications.
    """
    route_app_labels = {'auth', 'contenttypes'}

    def db_for_read(self, model, **hints):
        """
        Attempts to read auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return 'auth_db'
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return 'auth_db'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the auth or contenttypes apps is
        involved.
        """
        if (
            obj1._meta.app_label in self.route_app_labels or
            obj2._meta.app_label in self.route_app_labels
        ):
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth and contenttypes apps only appear in the
        'auth_db' database.
        """
        if app_label in self.route_app_labels:
            return db == 'auth_db'
        return None

同样,您可以为其他数据库创建路由器。

最后,在设置文件中,我们添加以下内容(将 path.to. 替换为定义路由器的模块的实际 Python 路径):

DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.OtherDBRouter']

处理路由器的顺序很重要。路由器将按照它们在 DATABASE_ROUTERS 设置中列出的顺序进行查询。在此示例中,AuthRouter 在 OtherDBRouter 之前处理,因此,与 auth 中的模型有关的决策在做出任何其他决策之前被处理。

从/向数据库检索/存储数据。

安装此设置后,让我们运行一些 Django 代码:

>>> # This retrieval will be performed on the 'auth_db' database
>>> fred = User.objects.get(username='fred')
>>> fred.first_name = 'Frederick'

>>> # This save will also be directed to 'auth_db'
>>> fred.save()

默认路由方案确保对象对它们的原始数据库保持“粘性”(即,从 foo 数据库检索的对象将保存在同一数据库中)。默认路由方案确保如果未指定数据库,所有查询都回退到默认数据库。

创建模型

现在您一定在想,在这种情况下,如何为不同的数据库创建模型,以便我们可以使用酷炫的 Django ORM 功能。

在这种情况下,您必须指定到数据库名称的映射。

在您的setting.py文件中添加,

DATABASE_APPS_MAPPING = {'user_data': 'auth_db',
                        'customer_data':'customers'}

相应的模型将被修改为

class User(models.Model):
    username = models.Charfield(ax_length=100)
    class Meta:
        app_label = 'user_data'

class Customer(models.Model):
    name = models.TextField(max_length=100)
    class Meta:
        app_label = 'customer_data'

有关更多信息并手动选择用于存储/检索的数据库。Django 还提供了一个 API,允许您在代码中保持对数据库使用的完全控制。手动指定的数据库分配将优先于路由器分配的数据库。请参阅文档

于 2019-12-16T08:56:13.293 回答