进行HTTP调用时在Ruby中频繁进行SystemExit

时间:2020-03-05 18:37:22  来源:igfitidea点击:

我有一个Ruby on Rails网站,可以对外部Web服务进行HTTP调用。

大约每天一次,我会收到一条SystemExit(以下堆栈跟踪)错误电子邮件,其中对该服务的调用失败。如果稍后再尝试在我的网站上使用完全相同的查询,它将正常工作。
自该网站上线以来,这种情况一直在发生,而且我一直没有找到原因的运气。

Ruby是1.8.6版,而rails是1.2.6版。

还有其他人有这个问题吗?

这是错误和堆栈跟踪。

A SystemExit occurred
  /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.6/lib/fcgi_handler.rb:116:in
  exit'
  /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.6/lib/fcgi_handler.rb:116:in
  exit_now_handler'
  /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/inflector.rb:250:in
  to_proc' /usr/local/lib/ruby/1.8/net/protocol.rb:133:in call'
  /usr/local/lib/ruby/1.8/net/protocol.rb:133:in sysread'
  /usr/local/lib/ruby/1.8/net/protocol.rb:133:in rbuf_fill'
  /usr/local/lib/ruby/1.8/timeout.rb:56:in timeout'
  /usr/local/lib/ruby/1.8/timeout.rb:76:in timeout'
  /usr/local/lib/ruby/1.8/net/protocol.rb:132:in rbuf_fill'
  /usr/local/lib/ruby/1.8/net/protocol.rb:116:in readuntil'
  /usr/local/lib/ruby/1.8/net/protocol.rb:126:in readline'
  /usr/local/lib/ruby/1.8/net/http.rb:2017:in read_status_line'
  /usr/local/lib/ruby/1.8/net/http.rb:2006:in read_new'
  /usr/local/lib/ruby/1.8/net/http.rb:1047:in request'
  /usr/local/lib/ruby/1.8/net/http.rb:945:in request_get'
  /usr/local/lib/ruby/1.8/net/http.rb:380:in get_response'
  /usr/local/lib/ruby/1.8/net/http.rb:543:in start'
  /usr/local/lib/ruby/1.8/net/http.rb:379:in get_response'

解决方案:

众所周知,将fcgi与Ruby一起使用会带来很多麻烦。

出于这个原因,几乎每个人都搬到了Mongrel,我建议我们也这样做。

自从我使用FCGI已经有一段时间了,但是我认为如果线程花费的时间太长,FCGI进程可能会抛出SystemExit。这可能是Web服务没有响应,甚至是缓慢的DNS查询。谷歌的一些结果表明,Python和FCGI出现了类似的错误,因此改用杂种是个好主意。这篇文章是我用来设置杂种的参考,现在我仍然参考它。

我也会看看旅客。它比Apache / nginx + Mongrel的传统## 解决方案容易得多。

我以前一直在Apache1 / fastcgi上获取这些信息。我认为这是由于fastcgi在Ruby完成之前就挂断了。

切换到杂种是不错的第一步,但是还有更多工作要做。从实时页面上的Web服务中剔除是个坏主意,尤其是从Rails中剔除。 Rails不是线程安全的。我们可以支持的并发连接数等于集群中的杂项(或者"乘客"进程)数。

如果我们有一个杂种,并且有人访问一个调用Web服务的页面,该页面花费了10秒钟的超时时间,则对该网站的每个请求都将在该时间段内超时。大多数负载均衡器只是盲目地循环访问杂项,因此,如果我们有两个杂项,则其他每个请求都会超时。

任何可能出乎意料的缓慢的事情都需要在作业队列中发生。 / slow / action的第一个匹配项将作业添加到队列中,并且/ slow / action继续通过页面刷新或者ajax进行刷新,直到作业完成,然后我们才能从作业队列中获取结果。如今,Rails的工作队列很少,但是最古老且可能使用最广泛的队列是BackgroundRB。

根据应用程序的性质,另一种替代方法是每隔N分钟通过cron删除服务,在本地缓存数据,并从缓存中读取实时页面。