RabbitMQ is a lightweight, reliable, scalable and portable message broker. But unlike many message brokers familiar to Java developers, it's not based on JMS. Instead, your applications communicate with it via a platform-neutral, wire-level protocol: the Advanced Message Queuing Protocol (AMQP). Fortunately there's already a Java client library and SpringSource is working on first class Spring and Grails integration - so don't worry about having to do low-level stuff to use RabbitMQ. You can even find AMQP client libraries that expose a JMS interface. But AMQP is sufficiently different in operation from JMS that it might cause headaches for Java developers that are used to the JMS model.

In order to ease the transition, I'll be looking in this post at the basic concepts that underpin AMQP along with three common usage scenarios. By the end, you will hopefully have a good enough understanding to configure RabbitMQ and use it via the APIs provided by Spring and Grails.

Exchanges, queues, and bindings

Like any messaging system, AMQP is a message protocol that deals with publishers and consumers. The publishers produce the messages, the consumers pick them up and process them. It's the job of the message broker (such as RabbitMQ) to ensure that the messages from a publisher go to the right consumers. In order to do that, the broker uses two key components: exchanges and queues. The following diagram shows how they connect a publisher to a consumer:

As you can see, the setup is pretty straightforward. A publisher sends messages to a named exchange and a consumer pulls messages from a queue (or the queue pushes them to the consumer depending on the configuration). Of course, the connections have to be made in the first place, so how do publishers and consumers discover each other? Via the name of the exchange. Usually, either the publisher or consumer creates the exchange with a given name and then makes that name public. How that publication happens depends on the circumstances, but one might put it in public API documentation or send it to known clients.

How are the messages routed from the exchange to the queue? Good question. First, the queue has to be attached to the given exchange. Typically, a consumer creates a queue and attaches it to an exchange at the same time. Second, messages received by the exchange have to be matched to the queue - a process called "binding".

To understand binding, it's useful to understand the structure of an AMQP message:

The headers and properties of the message are basically key/value pairs. The difference between them is that headers are defined by the AMQP specification whereas properties can contain arbitrary, application-specific information. The actual message content is just a sequence of bytes, so if you want to pass text around in your messages, then you should standardise on an encoding. UTF-8 is a good bet. You can specify a content type and encoding in the message headers if you want, but that's apparently not particularly common.

What does this have to do with binding? One of the standard headers is called routing-key and it is this that the broker uses to match messages to queues. Each queue specifies a "binding key" and if that key matches the value of the routing-key header, the queue receives the message.

Things are slightly complicated by the concept of exchange types. The AMQP spec. defines the following four types:

EXCHANGE TYPE BEHAVIOUR
Direct The binding key must match the routing key exactly - no wildcard support.
Topic Same as Direct, but wildcards are allowed in the binding key. '#' matches zero or more dot-delimited words and '*' matches exactly one such word.
Fanout The routing and binding keys are ignored - all published messages go to all bound queues.
Headers  

Update I corrected the information on wildcards, which work on the basis of dot-delimited words or terms.

For example, say a publisher sends a message with a routing key of "NYSE" to a topic exchange called "Stocks". If a consumer creates a queue attached to "Stocks" with a binding key of "#", "*", or "NYSE", then that consumer will get the message because all three binding keys match "NYSE". However, if the message is published to a direct exchange, then the consumer will not get the message if the binding key is "#" or "*" since those characters are treated as literals, not wildcards. Interestingly, "#.#" will also match "NYSE" despite the routing key not having a dot.

Now consider a message with a routing key of "NYSE.TECH.MSFT". What binding keys will match it given that the message is going to a topic exchange?

BINDING KEY MATCH?
NYSE.TECH.MSFT Yes
# Yes
NYSE.# Yes
*.* No
NYSE.* No
NYSE.TECH.* Yes
NYSE.*.MSFT Yes

That's really all there is to it. Flexibility is provided by support for multiple consumers per queue and multiple queues per exchange. In fact, a single queue can even be bound to multiple exchanges. Now let's look at some of those scenarios.

RPC

An AMQP broker can act as an RPC mechanism between a client and a service. The general setup is like this, using a direct exchange:

The general sequence goes:

  1. Client sends message to the queue, specifying: (a) a routing key that matches the service; and (b) the name of a queue to pick the response up from.
  2. Exchange passes the message to the service's queue ("ops_q" in this case).
  3. The queue pushes the message to the service, which then does some work and sends a response message back to the exchange, specifying a routing_key that matches the reply queue.
  4. The client picks the response message off the reply queue.

From the perspective of the client, the call could either be blocking or non-blocking. How easy it is to do one or the other, though, depends on the client library in use.

The key to the RPC scenario is making sure that the client and service are using the same exchange for the initial request and that the client knows what to specify for the routing key.

As for the reply queue, it's typically created by the client, which then populates the reply_toheader appropriately. Also, although you can use a different exchange for the replies compared to the requests, it's much more common to use the same exchange for both requests and replies.

Pub(lish)/Sub(scribe)

JMS has the concept of topic queues that ensure that messages from a publisher go to all subscribers. You can easily achieve the same behaviour in AMQP by binding multiple queues to an exchange like so:

Even better, the queues can filter which messages they receive via the binding key. If a consumer wants to receive all messages, then it can specify a binding key of "#" - the "match any number of words" wildcard. Rather confusingly for your average developer, "*" matches zero or one (dot-delimited) words as mentioned earlier.

Work distribution

Imagine you have an application that has a bunch of jobs that need executing. With AMQP, you can hook up multiple consumers such that each job goes to one, and only one, of those consumers. The publisher doesn't care which consumer does the work, just that the work is done. This is work distribution.

Configuring it is pretty straightforward, as shown in this diagram:

