将大量消息发布到AMQP队列

时间:2011-08-17 21:49:30

标签: ruby amqp eventmachine

使用Ruby amqp库和Ruby 1.8.7的v0.7.1,我试图将大量(数百万)短(~40字节)消息发布到RabbitMQ服务器。我的程序的主循环(好吧,不是真正的循环,但仍然)看起来像这样:

AMQP.start(:host => '1.2.3.4', 
       :username => 'foo',
       :password => 'bar') do |connection|

  channel  = AMQP::Channel.new(connection)
  exchange = channel.topic("foobar", {:durable => true})
  i = 0

  EM.add_periodic_timer(1) do
    print "\rPublished #{i} commits"
  end

  results = get_results # <- Returns an array 

  processor = proc do
    if x = results.shift then
        exchange.publish(x, :persistent => true, 
                         :routing_key => "test.#{i}")
        i += 1
        EM.next_tick processor
      end
  end
  EM.next_tick(processor)
  AMQP.stop {EM.stop} end

代码开始处理结果数组就好了,但过了一会儿(通常是在12k消息之后),它会因以下错误而死掉

/Library/Ruby/Gems/1.8/gems/amqp-0.7.1/lib/amqp/channel.rb:807:in `send': 
The channel 1 was closed, you can't use it anymore! (AMQP::ChannelClosedError)

队列中不存储任何消息。当程序到队列服务器的网络活动开始时,似乎发生了错误。

我做错了什么?

1 个答案:

答案 0 :(得分:-1)

第一个错误是你没有发布你正在使用的RabbitMQ版本。许多人正在运行旧的过时版本1.7.2,因为这是他们的OS包存储库中的内容。发送大量邮件的人不好行动。从RabbitMQ站点获取RabbitMQ 2.5.1并删除默认系统包。

第二个错误是你没有告诉我们RabbitMQ日志中的内容。

第三个错误是你没有说消息的消息。是否有另一个进程在某个地方运行,该进程声明了一个队列并将其绑定到交换机。除非有人向RabbitMQ声明并将其绑定到交换机,否则有 NO 消息队列。即使这样,只有当队列的绑定密钥与您发布的路由密钥匹配时,消息才会流动。

第四个错误。您将路由键和绑定键混合在一起。路由键是一个字符串,例如topic.test.json.echos,绑定键(用于将队列绑定到交换机)是一个类似于主题的模式。#或topic。 .json。 < / p>

在您的澄清后更新 关于版本,我不确定它什么时候修复但1.7.2中存在大量持久性消息导致RabbitMQ在其持久性日志上滚动时崩溃的问题,并且在崩溃后无法重启直到有人手动解除翻滚。

当您说正在打开和关闭连接时,我希望它不是每封邮件。这将是一种使用AMQP的奇怪方式。

让我再说一遍。生产者 NOT 将消息写入队列。他们将消息写入交换机,然后根据路由密钥(字符串)和队列的绑定密钥(模式)将消息路由到队列。在你的例子中,我误读了#符号的使用,但我没有看到任何声明队列并将其绑定到交换的东西。