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

Heroku自动缩容Dyno时Passenger引发H13错误求助

解决Heroku缩容时的H13错误问题

我完全懂你遇到的麻烦——Heroku自动缩容关闭Dyno时,Passenger会立刻终止所有未完成的请求,直接导致连接提前断开触发H13错误。从你贴的日志也能看出来,核心问题就是Passenger对SIGTERM信号的处理太激进,没给正在跑的请求留完成的时间。

下面是几个经过实践验证的解决方案,按优先级给你整理好了:

1. 配置Passenger的优雅关闭超时

Passenger默认收到SIGTERM后会立刻终止请求,我们可以通过环境变量让它等一等正在处理的请求:

  • 打开Heroku应用的设置页面,添加环境变量:
    PASSENGER_GRACEFUL_SHUTDOWN_TIMEOUT=30
    
    这里的30是等待的秒数,你可以根据自己应用里请求的平均处理时长调整(注意Heroku本身给Dyno的关闭宽限期就是30秒,别超过这个值)。

2. 代码层捕获SIGTERM,自定义优雅关闭逻辑

如果Passenger的默认配置还不够灵活,你可以在应用代码里直接捕获SIGTERM信号,拒绝新请求的同时等待现有请求完成:

  • 拿Rails应用举例子,在config/application.rb里加这段代码:
    shutdown_requested = false
    
    Signal.trap('TERM') do
      shutdown_requested = true
      Rails.logger.info "收到SIGTERM信号,开始优雅关闭"
    end
    
    # 自定义中间件拦截新请求
    class ShutdownMiddleware
      def initialize(app)
        @app = app
      end
    
      def call(env)
        if shutdown_requested
          [503, {'Content-Type' => 'text/plain'}, ["服务正在关闭,请稍后再试"]]
        else
          @app.call(env)
        end
      end
    end
    
    config.middleware.use ShutdownMiddleware
    
    这样收到SIGTERM后,应用会给新请求返回503,同时让正在处理的请求继续跑完,直到超时。

3. 调整Heroku的缩容策略(可选)

如果你的应用有不少长耗时请求,还可以从缩容触发逻辑上优化:

  • 避免在请求高峰期自动缩容,用Heroku的autoscaling插件自定义缩容条件,比如只有当请求量持续低于阈值10分钟以上再触发缩容。
  • 或者用蓝绿部署的思路替换Dyno:先启动新的Dyno实例,等所有新请求都路由到新实例后,再慢慢关闭旧Dyno,从根源上避免缩容时打断请求。

最后提醒一句:Heroku给Dyno的关闭宽限期最多30秒,所有优雅关闭的逻辑都得在这个时间内完成,超时后Heroku会发SIGKILL强制终止进程,到时候还是会出现H13错误,所以一定要根据自己请求的实际处理时长来设置超时时间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:46:31