You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Heroku接收3MB JSON POST请求时读取超时问题求助

3MB JSON POST请求在Heroku超时(H13错误)排查

问题情况

本地环境能正常处理包含3MB JSON字典的POST请求,但部署到Heroku服务器后,视图读取请求参数时出现超时,触发H13错误。

相关代码

请求发送代码

def send_request():
    with open(file) as f:
        data = json.loads(f.read())
    data = json.dumps(data)
    response = requests.post(url=url_recette, data=data)
    return response

服务器视图代码

@csrf_exempt
def view(request):
    print('the server gets here')
    _args = json.loads(request.body.decode('utf-8'))
    print('the server never gets here so the timeout occurs when i load the args')

Heroku错误日志

Jan 13 09:00:03 gestion app[web] INFO [2023-01-13 09:00:03 +0100] [18] [INFO] Worker exiting (pid: 18)
Jan 13 09:00:03 gestion heroku[router] error at=error code=H13 desc="Connection closed without response" method=POST path="/resiliation/api_get_requete_from_ak" host=gestion-recette.herokuapp.com request_id=xx fwd="xxxx.231" dyno=web.1 connect=0ms service=30826ms status=503 bytes=0 protocol=https
Jan 13 09:00:04 gestion app[web] INFO [2023-01-13 09:00:04 +0100] [26] [INFO] Booting worker with pid: 26

原因分析

  • Heroku超时限制触发:Heroku的Web Dyno默认请求处理超时时间是30秒,日志显示处理耗时30826ms(约30秒),刚好触碰到阈值,路由直接强制关闭连接,抛出H13错误。本地环境没有这个严格限制,所以能正常处理。
  • 资源瓶颈:Heroku基础级Dyno的CPU和内存资源有限,3MB JSON的解析过程需要占用较多资源,服务器端资源不足时,解析速度远慢于本地,最终拖到超时。
  • 一次性加载解析的低效:直接读取整个request.body并一次性解析成JSON对象,会瞬间占用大量内存,不仅拖慢解析速度,还可能触发内存压力导致进程不稳定(日志里的worker重启也能佐证这点)。

解决方案建议

  • 改用流式解析JSON:使用ijson这类支持流式解析的库,分块处理大JSON数据,避免一次性加载全部内容到内存,降低资源占用和处理时间。示例代码大致如下:
    import ijson
    
    @csrf_exempt
    def view(request):
        print('the server gets here')
        # 流式解析request.body
        parser = ijson.parse(request.body)
        _args = {}
        for prefix, event, value in parser:
            # 根据实际JSON结构逐步构建数据
            if prefix.endswith("your_key"):
                _args[prefix.split('.')[-1]] = value
        print('finished parsing')
    
  • 启用请求压缩:发送请求时对JSON数据进行gzip压缩,减少传输体积和服务器端的接收解析压力。修改发送代码:
    import gzip
    from io import BytesIO
    
    def send_request():
        with open(file) as f:
            data = json.loads(f.read())
        data_bytes = json.dumps(data).encode('utf-8')
        # 压缩数据
        buffer = BytesIO()
        with gzip.GzipFile(fileobj=buffer, mode='wb') as f:
            f.write(data_bytes)
        compressed_data = buffer.getvalue()
        # 发送压缩请求
        response = requests.post(
            url=url_recette,
            data=compressed_data,
            headers={'Content-Encoding': 'gzip', 'Content-Type': 'application/json'}
        )
        return response
    
    同时确保服务器端配置支持自动解压gzip请求(Django可通过中间件实现)。
  • 调整WSGI服务器超时:如果使用Gunicorn作为WSGI服务器,在Procfile中增加超时配置,比如:
    web: gunicorn your_project.wsgi --timeout 60
    
    给大请求处理留出更多时间,但注意Heroku的路由超时最长是55秒,不要超过这个值。
  • 升级Dyno规格:如果上述优化后仍无法解决,考虑升级到更高配置的Heroku Dyno,获得更多CPU和内存资源,提升大文件处理速度。

内容的提问来源于stack exchange,提问作者Arthur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 22:50:31