So you have one queue bound to the exchange with multiple consumers sharing that queue. This setup guarantees that only one consumer processes a given message, no matter how many consumers there are.

Those are the three main usage patterns for AMQP brokers. Although I have described each individually, it's fairly common to combine them. For example, you could have multiple services sharing the same queue (work distribution) in the RPC pattern. It's really up to you to decide how to configure the exchanges and queues, and now you should have a good enough understanding to work out the appropriate setup for your situation.

If you want to go further into AMQP, then check out the specification itself, particularly the section on General Architecture. And to get started with RabbitMQ, just go to its website.

reference from:

http://spring.io/blog/2010/06/14/understanding-amqp-the-protocol-used-by-rabbitmq/

Understanding AMQP, the protocol used by RabbitMQ--reference的更多相关文章

  1. Serial Communication Protocol Design Hints And Reference

    前面转载的几篇文章详细介绍了UART.RS-232和RS-485的相关内容,可以知道,串口通信的双方在硬件层面需要约定如波特率.数据位.校验位和停止位等属性,才可以正常收发数据.实际项目中使用串口通信 ...

  2. Spring Boot Reference Guide

    Spring Boot Reference Guide Authors Phillip Webb, Dave Syer, Josh Long, Stéphane Nicoll, Rob Winch,  ...

  3. What is AMQP? and the architecture

    What is AMQP? (Advanced Message Queuing Protocol) When two applications need to communicate there ar ...

  4. AMQP 0-9-1 Model Explained Why does the queue memory grow and shrink when publishing/consuming? AMQP和AMQP Protocol的是整体和部分的关系 RabbitMQ speaks multiple protocols.

    AMQP 0-9-1 Model Explained — RabbitMQ http://next.rabbitmq.com/tutorials/amqp-concepts.html AMQP 0-9 ...

  5. AMQP 0.9.1和1.0协议差别以及rabbitmq支持情况

    RabbitMQ implements AMQP 1.0 via a plugin. However, AMQP 1.0 is a completely different protocol than ...

  6. 深入剖析 RabbitMQ —— Spring 框架下实现 AMQP 高级消息队列协议

    前言 消息队列在现今数据量超大,并发量超高的系统中是十分常用的.本文将会对现时最常用到的几款消息队列框架 ActiveMQ.RabbitMQ.Kafka 进行分析对比.详细介绍 RabbitMQ 在 ...

  7. 二、RabbitMQ简介及AMQP协议

    RabbitMQ简介 RabbitMQ是开源的消息代理和队列服务器,是由Erlang语言开发的,基于AMQP协议(Advanced Message Queuing Protocol高级消息队列协议)的 ...

  8. PHP 下基于 php-amqp 扩展的 RabbitMQ 简单用例 (一) -- 安装 AMQP 扩展和 Direct Exchange 模式

    Windows 安装 amqp 扩展 RabbitMQ 是基于 amqp(高级消息队列协议) 协议的.使用 RabbitMQ 前必须为 PHP 安装相应的 amqp 扩展. 下载相应版本的 amqp ...

  9. RabbitMQ 的消息持久化与 Spring AMQP 的实现剖析

    文章目录 1. 原生的实现方式 2. Spring AMQP 的实现方式   要从奔溃的 RabbitMQ 中恢复的消息,我们需要做消息持久化.如果消息要从 RabbitMQ 奔溃中恢复,那么必须满足 ...

随机推荐

  1. 【转】 iOS开发 剖析网易新闻标签栏视图切换(addChildViewController属性介绍)

    原文:http://blog.csdn.net/hmt20130412/article/details/34523235 本来只是打算介绍一下addChildViewController这个方法的,正 ...

  2. 手把手教你DIY一个春运迁徙图(一)

    换了新工作,也确定了我未来数据可视化的发展方向.新年第一篇博客,又逢春运,这篇技术文章就来交给大家如何做一个酷炫的迁徙图(支持移动哦).(求star 代码点这里) 迁徙图的制作思路分为静态的元素和变换 ...

  3. Cisco CatOS系统交换机的SPAN配置

    以下内容摘自最新上市的“四大金刚”图书之一<Cisco交换机配置与管理完全手册>(第二版)(其它三本分别为<Cisco路由器配置与管理完全手册>(第二版).<H3C交换机 ...

  4. JQuery在光标位置插入内容

    (function($) { $.fn.extend({ insertAtCaret: function(myValue) { var $t = $(this)[0]; //IE if (docume ...

  5. Aptana Studio 快捷键

    窗口 Ctrl+ Shift +L 调出快捷键提示 Ctrl+ W 关闭当前标签窗口 Ctrl+ Shift + W 关闭当前标签窗口 Ctrl+ F6 (或者是Aptana的Ctrl+Tab )下一 ...

  6. 『Python』 多线程 端口扫描器

    0x 00 Before Coding 当端口打开时,向端口发送 TCP SYN 请求,会返回一个 ACK 响应: 当端口关闭,返回的是 RST 响应: 0x 01 Coding  可以用 socke ...

  7. Cracking the coding interview--Q2.3

    Implement an algorithm to delete a node in the middle of a singly linked list,given only access to t ...

  8. Android 有趣味的GridView

    工作这么久以来,都是以解决需求为目标.渐渐发现这种学习方式不好,学到的知识能马上解决问题,但没有经过梳理归纳.故想系统总结下一些有趣味的知识点.在这篇博客中想以一个例子系统讲解下GridView控件涉 ...

  9. 【HDOJ】1208 Pascal's Travels

    记忆化搜索.注意当除右下角0外,其余搜索到0则返回. #include <algorithm> #include <cstdio> #include <cstring&g ...

  10. 王学长的LCT标程

    善良的王学长竟然亲自打了一遍QAQ好感动QAQ #include<iostream> #include<cstdio> #include<cmath> #inclu ...