我只想从Rails控制器内部访问服务器,但不等待响应。这可能吗?(由于性能原因,如果不启动其他线程,则无法执行此操作)
可以通过打开一个插座然后关闭它来实现。这将建立连接并关闭连接,而不会在连接上下文内传输任何数据...
...您将需要等待连接打开-尽管可能有避免该连接的方法。
require 'socket'
# opens a connection, will wait for connection but not for data.
s = TCPSocket.new 'host.url.com', 80
# closes the connection
s.close
它可能与ping等效,并且不会打开新线程...尽管它不是完全异步的。
使用HTTP请求,代码可能看起来像这样:
require 'socket'
host = 'www.google.com'
# opens a connection, will wait for connection but not for data.
s = TCPSocket.new host, 80
# send a GET request for '/' .
s.puts "GET / HTTP/1.1\r\nHost: #{host}\r\n\r\n"
# closes the connection
s.close
您可以在堆栈交换中搜索有关HTTP请求的更多信息,并获得一些想法,例如here。
只是为了澄清(由于评论):
这将引入与建立连接(和发送请求)相关的延迟,但是您将不必等待处理和接收答复。
断开连接(关闭套接字的一半)可能会产生以下任何一种效果-所有这些都假设是一个不错的Web服务器:
如果s.close
在Web服务器完全发送响应之前完成,则Web服务器将首先处理该请求,然后在尝试发送数据时Web服务器的套接字上将引发异常。然后,Web服务器应关闭套接字并释放所有资源。
如果s.close
在响应完全由Web服务器发送之后完成,则服务器可能:1.立即关闭套接字(正常的HTTP 1行为),或2.保持连接直到发生超时(可选的HTTP 1.1行为)-超时通常约为10秒。
以很小的间隔反复击中Web服务器可能会导致DOS安全标志被提升并且以后的连接将被阻止(无论您如何打Web服务器,都是如此)。
我可能会选择使用工作线程,如下所示:
我确实相信运行单独的线程可能不会像您认为的那样昂贵。所有异步Web请求可能只有一个线程周期。
这是一个想法:
require 'socket'
REQUESTS_MUTEX = Mutex.new
REQUESTS_QUE = []
REQUESTS_THREAD = Thread.new do
begin
loop do
sleep 0.5 while REQUESTS_QUE.empty?
host, path = REQUESTS_MUTEX.synchronize {REQUESTS_QUE.shift}
# the following will open a connection and start a request,
# but it's easier to use the built in HTTP API...
# although it will wait for a response.
s = TCPSocket.new host, 80
s.puts "GET #{path} HTTP/1.1\r\nHost: #{host}\r\n\r\n"
s.close
# log here:
puts "requested #{path} from #{host}."
end
rescue Exception => e
retry
end
end
def asynch_request host, path = '/'
REQUESTS_MUTEX.synchronize {REQUESTS_QUE << [host, path]}
REQUESTS_THREAD.alive?
end
现在,对于每个请求,您都可以简单地调用asynch_request
,并且循环线程应该在唤醒并注意到队列后立即访问Web服务器。
您可以通过在终端中粘贴一些请求来对它进行测试:
asynch_request 'www.google.com'
asynch_request 'www.yahoo.com'
asynch_request 'I.Dont.exist.com'
asynch_request 'very bad host address...'
asynch_request 'www.github.com'
注意静默失败(您可以调整代码)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句