Fanout

Continuing my exploration of message queues…

A common MQ modality is publish/subscribe. A simplistic queue model has producers publishing messages directly to a queue and consumers taking messages off a queue. In the publish/subscribe model, the producer sends messages to an exchange, who’s only job is to publish messages to queues. In this scenario, the exchange knows to which queue(s) the message should be published according to established rules. The relationship between an exchange and a queue is called a binding.

Types of exchanges

  1. direct
  2. topic
  3. headers
  4. fanout – broadcasts every message it receives to all the queues it knows

Create a fanout exchange:

emit_log.rb
1
2
3
4
5
6
7
8
9
10
11
# create and start the connection
connection = Bunny.new()
connection.start
# create and start the channel
channel = connection.create_channel
# create the exchange:
exchange = channel.fanout('logs')
# publish to your named exchange:
exchange.publish(msg)
# close the connection
connection.close

Create a fanout worker

receive_log.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# create and start the connection
connection = Bunny.new()
conn.start
# create and start the channel
channel  = connection.create_channel
# name the exchange to listen to
exchange = ch.fanout("logs")
# name the queue
q = ch.queue("", :exclusive => true)
# bind the queue to the exchange
q.bind(exchange)
# subscribe to the bound queue
q.subscribe(:block => true) do |delivery_info, properties, body|
  puts " [x] #{body}"
end

In action

Start three terminals:

  1. $ ruby -rubygems receive_logs.rb > logs_from_rabbit.log
  2. $ ruby -rubygems receive_logs.rb
  3. $ ruby -rubygems emit_log.rb

In the last terminal, add a few more messages:

1
2
$ ruby -rubygems emit_log.rb this is a longer message
$ ruby -rubygems emit_log.rb this message should be logged in a file AND appear in my terminal window

The output in terminal 2:

1
2
3
4
5
$ ruby -rubygems receive_logs.rb
 [*] Waiting for logs. To exit press CTRL+C
 [x] Hello World!
 [x] this is a longer message
 [x] this message should be logged in a file AND appear in my terminal

The output from the log file:

1
2
3
4
5
$ cat logs_from_rabbit.log
 [*] Waiting for logs. To exit press CTRL+C
 [x] Hello World!
 [x] this is a longer message
 [x] this message should be logged in a file AND appear in my terminal

Resources