EventMachine не может ответить при использовании отложенного
Это мой сервер
require 'rubygems'
require 'benchmark'
require 'eventmachine'
class Handler < EventMachine::Connection
def initialize(*args)
super
end
def receive_data(data)
@state = :processing
EventMachine.defer(method(:do_something), method(:callback))
#EM.defer(operation, callback)
rescue Exception => ex
LOGGER.error "#{ex.class}: #{ex.message}\n#{ex.backtrace.join("\n")}"
ensure
close_connection_after_writing unless @state == :processing
end
def do_something
#simulate a long running request
for i in 1..1000
a << rand(1000)
a.sort!
end
return "response from server"
end
def callback(msg)
self.send_data msg
@state = :closing
end
def unbind
close_connection_after_writing unless @status == :process
end
end
EventMachine::run {
EventMachine.epoll
EventMachine::start_server("0.0.0.0", 8080, Handler)
puts "Listening..."
}
Это мой клиент
require 'rubygems'
require 'benchmark'
require 'socket'
require 'logger'
Benchmark.bm do |x|
logger = Logger.new('test.log', 10, 1024000)
logger.datetime_format = "%Y-%m-%d %H:%M:%S"
x.report("times:") do
for i in 1..10
#Thread.new do
TCPSocket.open "127.0.0.1", 8080 do |s|
s.send "#{i}th sending\n", 0
if result = s.recv(100)
logger.info result
end
puts "#{i}th sending"
#end
end
end
end
end
Когда я запускаю свой клиент, сервер не может получать данные, поэтому я меняю свой сервер следующим образом
require 'rubygems'
require 'benchmark'
require 'eventmachine'
class Handler < EventMachine::Connection
def initialize(*args)
super
end
def receive_data(data)
operation = proc do
# simulate a long running request
a = []
for i in 1..1000
a << rand(1000)
a.sort!
end
end
# Callback block to execute once the request is fulfilled
callback = proc do |res|
send_data "data from server"
end
puts data
EM.defer(operation, callback)
end
end
EventMachine::run {
EventMachine.epoll
EventMachine::start_server("0.0.0.0", 8080, Handler)
puts "Listening..."
}
Это работает, я хочу знать, почему мой первый сервер не может работать правильно
1 ответ
Проблема в первом сервере: вы никогда не определяли a = []
Таким образом, исключение было брошено. Это исключение, по сути, прервет обработку потока. Обратный вызов никогда не будет выполнен, и сервер никогда не ответит.
поскольку EM.defer
работает в потоке, rescue
заявление в received_data
не будет иметь никакого эффекта. Вам нужно спасение в do_something
способ перехвата любых исключений, которые происходят во время обработки.
ensure
блокировать в receive_data
также не будет иметь никакого эффекта, так как EM.defer
немедленно вернется, и этот блок кода завершится. @state
никогда не будет настроен на что-то другое, то :processing
в таком случае.
Вы хотите переместить close_connection_after_writing
в сам метод обратного вызова.