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 в сам метод обратного вызова.

Другие вопросы по тегам