草庐IT

python - 用于网络分析屏幕的Django设计模式需要很长时间才能计算出来

coder 2023-08-20 原文

我有一个“分析仪表板”屏幕,对我的Django Web应用程序用户可见,这需要很长的时间来计算。它是这些屏幕中的一个,为用户浏览数据库中的每个事务,并为他们提供关于它的度量。
我希望这是一个实时操作,但对于活动用户,计算时间可以是20-30秒(不允许分页,它给出事务的平均值)。
想到的解决方案是通过manage.py批处理命令在后端计算这个值,然后只向用户显示缓存的值。是否有Django设计模式来帮助简化这些类型的模型/显示?

最佳答案

您要寻找的是脱机处理和缓存的组合。离线时,我的意思是计算逻辑发生在请求响应周期之外。通过高速缓存,我的意思是昂贵的计算结果对于X时间是足够有效的,在此期间您不需要重新计算它来显示。这是一种非常常见的模式。
脱机处理
有两种广泛使用的工作方法需要在请求响应周期之外进行:
cron作业(通常通过自定义管理命令变得更容易)
Celery
相对而言,cron的设置更简单,芹菜更强大/更灵活。这就是说,芹菜拥有出色的文档和全面的测试套件。我几乎在每个项目的生产中都使用过它,虽然它确实涉及到一些需求,但它并不是一个真正的负担。
克朗
cron作业是一种由来已久的方法。如果您只需要运行一些逻辑并在数据库中存储一些结果,cron作业就没有依赖性。cron作业唯一的麻烦就是让代码在Django项目的上下文中运行——也就是说,为了了解数据库和应用程序,代码必须正确加载settings.py。对于未经启蒙的人来说,这可能会导致在预言正确的PYTHONPATH等方面的一些恶化。
如果您要使用cron路由,一个好的方法是编写一个定制的管理命令。您可以轻松地从终端测试您的命令(并编写测试),并且不需要在管理命令的顶部执行任何特殊的Hoopla来设置适当的Django环境。在生产中,只需运行path/to/manage.py yourcommand。我不确定这种方法是否在没有virtualenv帮助的情况下有效,不管怎样,您都应该使用它。
另一个需要考虑的方面是cronjobs:如果您的逻辑需要可变的运行时间,cron就不知道这一点。杀死服务器的一个可爱的方法是每小时运行一个两小时的cronjob。您可以滚动自己的锁定机制来防止这种情况发生,只要注意这一点,当您的数据增长时,或者当您的RDBMS行为不正常时,一个简短的cronjob可能不会保持这种状态,等等。
在您的案例中,cron似乎不太适用,因为您需要经常为每个用户计算图表,而不考虑实际使用系统的用户。这就是芹菜的用处。
芹菜
…是蜜蜂的膝盖。通常,人们被AMQP经纪人的“违约”要求吓跑了。设置rabbitmq并不是很麻烦,但它确实需要稍微走出舒适的python世界。对于许多任务,我只使用redis作为我的芹菜任务存储。设置为:

CELERY_RESULT_BACKEND = "redis"
REDIS_HOST = "localhost"
REDIS_PORT = 6379
REDIS_DB = 0
REDIS_CONNECT_RETRY = True

喂,不需要AMQP经纪人。
芹菜比简单的克罗恩工作有很多优势。与cron一样,您可以调度straightforward,但也可以在不占用请求/响应周期的情况下响应其他刺激而触发任务。
如果您不想经常为每个活动用户计算图表,则需要按需生成它。我假设查询最新的可用平均值是便宜的,计算新的平均值是昂贵的,并且您使用类似于periodic tasks的工具生成客户端的实际图表。下面是一个示例流程:
用户请求包含平均值图表的页面。
检查缓存——是否有一个存储的、未过期的查询集包含此用户的平均值?
如果是,使用它。
如果没有,则启动芹菜任务以重新计算它,重新查询并缓存结果。由于查询现有数据很便宜,如果您希望同时向用户显示过时的数据,请运行查询。
如果图表过时。或者提供一些图表过时的指示,或者每隔一段时间对Ping Django执行一些Ajax狂热操作,并询问刷新后的图表是否已就绪。
您可以将此任务与定期任务结合起来,为具有活动会话的用户每小时重新计算图表,以防止显示真正过时的图表。这不是剥皮猫的唯一方法,但它为您提供了在限制计算任务的CPU负载的同时确保新鲜度所需的所有控制。最重要的是,周期性任务和“按需”任务具有相同的逻辑,您只定义一次任务,并从两个地方调用它以增加干燥度。
缓存
flot为您提供了所需的所有钩子,您可以随时缓存所需的任何内容。大多数生产站点依赖于Django cache framework作为其缓存后端,我最近开始使用带有memcached后端的Redis,但我不确定我是否会将其信任为主要的生产站点。
以下是一些代码,展示了使用django-redis-cache来完成上述工作流:
import pickle
from django.core.cache import cache
from django.shortcuts import render
from mytasks import calculate_stuff

from celery.task import task

@task
def calculate_stuff(user_id):
    # ... do your work to update the averages ...
    # now pull the latest series
    averages = TransactionAverage.objects.filter(user=user_id, ...)
    # cache the pickled result for ten minutes 
    cache.set("averages_%s" % user_id, pickle.dumps(averages), 60*10)

def myview(request, user_id):
    ctx = {}
    cached = cache.get("averages_%s" % user_id, None)
    if cached:
        averages = pickle.loads(cached) # use the cached queryset
    else:
        # fetch the latest available data for now, same as in the task
        averages = TransactionAverage.objects.filter(user=user_id, ...)
        # fire off the celery task to update the information in the background
        calculate_stuff.delay(user_id) # doesn't happen in-process.
        ctx['stale_chart'] = True # display a warning, if you like

    ctx['averages'] = averages
    # ... do your other work ...
    render(request, 'my_template.html', ctx)

编辑:值得注意的是,酸洗一个查询集会将整个查询集加载到内存中。如果使用平均查询集提取大量数据,这可能是次优的。在任何情况下,使用真实数据进行测试都是明智的。

关于python - 用于网络分析屏幕的Django设计模式需要很长时间才能计算出来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6887100/

有关python - 用于网络分析屏幕的Django设计模式需要很长时间才能计算出来的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  6. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  7. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  8. ruby - inverse_of 是否适用于 has_many? - 2

    当我使用has_one时,它​​工作得很好,但在has_many上却不行。在这里您可以看到object_id不同,因为它运行了另一个SQL来再次获取它。ruby-1.9.2-p290:001>e=Employee.create(name:'rafael',active:false)ruby-1.9.2-p290:002>b=Badge.create(number:1,employee:e)ruby-1.9.2-p290:003>a=Address.create(street:"123MarketSt",city:"SanDiego",employee:e)ruby-1.9.2-p290

  9. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  10. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

随机推荐