【问题标题】:django UnreadablePostError: request data read errordjango UnreadablePostError:请求数据读取错误
【发布时间】:2013-03-21 09:51:19
【问题描述】:

我正在开发 django 项目,我收到了这封错误电子邮件。

堆栈跟踪

File "/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/core/handlers/wsgi.py", line 180, in _get_post
    self._load_post_and_files()

File "/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/http/__init__.py", line 379, in _load_post_and_files
    self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict()

File "/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/http/__init__.py", line 335, in body
    self._body = self.read()

File "/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/http/__init__.py", line 391, in read
    return self._stream.read(*args, **kwargs)

File "/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/core/handlers/wsgi.py", line 98, in read
    result = self.buffer + self._read_limited()

File "/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/core/handlers/wsgi.py", line 92, in _read_limited
    result = self.stream.read(size)

UnreadablePostError: request data read error

为什么会出现这个错误?
如何解决?

【问题讨论】:

  • 这些是损坏的请求。例如。有人在发布内容时取消了请求。你可以忽略它们。但是您可能想检查这是在哪个页面上发生的。也许您的应用加载某些内容需要花费太多时间。
  • @Bibhas 我曾经与最糟糕的 QA 合作过,他们的“压力测试”想法是在浏览器中按住“F5”。很多这些都冒出来了。 :)
  • :D 人和他们疯狂的逻辑。 :P 顺便说一句,我应该将该评论作为答案发布吗?它并没有真正说明如何解决它。我也不确定您是如何解决中断请求的。
  • @Bibhas 从技术上讲,这不是实际的服务器错误。更多的是客户端错误。不过,您可以以更易读的方式记录它。

标签: python django mod-wsgi


【解决方案1】:

为什么会出现这个错误?

因为服务器正在接收格式错误的请求,这可能由于多种原因而发生。有人可能取消了加载页面,有人可能有一个糟糕的互联网连接中断了,宇宙射线可能有点翻转

在它开始频繁发生之前,您真的不需要担心。当这些错误发生时,您可能需要做一个记录,看看它是否因此在同一页面上。

如何解决?

你不能。至少现在不是。收集更多有关此错误何时发生的数据。看看能不能找到手动触发的方法。

【讨论】:

    【解决方案2】:

    对于大规模应用程序,您总会偶尔收到取消的请求。如果您收到 500 封电子邮件,它们可能会非常乏味。

    我不建议完全忽略它们。如果 UnreadablePostErrors 涌入,那么有问题,例如较长的响应时间会导致用户取消请求。

    我的解决方案是针对管理员电子邮件的自定义过滤器,您可以在其中放置您想要的任何逻辑。

    最简单的可能是随机忽略 20 个 UnreadablePostErrors 中的 19 个。这样,如果出现问题,我仍然会被告知,但我会少 20 倍的麻烦。

    如果你想要更花哨的东西,我会选择@pztrick 的解决方案。

    import logging
    import random
    from django.http import UnreadablePostError
    
    class ReduceUnreadablePostErrors(logging.Filter):
        def filter(self, record):
            if record.exc_info:
                exc_value = record.exc_info[1]
                if isinstance(exc_value, UnreadablePostError):
                    return random.randint(1,20) % 20==0
            return True
    

    settings.py:

    'filters': {
       'reduce_unreadable_post_errors' : {
            '()' : 'path.to.your.ReduceUnreadablePostErrors'
        },
    
        ...
    
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false','reduce_unreadable_post_errors'],
            'class': 'common.utils.log.AdminEmailHandlerWithEmail'
         },
    
         ...
    

    【讨论】:

    • 不错的解决方案。使用过期的缓存键(60 秒?我不知道频率是多少。)也可能是一个很好的解决方案。
    • 我需要调用这个函数吗?如果需要,需要什么参数?
    • 只要您在 settings.py 的日志记录部分正确指定过滤器,只要发生 500 错误,Django 就会为您调用它。如果您尝试在开发中玩耍,请确保它没有被另一个过滤器排除(从上面的示例中删除 require_debug_false)。查看文档了解更多详情:docs.djangoproject.com/en/3.0/topics/logging
    【解决方案3】:

    我为此编写了一个节流版本。如果它是尖峰的,你会想看到错误,但如果它每五分钟出现一次或其他什么,你可以忽略它。这假设如果它在一分钟内出现两次,您可能需要调查一些问题。

    def skip_unreadable_post(record):
        if record.exc_info:
            exc_value = record.exc_info[1]
            if isinstance(exc_value, UnreadablePostError):
                cache_key = "settings.unreadable_post_error"
                r = make_redis_interface("CACHE")
                if r.get(cache_key) is not None:
                    # We've seen this recently; let it through; hitting it a lot
                    # might mean something.
                    return True
                else:
                    # Haven't seen this recently; cache it with a minute expiry,
                    # and don't let it through.
                    r.set(cache_key, "True", ex=60)
                    return False
        return True
    
    ...
        "filters": {
            "skip_unreadable_posts": {
                "()": "django.utils.log.CallbackFilter",
                "callback": skip_unreadable_post,
            },
        },
    ...
            "django.server": {
                "level": "INFO",
                "class": "logging.StreamHandler",
                "formatter": "django.server",
                "filters": ["skip_unreadable_posts"],
            },
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-08
      • 2012-07-02
      • 2012-09-14
      • 1970-01-01
      • 2019-11-06
      • 1970-01-01
      相关资源
      最近更新 更多