Django:简单的速率限制

2024-04-24

我的许多视图都获取外部资源。我想确保在重负载下我不会炸毁远程站点(和/或被禁止)。

我只有 1 个爬行器,所以有一个中央锁就可以了。

我希望每秒最多允许对主机进行 3 次查询,并让其余的块最多持续 15 秒。我怎样才能做到这一点(简单)?

  • Use django cache
    • 好像只有1秒分辨率
  • Use a file based semaphore
    • 很容易做并发锁。不知道如何确保每秒只发生 3 次提取。
  • Use some shared memory state
    • 我不想安装更多东西,但如果有必要的话我会安装。

一种方法;创建一个像这样的表:

class Queries(models.Model):
    site = models.CharField(max_length=200, db_index=True)
    start_time = models.DateTimeField(null = True)
    finished = models.BooleanField(default=False)

这记录了每个查询何时发生,或者如果限制阻止它立即发生,则将来将会发生。 start_time 是动作开始的时间;如果该操作当前处于阻塞状态,则这是将来的情况。

我们不要考虑每秒的查询次数,而是考虑每次查询的秒数;在本例中,每个查询需要 1/3 秒。

每当要执行操作时,请执行以下操作:

  • 为操作创建一行。 q = Queries.objects.create(site=sitename)
  • 在您刚刚创建的对象(q.id)上,原子设置start_time为该站点的最大 start_time 加 1/3 秒。如果最大的是未来 10 秒,那么我们可以在 10 1/3 秒开始我们的行动。如果该时间是过去的时间,则将其固定到 now()。
  • 如果刚刚设置的start_time是将来的时间,则休眠直到该时间。如果距离太远(例如超过 15 秒),请删除该行并出错。
  • 查询完成后,将 finish 设置为 True,以便稍后可以清除该行。

原子行动才是重要的。您不能简单地对查询进行聚合然后保存它,因为它会发生竞争。我不知道 Django 是否可以本地执行此操作,但在原始 SQL 中这很容易:

UPDATE site_queries
SET start_time = MAX(now(), COALESCE(now(), (
    SELECT MAX(start_time) + 1.0/3 FROM site_queries WHERE site = site_name
)))
WHERE id = object_id

然后,重新加载模型并在必要时休眠。您还需要清除旧行。像 Queries.objects.filter(site=site, finish=True).exclude(id=id).delete() 之类的东西可能会起作用:删除除刚刚创建的查询之外的所有已完成的查询。 (这样,你就永远不会删除latest查询,因为后面的查询需要安排该查询。)

最后,确保更新不会在事务中发生。必须打开自动提交才能使其工作。否则,更新将不是原子的:两个请求可能同时更新,并收到相同的结果。 Django 和 Python 通常会关闭自动提交,因此您需要将其打开然后关闭。对于 Postgres,这是 connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) 和 ISOLATION_LEVEL_READ_COMMITTED。我不知道如何使用 MySQL 来做到这一点。

(我认为 Python 的 DB-API 中默认关闭自动提交是一个严重的设计缺陷。)

这种方法的好处是它非常简单,状态简单;您不需要诸如事件监听器和唤醒之类的东西,它们有自己的一系列问题。

一个可能的问题是,如果用户在延迟期间取消请求,无论您是否执行该操作,延迟仍然会强制执行。如果您从未开始该操作,其他请求将不会移至未使用的“时间段”。

