RuntimeError:在 Rack 中的迭代期间无法将新密钥添加到哈希中

Posted

技术标签:

【中文标题】RuntimeError:在 Rack 中的迭代期间无法将新密钥添加到哈希中【英文标题】:RuntimeError: can't add a new key into hash during iteration in Rack 【发布时间】:2018-05-25 21:33:18 【问题描述】:

我构建了一个非常小的 Rails 5.1.4 (Ruby 2.3.1) 应用程序。将其部署到生产环境后,我会不时收到此特定错误:

RuntimeError: can't add a new key into hash during iteration

指向这里:

# rack/request.rb, line 67
def set_header(name, v)
  @env[name] = v
end

我了解,当您在迭代该哈希时尝试向该哈希添加新键时会发生此错误。因为@env 是一个哈希,所以它是有道理的。但是:

    在堆栈跟踪中,我没有发现任何与 @env 上的迭代相关的内容,这是一个简单的 app.call(env) 调用链。 这个错误并不总是发生,而是一两个小时发生一次,所以这对我来说也很奇怪 我无法在本地重现它:我尝试加载具有多个请求命中的服务器,假设这可能是线程安全问题,但在本地它就像一个魅力...

完整的堆栈跟踪仅包含机架中间件,可在此处找到: https://gist.github.com/Nattfodd/e513122400b4115a653ea38d69917a9a

Gemfile.lock: https://gist.github.com/Nattfodd/a9015e9204544302bf3959cec466b715

服务器使用 puma 运行,配置非常简单:只是线程和工作线程的数量:

threads 0, 5
workers 5

我目前的想法是:

其中一个监控 gem 存在错误(sentry-raven、new_relic) concurrent-ruby 有一个错误(我读过一个,但它在 1.0.2 中已修复,而我用于 Puma 的实际版本是 1.0.5) 一些超级愚蠢的东西,我错过了,但我不知道在哪里看,因为控制器的操作包含 3 行代码,并且应用程序配置大多是默认的... 这与配置有关,因为回溯根本不包含控制器...

【问题讨论】:

你有想过这个吗?我有同样的问题 是的,原因是newrelic_rpm 最新版本。仍然不知道究竟是什么导致了 newrelic gem 中的这个错误。 感谢您的回复。关于使用哪个版本的新遗物稳定且不会导致此问题的任何建议? 4.6.0 肯定坏了,不能说是 4.7 还是 4.5 还可以——我还没有测试过 一个类似的错误已经间歇性地影响我的生产应用程序 2 年多,在 unicorn 和 puma 上,newrelic_rpm 的版本范围从 v3.16.0.318 到 v4.8.0.341。一个区别是我的堆栈跟踪的顶部位于 aws-sdk 客户端连接池处理程序 (issue) 中,但由于这没有出现任何明显的问题,我越来越怀疑 New Relic 检测是罪魁祸首。我的堆栈跟踪的另一个共同点是它还包括 sinatra + activerecord- 也许这也相关? 【参考方案1】:

你能粘贴完整的堆栈跟踪吗? 我的假设是 set_header 是从迭代 env 的方法中调用的。

【讨论】:

完整堆栈跟踪的链接在我的问题中 - gist.github.com/Nattfodd/e513122400b4115a653ea38d69917a9a

以上是关于RuntimeError:在 Rack 中的迭代期间无法将新密钥添加到哈希中的主要内容,如果未能解决你的问题,请参考以下文章

是否有解决方案绕过“无法在迭代期间将新密钥添加到哈希(RuntimeError)”?

递归:如何避免 Python set changed set 在迭代 RuntimeError 期间

通过 DataLoader (PyTorch) 迭代:RuntimeError: 标量类型 unsigned char 的预期对象但序列元素 9 的标量类型浮点数

RuntimeError:字典迭代过程中改变大小 - 如何解决?

Rack / Rails 中的 HTTP/2 支持

Ruby/Rack 中的单点登录服务器身份验证