首页 > 解决方案 > 乘客的 Heroku H13 错误

问题描述

当测功机由于自动缩放而关闭时,我在 Heroku 中一直收到 H13 错误。H13 错误意味着在给出响应之前连接已关闭。

从日志中,您可以看到 Heroku 在缩减 dynos 时发送了一个 SIGTERM,并且乘客会立即关闭任何尚未完成处理的请求:

May 03 08:38:24 myapp app/web.4:  App 175 stdout: Started POST "/exams/3167060/tick?elapsed_time=1" for 108.162.237.61 at 2018-05-03 12:38:23 +0000 
May 03 08:38:24 myapp app/web.4:  App 175 stdout: Processing by ExamsController#tick as HTML 
May 03 08:38:24 myapp app/web.4:  App 175 stdout:   Parameters: {"elapsed_time"=>"1", "id"=>"3167060"} 
May 03 08:38:24 myapp app/web.4:  Stopping web server... done 
May 03 08:38:24 myapp heroku/router:  at=info method=POST path="/exams/3167120/tick?elapsed_time=1" host=www.myapp.com request_id=d81b4dc5-2a5a-44a4-96c6-61b7ea6d28f3 fwd="206.221.128.1,162.158.63.225" dyno=web.4 connect=1ms service=37ms status=200 bytes=954 protocol=https 
May 03 08:38:24 myapp heroku/web.4:  Stopping all processes with SIGTERM 
May 03 08:38:24 myapp heroku/router:  at=error code=H13 desc="Connection closed without response" method=POST path="/exams/3167060/tick?elapsed_time=1" host=www.myapp.com request_id=28c2f413-847c-4d11-bce9-5be7186cfbd8 fwd="152.27.48.186,108.162.237.61" dyno=web.4 connect=1ms service=53ms status=503 bytes=0 protocol=https 
May 03 08:38:24 myapp heroku/web.4:  Process exited with status 2

我的Procfile乘客配置如下,我没有设置任何与超时相关的内容:

web: bundle exec passenger start -p $PORT --max-pool-size $MAX_POOL_SIZE --min-instances $MIN_INSTANCES --nginx-config-template config/nginx.conf.erb

在 24 小时内,我看到大约 16 个 H13 错误,原因是来自测功机缩减事件的 SIGTERM。我可以在我的 Heroku 指标仪表板中证实测功机按比例缩小到 H13。Heroku 支持告诉我,乘客默认允许 30 秒(尽管我不确定他们是否在谈论他们自己的 H12 错误,该错误将在 30 秒后抛出,但我在这里看不到 H12)。

在 SIGTERM 之后,Passenger 不应该允许一些默认时间来完成进程并正常关闭吗?我的配置中是否有我遗漏的东西?

标签: ruby-on-railsherokuerror-handlingpassengersigterm

解决方案


在 HTTP 请求-响应生命周期中,SIGTERM 可能会到达三个阶段:

  1. 请求仍在流式传输到服务器(在这种情况下,请求尚未完全接收,并且缺少一些数据)。

  2. 正在处理请求。

  3. 响应正在流式传输到客户端。

作为服务器作者(碘),可以选择保护哪些阶段免受与关闭相关的断开连接(如果有)。

(阶段1):

我很确定没有服务器会保护仍在流式传输的请求(这可能会使服务器在关闭过程中受到缓慢的客户端攻击)。

(第 2 阶段):

在请求处理期间,服务器本身就是客户端正在等待的那个。所有服务器(AFAIK)在继续关闭过程之前等待响应完成(或超时)。

(第 3 阶段):

限制传出流也是一种常见做法,以防止慢速客户端攻击,同时允许普通客户端完成下载响应。

在这个阶段,碘允许 10 秒,这是硬编码的。我找不到Passenger的任何配置选项,所以也许它也是一个硬编码的东西(或者它可能不存在)。


总结一下:我会考虑使用慢速客户端测试一些服务器并测试它们的关闭顺序。

无论您决定使用哪台服务器,某些客户端可能仍会突然断开连接。

这可能不是您可以控制或解决的问题,但您可以对其进行测试和最小化。

在 SIGTERM 之后,Passenger 不应该允许一些默认时间来完成进程并正常关闭吗?

这取决于乘客,不是要求。

此外,文档中没有控制此类设置的选项。这可能是一个重要的缺席(强烈表明乘客不支持此功能)。

我的配置中是否有我遗漏的东西?

nginx 配置不控制乘客配置。它们与学位相关联,但它们并不相同。

AFAIK 无法控制此关闭选项。


推荐阅读