如果您无法让自动提交工作,解决方法是向 (site, start_time) 添加 UNIQUE 约束。 (我认为 Django 不能直接理解这一点,因此您需要自己添加约束。)然后,如果发生竞争并且对同一站点的两个请求同时结束,其中一个将引发约束您可以捕获异常,然后重试。您还可以使用普通的 Django 聚合来代替原始 SQL。不过,捕获约束异常并不那么强大。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django:简单的速率限制 的相关文章

  • django如何将字符串转换为模块?

    我试图了解 django 的另一个神奇之处 它可以将字符串转换为模块 In settings py INSTALLED APPS声明如下 INSTALLED APPS django contrib auth django contrib c
  • Http POST 删除 URL 中的端口

    我有一个用 Django 构建的网络应用程序 我目前正在家里的路由器后面的笔记本电脑上运行它 我将路由器配置为将发送到特定端口的所有流量路由到该笔记本电脑 我将 Nginx 作为 Apache 的反向代理 使用 mod wsgi 来运行 D
  • Django:从登录页面重定向登录用户

    我想设置我的网站 以便如果用户点击 login页面并且他们已经登录 它会将他们重定向到主页 如果他们没有登录 那么它将正常显示 既然登录代码内置于 Django 中 我该如何做到这一点 我假设您当前正在使用内置登录视图 r accounts
  • 在身份验证上运行 Django 测试时出现“重复键值”错误

    我有一个运行良好的 Django 网站 它的数据库中有少量数据 我想用它来进行测试 我已经完成了 dumpdata 来生成一些 json 固定装置 但是 当我尝试在我的应用程序 tagger 上运行测试时 我收到 Postgresql 错误
  • 如何在 Django 1.4 中自定义管理过滤器

    我是 Python 和 Django 开发的新手 我从社区提供的易于阅读的示例中学到了很多东西 但最近我想为 Django 附带的管理控制台实现一个自定义的管理过滤器 我进行了很多搜索 只发现了一些过时的方法来完成它 例如 Django 1
  • 带有redirect_uri的social-auth-app-django Facebook后端状态

    我知道我的问题听起来像是重复的 但我到处寻找但没有找到任何解决方案 我正在努力为我的 django web 应用程序实现社交登录 到目前为止 谷歌 推特和雅虎登录均按预期工作 但facebook总是给出以下错误 URL 被阻止 此重定向失败
  • django 南迁移,不设置默认值

    我使用 South 来迁移我的 Django 模型 然而 南方有一个令人讨厌的错误 它不会在 Postgres 数据库中设置默认值 例子 created at models DateTimeField default datetime no
  • 在 Django 中处理 ajax json 对象 - 'QueryDict' 对象没有属性 'read' 错误

    我正在尝试解析 Django 视图中的 json 对象 该对象已通过 ajax 通过 post 方法从客户端传递过来 JS post update vendor merchandise types JSON stringify json o
  • coreapi 操作,没有当前文档

    我正在尝试使用 coreapi 和 Django Rest Framework 进行发布 我正在关注这个tutorial https wsvincent com official django rest framework tutorial
  • Mac 上的 GeoDjango 和 Spatialite:C 扩展加载问题

    我正在关注GeoDjango 教程 https docs djangoproject com en dev ref contrib gis tutorial 在我的家用计算机 运行 OSX 10 8 2 的 Mac Mini 上为我的项目设
  • pip install django_compressor 时命令 cl.exe 失败

    我发布此消息是因为我遇到了这个问题 并且已经尝试解决这个问题好几天了 但未能成功 当我尝试安装 django compressor pip install django compressor 时 我遇到以下错误 请参阅附件 我在网上搜索解决
  • 如何使用 django Rest 框架保存多对多字段对象

    我有博客 发布 标签三个模型 在博客模型中 我将字段 postedin 作为发布模型的外键 将 标签 作为标签模型的许多字段 模型 py class Posted models Model name models CharField Pos
  • 我可以在pycharm中的断点处进入交互模式吗

    我是一个相当新的 Pycharm 3 用户 正在从事 django 项目 我可以在 pycharm3 中的断点处进入交互模式吗 这可能吗 当程序在断点处停止时 我尝试过工具 gt 打开调试命令行 但我没有看到控制台打开 我怎样才能让它发挥作
  • 401 Unauthorized("detail":"未提供身份验证凭据。")

    我在后端使用 djoser 的身份验证 当我通过具有内容类型和授权标头的邮递员在 account me 发出获取请求时 我得到了正确的响应 但是当我尝试从我的角度客户端执行相同的请求时 我得到401 Unauthorized detail
  • Django - 找不到静态文件

    我看过有关此问题的几个帖子 但没有找到我的解决方案 我正在尝试在 Django 1 3 开发环境中提供静态文件 这是我的设置 STATIC ROOT home glide Documents django cbox static STATI
  • 如何向 Django 管理添加报告部分?

    我想在 Django 管理中实现一个报告部分 这意味着在管理主页中添加一个自定义部分 我将看到报告列表 而不是模型列表 我想使用 Django 的管理表 其中包括过滤器 排序以及所有可能的功能 实现这一目标的 最佳 方法是什么 我意识到这是
  • Django excel save_book_to_database() 在使用 Django 1.8 的最新版本中损坏

    我一直在使用 Django 1 8 浏览 django excel 文档 但无法获得save book to database 上班 它要么默默地失败 要么给出以下错误 tuple object has no attribute meta
  • 如何修改查询集并将其另存为新对象?

    我需要查询特定模型的一组对象 更改单个属性 列 帐户 然后将整个查询集的对象保存为新对象 行 换句话说 我想复制对象 并在重复项上更改单个属性 帐户 我基本上是创建一个新帐户 然后检查每个模型并将以前帐户的对象复制到新帐户 因此我将使用不同
  • 是否有模型 MultiField(在 Django 中组合数据库模型字段的任何方法)?或者为什么这不是一个有用的概念?

    在构建 Django 应用程序时 我们接触到了 表单 MultiValueField and MultiWidget 它们似乎是一种有趣的方法来组成各自的基类 从而提供更多的模块化性 然而 现在在我们看来 真正能让这两个人大放异彩的作品将是
  • 将初始值传递给 django 中的模型表单

    如何将字段的初始值传递给模型表单 我有类似下面的代码 class ScreeningForm forms ModelForm class Meta model Screening def init self args kwargs supe

随机推荐