StupidBeauty
Read times:1653Posted at: - no title specified

RabbitMQ Ruby教程翻译: "世界妳好!" "Hello World!"

介绍

前提

本教程假设RabbitMQ已经安装,并且在localhost的标准端口(5672)上运行。如果妳用的是别的主机名、端口号或认证信息,那么,连接设置会需要进行调整。

如何寻求帮助

如果妳在学习本教程时遇到困难,那么,可通过邮件列表来与我们联系

RabbitMQ 是一个消息转发器。本质 上,它从 生产者 那里接收消息,然后将消息传递给 消费者 在这个过程中, 它可以按照妳设置的规则,对消息进行路由、缓存及持久存储。

RabbitMQ,以及一般的消息通信系统中,会使用一些术语。

  • •. 生产 ,意思就是,发送消息。 发送消息的程序,就称作 生产者 我们以下图来表示,圈圈 中带一个 "P"字母

  • •. 队列 ,是指,某个信箱的名字。 它存在于 RabbitMQ内部 。尽管消息 是在妳的应用程序及 RabbitMQ之间来回驰骋 ,但是,它们只能 被储存在 队列 内部。 队列 本身并无任何限制 妳可以根据自己的需要让它储存尽可能多的消息—— 它本质上是一个无限容量的缓冲区。 多个 生产者 可以 向同一个队列中发送消息 —― 多个 消费者 可以尝试从同一个队列中接收消息。队列 是以下图来表示的, 其顶部会带有它的名字:

  • •. 消费 ,其意义与接收类似。 消费 ,指的是,一个大部分时间在等待接收消息的程序。 我们以下图来表示消费者,圈圈中带有一个 "C"

注意,生产者、消费者和转发器并不一定是位于同一个机器上;实际上,大部分应用场景下,它们都不在同一个机器上。

"世界妳好"

(使用Bunny Ruby客户端)

在教程的这个部分, 我们会使用 Ruby 来写两个小程序;其中 会有一个生产者,用来发送单个消息 ,另外 有一个消费者,它会接收消息并且输出。 我们略过 Bunny  API 中的某些细节,只专注于尽快完成这个简单的示例,以便入门。 它是消息传递领域 的“世界妳好”。

在下图中,"P"表示生产者,"C"表示消费者。中间的盒子是一个队列——RabbitMQ 会根据消费者的行为来维护这个消息缓冲区。

Bunny客户端

RabbitMQ支持 的协议是 AMQP 0.9.1 ,它是一个开放 、通用用途的消息传递协议。 狠多不同的语言 中,有 狠多针对RabbitMQ 的客户端。 在本教程中,我们会使用Bunny 客户端。

首先 ,使用 Rubygems 来安装Bunny:

$ gem install bunny --version ">= 1.6.0"

好了,安装了Bunny之后,我们就可以写一些代码了。

发送

我们将消息发送代码放置在 send.rb 中,消息接收代码放置在 receive.rb 中。发送者,会连接到RabbitMQ,发送单条消息,然后退出。

send.rb 中,首先 要引入这个库:

#!/usr/bin/env ruby

# encoding: utf-8

require "bunny"

然后,连接到RabbitMQ服务器

conn = Bunny . new

conn . start

此处的连接对象,对套接字连接进行了抽象,它会为我们处理好以下事情:协议版本协商;身份认证;等等。在此示例中,我们全部使用默认设置,连接到本机运行的一个转发器。

如果我们想要连接到别的机器上运行着的转发器,那么,只需使用 :hostname 选项来指定它的名字或IP 地址即可:

conn = Bunny . new(:hostname => "rabbit.local")

conn . start

接下来,我们创建一个频道,我们完成任务所需的大部分API 都是位于这个对象中:

ch = conn . create_channel

要想发送,我们必须声明一个要向其中发送的队列;然后,我们就可以向该队列中发布消息:

q = ch . queue("hello")

ch . default_exchange . publish("Hello World!", :routing_key => q . name)

puts " [x] Sent 'Hello World!'"

声明队列的动作是幂等的——仅当它不存在的情况下,才会被创建。消息内容是一个字节数组,所以,妳可以在其中写入任意内容。

最后,我们关闭连接;

conn . close

此链接目标 是完整的 send.rb脚本内容

发送失败!

如果 这是妳第一次使用 RabbitMQ ,并且又未看到 "Sent"文字出现 ,那么, 妳可能会垂头丧气、抓耳挠腮、感叹民生之多艰。 这可能是因为,转发器启动时,空闲磁盘空间 不够 (默认情况 下,它需要至少 1Gb空闲空间) ,因而拒绝接收消息 。查看转发 器的日志文件以确认原因,在必要的情况下,减小限制 值。 配置文件文 会告诉妳该如何设置 disk_free_limit

接收

发送者就这些东西了。我们的接收器,会接收RabbitMQ 推送过来的消息,因此,不像发送者那样只发布单条消息,我们会保持接收者的运行,监听新的消息,并且将它们输出。

#!/usr/bin/env ruby

# encoding: utf-8

require "bunny"

初始设置代码与发送者相同;我们打开一个连接和一个频道,然后声明一个队列,我们将从该队列中接收消息。注意,这个队列的名字,应当与 send 向其中发布消息的那个队列的名字相同。

conn = Bunny . new

conn . start

ch = conn . create_channel

q = ch . queue("hello")

注意,这里我们同样声明了这个队列。因为,我们可能在启动发送者之前先启动接收者,这样的话,我们想要确保,在我们从队列中接收消息之前,队列就已经存在了。

接下来,我们要告诉服务器,将这个队列中的消息传递给我们。由于服务器是异步地向我们推送消息的,所以,我们提供一个回调函数,每当RabbitMQ 向我们的消费者推送消息时被执行。这是由 Bunny::Queue#subscribe 来完成的。

puts " [*] Waiting for messages in #{ q . name }. To exit press CTRL+C"

q . subscribe(:block => true) do | delivery_info, properties, body |

puts " [x] Received #{ body }"

# cancel the consumer to exit

delivery_info . consumer . cancel

end

Bunny::Queue#subscribe 中传递了 :block选项,使得它会阻塞住发起调用的线程(我们不希望这个脚本刚启动就结束运行了!)

此链接指向 receive.rb脚本 的完整代码。

将代码凑到一起

现在,我们可以执行这两个脚本了。打开一个终端,运行发送者:

$ ruby -rubygems send.rb

然后,运行接收者:

$ ruby -rubygems receive.rb

接收者,会将它通过RabbitMQ 从发送者那里接收到的消息输出。接收者会持续运行,等待新的消息(Ctrl-C来终止它),所以,try一try,打开另一个终端来运行发送者。

如果妳想查看该队列的相关信息,则,可以运行 rabbitmqctl list_queues

世界妳好!

是时候去学习 2 部分 了, 在那个教程中,将构建出一个简单的 工作队列

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands