【问题标题】:Django: disable initial system checks in production?Django:在生产中禁用初始系统检查?
【发布时间】:2018-03-12 20:08:18
【问题描述】:

我浏览了文档并正在寻找一个 Django 设置,该设置在生产中禁用系统检查(不仅仅是使它们静音)。我有一个包含 20,000 多个模型的项目,这些模型会自动生成以创建 RESTful 端点。这些系统检查需要相当长的时间:

https://docs.djangoproject.com/en/1.11/ref/checks/#models

在开发中检查系统是必要的,即使它会导致manage.py 20-30 分钟启动。但是,每当我将新版本发布到生产环境时,对生产节点的第一个 HTTP 请求也需要 20-30 分钟才能响应!我显然想避免这种情况,因为在最初的请求之后,网站速度很快。

虽然下面 cmets 中的答案引用了一个让 runserver 更快出现的解决方案,但我正在寻找生产环境的解决方案,而不是我们的开发环境。

我四处寻找像DISABLED_SYSTEM_CHECKS 这样的设置,但只遇到SILENCED_SYSTEM_CHECKS (see here),但这似乎只是使输出静音,而不是不运行需要时间的检查。这样的动物存在吗?我在生产中运行mod_wsgi。我已经看到 requires_system_checks 用于单个命令,但我正在寻找一个项目范围的解决方案。非常感谢。

【问题讨论】:

  • 但是文档说 - For performance reasons, checks are not run as part of the WSGI stack that is used in deployment..
  • 是什么让您认为系统检查正在运行?你是如何启动你的生产服务器的?除非您出于某种原因使用 manage.py,否则不应运行检查。另一方面,如果你真的有 20000 个模型,那么加载这些模型的开销必然与它所花费的时间有关。
  • 嗯,这很奇怪。如果我禁用带有数据端点的urls.pyinclude 语句,它会立即加载。 mod_wsgi 作为 Apache 模块运行,在发布期间,wsgi.py 被重写,导致 mod_wsgi 重新加载。可能没有办法解决它;我试图避免将每个节点从 HA 代理中拉出,发布,用 curl 在本地命中它,然后将其放回池中。
  • 这听起来像是在滥用 Django! :D

标签: python django django-models mod-wsgi django-commands


【解决方案1】:

您可以创建DISABLE_CHECKS 设置并从检查函数本身中强制跳过检查。我注意到即使你在settings.py 中设置了SILENCED_SYSTEM_CHECKS,某些manage.py 命令仍然会运行检查(例如迁移)。这是我使用的:

import logging

from django.conf import settings
from django.core.checks import Error
from django.db import connections
from django.core.cache import caches

def check_cache_connectivity(app_configs, **kwargs):
    """
    Check cache
    :param app_configs:
    :param kwargs:
    :return:
    """
    errors = []

    # Short circuit here, checks still ran by manage.py cmds regardless of SILENCED_SYSTEM_CHECKS
    if settings.DISABLE_CHECKS:
        return errors

    cache_settings = settings.CACHES.keys()
    for cur_cache in cache_settings:
        try:
            key = 'check_cache_connectivity_{}'.format(cur_cache)
            caches[cur_cache].set(key, 'connectivity_ok', 30)
            value = caches[cur_cache].get(key)
            print("Cache '{}' connection ok, key '{}', value '{}'".format(cur_cache, key, value))
        except Exception as e:
            msg = "ERROR: Cache {} looks to be down. {}".format(cur_cache, e)
            print(msg)
            logging.exception(msg)
            errors.append(
                Error(
                    msg,
                    hint="Unable to connect to cache {}, set as {}. {}"
                         "".format(cur_cache, settings.CACHES[cur_cache], e),
                    obj='CACHES.{}'.format(cur_cache),
                    id='content_services.E002',
                )
            )
    return errors

我在构建环境中使用它,如果不是所有自定义检查,我最希望忽略。希望对您有所帮助!

【讨论】:

  • 谢谢!这正是我正在寻找的类型。非常感谢。
【解决方案2】:

我很久以前就发布了这个问题,但从未发布过我最终使用的解决方案。根本问题是,有这么多模型(我们现在多达 60,000 个!),每个模型都会在加载时进行验证。 urls.py 包含所有端点路由,它将导入 DRF ViewSets,这反过来又会预先加载序列化程序和模型。所以我所做的是创建一种延迟加载,我们已经开源了它:

https://pypi.org/project/automagic-rest/

关键元素是修改ViewSet 以在__init__ 中按需加载模型,而不是预先加载:

self.model = getattr(
    import_module(f"{self.python_path_name}.models.{self.schema_name}"),
    f"{self.schema_name}_{self.table_name}_model",
)

您可以在此处查看完整源代码:https://github.com/wharton/automagic-rest/blob/master/automagic_rest/views.py#L53

这需要为 DRF 的 basename 制定一个约定来保存数据库名称、应用程序名称、模式名称和模型名称,但它运作良好。 60,000 个模型的初始加载时间现在约为 45 秒,而不是超过三个小时。

【讨论】:

    猜你喜欢
    • 2016-06-17
    • 1970-01-01
    • 2021-07-14
    • 2015-09-14
    • 1970-01-01
    • 2016-04-29
    • 2014-11-21
    • 2011-10-16
    • 1970-01-01
    相关资源
    最近更新 更多