我正在努力解决这个问题,任何帮助都会受到赞赏!
我有两个Rails应用程序,我们称之为客户端和服务,这些都是非常简单,正常的REST接口 - 这是基本场景:
同样,非常简单,只是服务处理是非常耗时的,可能需要几分钟。如果发生这种情况,客户端会在请求发出后60秒(无论ActiveResource :: Base.timeout设置为)时引发EOFError,同时服务正确处理请求并响应与200/201。这就是我们在日志中看到的(按时间顺序排列):
C 00:00:00: POST /resources.json
S 00:00:00: Received POST /resources.json => resources#create
C 00:01:00: EOFError: end of file reached
/usr/ruby1.8.7/lib/ruby/1.8/net/protocol.rb:135:in `sysread'
/usr/ruby1.8.7/lib/ruby/1.8/net/protocol.rb:135:in `rbuf_fill'
/usr/ruby1.8.7/lib/ruby/1.8/timeout.rb:62:in `timeout'
...
S 00:02:23: Response POST /resources.json, 201, after 143s
显然,服务响应从未到达客户端。我将错误追溯到套接字级别并在脚本中重新创建场景,我在其中打开TCPSocket并尝试检索数据。由于我没有要求任何东西,我不应该得到任何回报,我的请求应该在70秒后超时(参见底部的完整脚本):
Timeout::timeout(70) { TCPSocket.open(domain, 80).sysread(16384) }
这些是几个域的结果:
www.amazon.com => Timeout after 70s
github.com => EOFError after 60s
www.nytimes.com => Timeout after 70s
www.mozilla.org => EOFError after 13s
www.googlelabs.com => Timeout after 70s
maps.google.com => Timeout after 70s
正如您所看到的,一些服务器允许我们“等待”整整70秒,而其他服务器则终止了我们的连接,从而引发了EOFErrors。当我们针对我们的服务进行此测试时,我们(预期)在60秒后得到了一个EOFError。
有谁知道为什么会这样?有没有办法防止这些或延长服务器端超时?由于我们的服务继续“工作”,即使在套接字关闭后,我认为它必须在代理级别终止?
非常感谢每一个提示!
PS:完整的脚本:
require 'socket'
require 'benchmark'
require 'timeout'
def test_socket(domain)
puts "Connecting to #{domain}"
message = nil
time = Benchmark.realtime do
begin
Timeout::timeout(70) { TCPSocket.open(domain, 80).sysread(16384) }
message = "Successfully received data" # Should never happen
rescue => e
message = "Server terminated connection: #{e.class} #{e.message}"
rescue Timeout::Error
message = "Controlled client-side timeout"
end
end
puts " #{message} after #{time.round}s"
end
test_socket 'www.amazon.com'
test_socket 'github.com'
test_socket 'www.nytimes.com'
test_socket 'www.mozilla.org'
test_socket 'www.googlelabs.com'
test_socket 'maps.google.com'
答案 0 :(得分:2)
我知道这已经快一年了,但是如果有人发现这个,我想添加一个可能的罪魁祸首。
Amazon的ELB将在60秒后终止空闲连接,因此如果您在ELB后面使用EC2,那么ELB可能是服务器端问题。
答案 1 :(得分:0)
每台服务器决定何时关闭连接。这取决于服务器端软件及其设置。你无法控制它。