messaging

RabbitMQ

Rabbit MQ


  • AMQP broker
  • AMQP defines messaging protocol (http://amqp.org)
  • Written in Erlang
  • Queues or Message destinations configured via the AMQP protocol 
  • Messages routed via Exchanges
  • Message Routing can be defined using client library (Ruby's amqp gem for example)
  • Message Store - File System based (in memory + disk) - http://www.rabbitmq.com/blog/2011/01/20/rabbitmq-backing-stores-databases-and-disks/

Active MQ


  • Broker, Messaging Bus
  • Supports AMQP protocol via configuration
  • AMQP not required though
  • Queues/Destination defined via configuration
  • Written in Java
  • JMS focussed
  • Can be used with other clients/languages
  • Default Message Store - KahaDB - file based message persistence database
  • Also supports most SQL based Databases as message store

MONGO DB


  • Capped Collection as a Message Bus
  • Message Store backed by Mongo
  • Suited for Pub/Sub
  • Node.js example (https://gist.github.com/3210919) mimics subscriber/broker behavior using "tailable" cursor

Rabbit MQ routing

rabbit mq routing

AMQP Exchange


  • Accepts messages from producer and routes them to message queues
  • Messages are always routed and published to Queues via Exchanges using pre-defined criteria called bindings
  • Binding - association between Exchange & Queue
  • Queue must be bound to at least one exchange to receive messages from publishers.
  • Exchange Types - Fanout, Direct, Topic, Headers
  • Message attribute routing_key is used by Exchange to route the message to its destination. Analogous to address.

Exchange


exchange = AMQP::Exchange.new(channel, :fanout, "nodes.metadata")

OR

exchange = channel.fanout("nodes.metadata")

Exchange/Queue Binding


  • Glue between Exchange and Queue

queue = channel.queue("queue.name", durable: true).bind(exchange)

queue.subscribe { |payload| puts "Queue #{queue.name} received #{payload}" }


Exchange - Fanout


Exchange - Direct


exchange - direct


exchange = AMQP::Exchange.new(channel, :direct, "nodes.metadata")

OR

exchange = channel.direct("nodes.metadata")

exchange - direct


queue = channel.queue("queue.name").bind(exchange, routing_key: "routing.key")

queue.subscribe { |payload| puts "Queue #{queue.name} on channel received #{payload}" }

exchange.publish("Hello, direct exchanges world!", routing_key: "routing.key")


routing key - pattern


channel.queue("us.california").bind(exchange, routing_key: "americas.north.us.ca.*").subscribe 
{ |metadata, payload| }

exchange.publish("San Diego update", routing_key: "americas.north.us.ca.sandiego")

exchange.publish("Berkeley update", routing_key: "americas.north.us.ca.berkeley")

AMQP Ruby library - Connection


require "amqp"

EventMachine.run do
  # using AMQP.connect with a block
  AMQP.connect(host: "localhost") do |connection|
    # connection is open and ready to be used
  end
end

AMQP RUBY LIBRARY - CONNECTION

require "amqp"

EventMachine.run do
  # using AMQP.connect with a block
  client = AMQP.connect(host: "localhost", username: "hedgehog", password: "pwd")
  
  # channel object used to create Exchange and Queue
  channel = AMQP::Channel.new(connection)
end

AmQp Queue


  • FIFO Message Buffers
  • Exchange route/store messages to Queue
  • Queue has a name to uniquely identify it
  • Queue are declared before they can be used
  • Declaring a queue will create it, if it does not exists
  • AMQP Broker will name a queue, if no name is provided by the client
  • Queue needs to bind to an exchange to receive messages
  • Queue Types - Durable Shared & Exclusive In-memory

AMQP - Durable queue


queue = AMQP::Queue.new(channel, "images.resize", durable: true)

Durable keys can be accessed by multiple consumers and from different process

AMQP - Exclusive queue


channel.queue("images.resize", auto_delete: true, exclusive: true)


Exclusive queues may only be accessed by the current connection and are deleted when that connection closes

messaging

By kapil