269 lines
19 KiB
XML
269 lines
19 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!-- ============================================================================= -->
|
||
<!-- Copyright © 2009 Red Hat, Inc. and others. -->
|
||
<!-- -->
|
||
<!-- The text of and illustrations in this document are licensed by Red Hat under -->
|
||
<!-- a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). -->
|
||
<!-- -->
|
||
<!-- An explanation of CC-BY-SA is available at -->
|
||
<!-- -->
|
||
<!-- http://creativecommons.org/licenses/by-sa/3.0/. -->
|
||
<!-- -->
|
||
<!-- In accordance with CC-BY-SA, if you distribute this document or an adaptation -->
|
||
<!-- of it, you must provide the URL for the original version. -->
|
||
<!-- -->
|
||
<!-- Red Hat, as the licensor of this document, waives the right to enforce, -->
|
||
<!-- and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent -->
|
||
<!-- permitted by applicable law. -->
|
||
<!-- ============================================================================= -->
|
||
|
||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||
<!ENTITY % BOOK_ENTITIES SYSTEM "HornetQ_User_Manual.ent">
|
||
%BOOK_ENTITIES;
|
||
]>
|
||
<chapter id="messaging-concepts">
|
||
<title>Messaging Concepts</title>
|
||
<para>HornetQ is an asynchronous messaging system, an example of <ulink
|
||
url="http://en.wikipedia.org/wiki/Message_oriented_middleware">Message Oriented
|
||
Middleware</ulink> , we'll just call them messaging systems in the remainder of this
|
||
book.</para>
|
||
<para>We'll first present a brief overview of what kind of things messaging systems do,
|
||
where they're useful and the kind of concepts you'll hear about in the messaging
|
||
world.</para>
|
||
<para>If you're already familiar with what a messaging system is and what it's capable of, then
|
||
you can skip this chapter.</para>
|
||
<section>
|
||
<title>Messaging Concepts</title>
|
||
<para>Messaging systems allow you to loosely couple heterogeneous systems together, whilst
|
||
typically providing reliability, transactions and many other features.</para>
|
||
<para>Unlike systems based on a <ulink
|
||
url="http://en.wikipedia.org/wiki/Remote_procedure_call">Remote Procedure
|
||
Call</ulink> (RPC) pattern, messaging systems primarily use an asynchronous message
|
||
passing pattern with no tight relationship between requests and responses. Most
|
||
messaging systems also support a request-response mode but this is not a primary feature
|
||
of messaging systems.</para>
|
||
<para>Designing systems to be asynchronous from end-to-end allows you to really take
|
||
advantage of your hardware resources, minimizing the amount of threads blocking on IO
|
||
operations, and to use your network bandwidth to its full capacity. With an RPC approach
|
||
you have to wait for a response for each request you make so are limited by the network
|
||
round trip time, or <emphasis role="italic">latency</emphasis> of your network. With an
|
||
asynchronous system you can pipeline flows of messages in different directions, so are
|
||
limited by the network <emphasis role="italic">bandwidth</emphasis> not the latency.
|
||
This typically allows you to create much higher performance applications.</para>
|
||
<para>Messaging systems decouple the senders of messages from the consumers of messages. The
|
||
senders and consumers of messages are completely independent and know nothing of each
|
||
other. This allows you to create flexible, loosely coupled systems.</para>
|
||
<para>Often, large enterprises use a messaging system to implement a message bus which
|
||
loosely couples heterogeneous systems together. Message buses often form the core of an
|
||
<ulink url="http://en.wikipedia.org/wiki/Enterprise_service_bus">Enterprise Service
|
||
Bus</ulink>. (ESB). Using a message bus to de-couple disparate systems can allow the
|
||
system to grow and adapt more easily. It also allows more flexibility to add new systems
|
||
or retire old ones since they don't have brittle dependencies on each other.</para>
|
||
</section>
|
||
<section>
|
||
<title>Messaging styles</title>
|
||
<para>Messaging systems normally support two main styles of asynchronous messaging: <ulink
|
||
url="http://en.wikipedia.org/wiki/Message_queue"> message queue</ulink> messaging
|
||
(also known as <emphasis role="italic">point-to-point messaging</emphasis>) and <ulink
|
||
url="http://en.wikipedia.org/wiki/Publish_subscribe">publish subscribe</ulink>
|
||
messaging. We'll summarise them briefly here:</para>
|
||
<section>
|
||
<title>The Message Queue Pattern</title>
|
||
<para>With this type of messaging you send a message to a queue. The message is then
|
||
typically persisted to provide a guarantee of delivery, then some time later the
|
||
messaging system delivers the message to a consumer. The consumer then processes the
|
||
message and when it is done, it acknowledges the message. Once the message is
|
||
acknowledged it disappears from the queue and is not available to be delivered
|
||
again. If the system crashes before the messaging server receives an acknowledgement
|
||
from the consumer, then on recovery, the message will be available to be delivered
|
||
to a consumer again.</para>
|
||
<para>With point-to-point messaging, there can be many consumers on the queue but a
|
||
particular message will only ever be consumed by a maximum of one of them. Senders
|
||
(also known as<emphasis role="italic"> producers</emphasis>) to the queue are
|
||
completely decoupled from receivers (also known as <emphasis role="italic"
|
||
>consumers</emphasis>) of the queue - they do not know of each other's
|
||
existence.</para>
|
||
<para>A classic example of point to point messaging would be an order queue in a
|
||
company's book ordering system. Each order is represented as a message which is sent
|
||
to the order queue. Let's imagine there are many front end ordering systems which
|
||
send orders to the order queue. When a message arrives on the queue it is persisted
|
||
- this ensures that if the server crashes the order is not lost. Let's also imagine
|
||
there are many consumers on the order queue - each representing an instance of an
|
||
order processing component - these can be on different physical machines but
|
||
consuming from the same queue. The messaging system delivers each message to one and
|
||
only one of the ordering processing components. Different messages can be processed
|
||
by different order processors, but a single order is only processed by one order
|
||
processor - this ensures orders aren't processed twice.</para>
|
||
<para>As an order processor receives a message, it fulfills the order, sends order
|
||
information to the warehouse system and then updates the order database with the
|
||
order details. Once it's done that it acknowledges the message to tell the server
|
||
that the order has been processed and can be forgotten about. Often the send to the
|
||
warehouse system, update in database and acknowledgement will be completed in a
|
||
single transaction to ensure <ulink url="http://en.wikipedia.org/wiki/ACID"
|
||
>ACID</ulink> properties.</para>
|
||
</section>
|
||
<section>
|
||
<title>The Publish-Subscribe Pattern</title>
|
||
<para>With publish-subscribe messaging many senders can send messages to an entity on
|
||
the server, often called a <emphasis role="italic">topic</emphasis> (e.g. in the JMS
|
||
world).</para>
|
||
<para>There can be many <emphasis>subscriptions</emphasis> on a topic, a subscription is
|
||
just another word for a consumer of a topic. Each subscription receives a
|
||
<emphasis>copy</emphasis> of <emphasis role="italic">each</emphasis> message
|
||
sent to the topic. This differs from the message queue pattern where each message is
|
||
only consumed by a single consumer.</para>
|
||
<para>Subscriptions can optionally be <emphasis role="italic">durable</emphasis> which
|
||
means they retain a copy of each message sent to the topic until the subscriber
|
||
consumes them - even if the server crashes or is restarted in between. Non-durable
|
||
subscriptions only last a maximum of the lifetime of the connection that created
|
||
them.</para>
|
||
<para>An example of publish-subscribe messaging would be a news feed. As news articles
|
||
are created by different editors around the world they are sent to a news feed
|
||
topic. There are many subscribers around the world who are interested in receiving
|
||
news items - each one creates a subscription and the messaging system ensures that a
|
||
copy of each news message is delivered to each subscription.</para>
|
||
</section>
|
||
</section>
|
||
<section>
|
||
<title>Delivery guarantees</title>
|
||
<para>A key feature of most messaging systems is <emphasis role="italic">reliable
|
||
messaging</emphasis>. With reliable messaging the server gives a guarantee that the
|
||
message will be delivered once and only once to each consumer of a queue or each durable
|
||
subscription of a topic, even in the event of system failure. This is crucial for many
|
||
businesses; e.g. you don't want your orders fulfilled more than once or any of your
|
||
orders to be lost.</para>
|
||
<para>In other cases you may not care about a once and only once delivery guarantee and are
|
||
happy to cope with duplicate deliveries or lost messages - an example of this might be
|
||
transient stock price updates - which are quickly superseded by the next update on the
|
||
same stock. The messaging system allows you to configure which delivery guarantees you
|
||
require.</para>
|
||
</section>
|
||
<section>
|
||
<title>Transactions</title>
|
||
<para>Messaging systems typically support the sending and acknowledgement of multiple
|
||
messages in a single local transaction. HornetQ also supports the sending and
|
||
acknowledgement of message as part of a large global transaction - using the Java
|
||
mapping of XA: JTA.</para>
|
||
</section>
|
||
<section>
|
||
<title>Durability</title>
|
||
<para>Messages are either durable or non durable. Durable messages will be persisted in
|
||
permanent storage and will survive server failure or restart. Non durable messages will
|
||
not survive server failure or restart. Examples of durable messages might be orders or
|
||
trades, where they cannot be lost. An example of a non durable message might be a stock
|
||
price update which is transitory and doesn't need to survive a restart.</para>
|
||
</section>
|
||
<section>
|
||
<title>Messaging APIs and protocols</title>
|
||
<para>How do client applications interact with messaging systems in order to send and
|
||
consume messages?</para>
|
||
<para>Several messaging systems provide their own proprietary APIs with which the client
|
||
communicates with the messaging system.</para>
|
||
<para>There are also some standard ways of operating with messaging systems and some
|
||
emerging standards in this space.</para>
|
||
<para>Let's take a brief look at these:</para>
|
||
<section>
|
||
<title>Java Message Service (JMS)</title>
|
||
<para><ulink url="http://en.wikipedia.org/wiki/Java_Message_Service">JMS</ulink> is part
|
||
of Sun's JEE specification. It's a Java API that encapsulates both message queue and
|
||
publish-subscribe messaging patterns. JMS is a lowest common denominator
|
||
specification - i.e. it was created to encapsulate common functionality of the
|
||
already existing messaging systems that were available at the time of its
|
||
creation.</para>
|
||
<para>JMS is a very popular API and is implemented by most messaging systems. JMS is
|
||
only available to clients running Java.</para>
|
||
<para>JMS does not define a standard wire format - it only defines a programmatic API so
|
||
JMS clients and servers from different vendors cannot directly interoperate since
|
||
each will use the vendor's own internal wire protocol.</para>
|
||
<para>HornetQ provides a fully compliant JMS 1.1 and JMS 2.0 API.</para>
|
||
</section>
|
||
<section>
|
||
<title>System specific APIs</title>
|
||
<para>Many systems provide their own programmatic API for which to interact with the
|
||
messaging system. The advantage of this it allows the full set of system
|
||
functionality to be exposed to the client application. API's like JMS are not
|
||
normally rich enough to expose all the extra features that most messaging systems
|
||
provide.</para>
|
||
<para>HornetQ provides its own core client API for clients to use if they wish to have
|
||
access to functionality over and above that accessible via the JMS API.</para>
|
||
</section>
|
||
<section>
|
||
<title>RESTful API</title>
|
||
<para><ulink url="http://en.wikipedia.org/wiki/Representational_State_Transfer"
|
||
>REST</ulink> approaches to messaging are showing a lot interest
|
||
recently.</para>
|
||
<para>It seems plausible that API standards for cloud computing may converge on a REST
|
||
style set of interfaces and consequently a REST messaging approach is a very strong
|
||
contender for becoming the de-facto method for messaging interoperability.</para>
|
||
<para>With a REST approach messaging resources are manipulated as resources defined by a
|
||
URI and typically using a simple set of operations on those resources, e.g. PUT,
|
||
POST, GET etc. REST approaches to messaging often use HTTP as their underlying
|
||
protocol.</para>
|
||
<para>The advantage of a REST approach with HTTP is in its simplicity and the fact the
|
||
internet is already tuned to deal with HTTP optimally.</para>
|
||
<para>Please see <xref linkend="rest"/> for using HornetQ's RESTful interface.</para>
|
||
</section>
|
||
<section>
|
||
<title>STOMP</title>
|
||
<para><ulink
|
||
url="http://stomp.github.io/"
|
||
>Stomp</ulink> is a very simple text protocol for interoperating with messaging
|
||
systems. It defines a wire format, so theoretically any Stomp client can work with
|
||
any messaging system that supports Stomp. Stomp clients are available in many
|
||
different programming languages.</para>
|
||
<para>Please see <xref linkend="stomp"/> for using STOMP with HornetQ.</para>
|
||
</section>
|
||
<section>
|
||
<title>AMQP</title>
|
||
<para><ulink url="http://en.wikipedia.org/wiki/AMQP">AMQP</ulink> is a specification for
|
||
interoperable messaging. It also defines a wire format, so any AMQP client can work
|
||
with any messaging system that supports AMQP. AMQP clients are available in many
|
||
different programming languages.</para>
|
||
<para>HornetQ implements the <ulink url="https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=amqp">AMQP 1.0</ulink>
|
||
specification. Any client that supports the 1.0 specification will be able to interact with HornetQ.</para>
|
||
</section>
|
||
</section>
|
||
<section>
|
||
<title>High Availability</title>
|
||
<para>High Availability (HA) means that the system should remain operational after failure
|
||
of one or more of the servers. The degree of support for HA varies between various
|
||
messaging systems.</para>
|
||
<para>HornetQ provides automatic failover where your sessions are automatically reconnected
|
||
to the backup server on event of live server failure.</para>
|
||
<para>For more information on HA, please see <xref linkend="ha"/>.</para>
|
||
</section>
|
||
<section>
|
||
<title>Clusters</title>
|
||
<para>Many messaging systems allow you to create groups of messaging servers called
|
||
<emphasis role="italic">clusters</emphasis>. Clusters allow the load of sending and
|
||
consuming messages to be spread over many servers. This allows your system to scale
|
||
horizontally by adding new servers to the cluster.</para>
|
||
<para>Degrees of support for clusters varies between messaging systems, with some systems
|
||
having fairly basic clusters with the cluster members being hardly aware of each
|
||
other.</para>
|
||
<para>HornetQ provides very configurable state-of-the-art clustering model where messages
|
||
can be intelligently load balanced between the servers in the cluster, according to the
|
||
number of consumers on each node, and whether they are ready for messages.</para>
|
||
<para>HornetQ also has the ability to automatically redistribute messages between nodes of a
|
||
cluster to prevent starvation on any particular node.</para>
|
||
<para>For full details on clustering, please see <xref linkend="clusters"/>.</para>
|
||
</section>
|
||
<section>
|
||
<title>Bridges and routing</title>
|
||
<para>Some messaging systems allow isolated clusters or single nodes to be bridged together,
|
||
typically over unreliable connections like a wide area network (WAN), or the
|
||
internet.</para>
|
||
<para>A bridge normally consumes from a queue on one server and forwards messages to another
|
||
queue on a different server. Bridges cope with unreliable connections, automatically
|
||
reconnecting when the connections becomes available again.</para>
|
||
<para>HornetQ bridges can be configured with filter expressions to only forward certain
|
||
messages, and transformation can also be hooked in.</para>
|
||
<para>HornetQ also allows routing between queues to be configured in server side
|
||
configuration. This allows complex routing networks to be set up forwarding or copying
|
||
messages from one destination to another, forming a global network of interconnected
|
||
brokers.</para>
|
||
<para>For more information please see <xref linkend="core-bridges"/> and <xref
|
||
linkend="diverts"/>.</para>
|
||
</section>
|
||
</chapter>
|