使用EM-HTTP消耗队列:无法创建新套接字:打开的文件过多

时间:2013-02-08 11:44:39

标签: ruby rabbitmq amqp eventmachine

我有一个使用amqp gem从RabbitMQ队列中消耗msgs的ruby进程,如下所示:

require "bundler/setup"
require "amqp"
require 'eventmachine'
require 'em-http'


AMQP.start(:host => $AMQP_URL) do |connection|
  @channel ||= AMQP::Channel.new(connection)
  @queue   ||= @channel.queue("results")

  puts " [*] Waiting for messages. "

  @queue.subscribe do |body|    
    http = EventMachine::HttpRequest.new(URL).post :body => body          

    http.callback {
      # do something
    }        

    http.errback  { 
      $LOG.error "[errorback] -> #{http.error}"    
    }
  end
end

现在网址很慢,队列中有很多消息(> 30K),我在日志中遇到了这个错误:

**[errorback] -> unable to create new socket: Too many open files** 

任何帮助都会受到高度赞赏,因为我一直在努力寻找如何解决它,但根本没有任何结果。

提前致谢

1 个答案:

答案 0 :(得分:5)

您消息太快了。由于您基本上一次获取所有未传递的消息(即,与RabbitMQ可以提供它们一样快),并为每条消息打开HTTP连接,您最终会消耗系统的所有可用资源(在这种情况下是并行打开的套接字的数量)

在阅读message acknowledgementsAMQP::Queue#subscribe上的文档后,我建议您对代码进行以下更改:

AMQP.start(host: $AMQP_URL) do |connection|
  @channel ||= AMQP::Channel.new(connection)
  @channel.prefetch(5) 
  @queue ||= @channel.queue("results")

  # disable auto-ack, switch to manual mode
  @queue.subscribe(ack: true) do |meta, body|
    http = EventMachine::HttpRequest.new(URL).post body: body          

    http.callback {
      # do something

      # acknowledge message consumption
      meta.ack
    }

    http.errback {
      # ...
      # do not `meta.ack` here, so the message gets redelivered
    }
  end
end

这样,您可以非常轻松地节省工作量。