在使用具有有效负载限制的Gunicorn和Flask的Heroku中,当我有意提高高负载的情况下提高413时,heroku给出了503而不是413

时间:2019-09-27 06:55:50

标签: sockets heroku flask gunicorn

美好的一天!

通常,我在stackoverflow中找到了所有解决方案,但是这次我遇到了一个我从未见过的奇怪错误,很可能是我自己的知识不足。

请仔细阅读以了解我的问题以及到目前为止所发现的内容:)

最近,我已经使用Flask完成了一个API,该API接收json数据作为有效载荷,从而神奇地将结果返回给用户。我的代码中有一个验证点,用于检查有效载荷是否不大,例如然后再说256字节(出于测试原因)。

一切都在本地和heroku中工作,而有效负载却在极限以下。但是在Heroku中,当我超过例如限制的162倍,那么我收到的错误代码为h18,而不是我收到的413错误。

例如,我执行content_length验证的代码与此类似:

from flask import request, make_response, jsonify

from my app.api import bp


@bp.route('/magic', methods=['POST'])
@token_auth.login_required
def magic():
    content_length = request.content_length

    if int(content_length) > allowed_clength:
        response = make_response(jsonify({
            'error': 'Too large payload in a single request!',
            'expected_content_length': f'bytes: {allowed_clength}',
            'received_content_length': f'bytes: {content_length}'
        }), 413)
        return response
    else:
        print('magic goes here')

因此,当我发送payload.content_length高于允许的限制(例如42062字节)但不超过巨大开销时,我在heroku中的应用收到了预期的响应:

{
    "error": "Too large payload in a single request!",
    "expected_content_length": "bytes: 256",
    "received_content_length": "bytes: 42062"
}

但是,当我用邮递员将请求发送到具有巨大净荷的/api/magic端点时,content_length超出了allowed_clength,比平时多了例如172(或44271字节)次heroku日志中出现以下错误:

2019-09-27T05:03:15.959932+00:00 app[web.1]: <some-ip> - - [27/Sep/2019:05:03:15 +0000] "POST /api/magic HTTP/1.1" 413 131 "-" "PostmanRuntime/7.6.0"
2019-09-27T05:03:15.984553+00:00 heroku[router]: sock=backend at=error code=H18 desc="Server Request Interrupted" method=POST path="/api/magic" host=my-host request_id=<some-request-id> fwd="my-ip" dyno=web.1 connect=0ms service=44ms status=503 bytes=306 protocol=https

在邮递员中,我收到以下错误消息:

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta charset="utf-8">
        <title>Application Error</title>
        <style media="screen">
          html,body,iframe {
            margin: 0;
            padding: 0;
          }
          html,body {
            height: 100%;
            overflow: hidden;
          }
          iframe {
            width: 100%;
            height: 100%;
            border: 0;
          }
        </style>
    </head>
    <body>
        <iframe src="//<heroku-error-age>"></iframe>
    </body>
</html>

我在heroku中发现了错误代码说明-error example with nodejs,上面写着

  

决议

     

H18错误类似于H13,两者均表示套接字在响应完成之前已被销毁。使用H13,套接字已连接,然后销毁而没有发送任何数据。 H18表示套接字已连接,应用程序将某些数据作为响应的一部分发送,但随后套接字被破坏而未完成响应。

     

通常,H18表示一个响应具有多个阶段-例如,大型响应的流式传输块-且其中一个阶段引发了错误。

     

要查找错误,请首先检查您的日志中H18附近的堆栈跟踪。如果看不到任何内容,则需要更仔细地查看失败的特定请求的处理程序。记录响应的每个步骤(包括x-request-id标头)都可以提供帮助。

但是它并没有向我解释为什么仅用额外的〜2000字节来表现不同,我想说这是因为heroku中存在一些限制,例如Heroku说他们没有请求限制,好吧,那么也许请求超时限制默认为heroku中的30s,但是当将上述有效负载示例与预期的413错误A - 42062 of bytes(在{{ 1}}和503(H18)错误419ms,甚至情人的响应时间为B - 44271 of bytes

我也发现了这个question,它也有类似的问题,但是他们使用了socketio,而我却没有(至少我是这样认为的,因为我没有在任何地方明确声明它的名称)。

我尝试创建特定的errohandler来捕获413错误,但仍然无法解决。

所以我的问题是:调试并修复此奇怪行为的可能方法是什么?因为在heroku日志中我只能看到我发布的内容,所以在本地环境中我无法复制它,因此在示例代码中,我添加了显示步骤的打印语句,因此创建324ms仅在{据我了解,发生了{1}}错误。

感谢您耐心等待所有评论和帮助!

0 个答案:

没有答案