OMTO-Client Program Model
Messaging Domains
Messaging middleware allows components and applications to communicate by producing and consuming messages. The JMS API defines two patterns or messaging domains that govern this communication: point-to-point messaging and publish/subscribe messaging. The JMS API is organized to support these patterns. The basic JMS objects: connections, sessions, producers, consumers, destinations, and messages are used to specify messaging behavior in both domains.
Point-To-Point Messaging
In the point-to-point domain, message producers are called senders and consumers are calledreceivers. They exchange messages by means of a destination called a queue: senders produce messages to a queue; receivers consume messages from a queue. Figure 2–1 shows the simplest messaging operation in the point-to-point domain. MyQueueSender sends Msg1 to the queue destination MyQueue1. Then, MyQueueReceiver obtains the message from MyQueue1.
Figure 2–2 shows a more complex picture of point-to-point messaging to illustrate the possibilities in this domain. Two senders, MyQSender1 and MyQSender2, use the same connection to send messages to MyQueue1. MyQSender3 uses an additional connection to send messages to MyQueue1.On the receiving side, MyQReceiver1 consumes messages from MyQueue1, and MyQReceiver2 and MyQReceiver3, share a connection in order to consume messages from MyQueue1.
This more complex picture illustrates a number of additional points about point-to-point messaging.
■ More than one producer can send messages to a queue. Producers can share a connection or use different connections, but they can all access the same queue.
■ More than one receiver can consume messages from a queue, but each message can only be consumed by one receiver. Thus Msg1, Msg2, and Msg3 are consumed by different receivers.(This is aMessage Queue extension.)
■ Receivers can share a connection or use different connections, but they can all access the same queue. (This is aMessage Queue extension.)
■ Senders and receivers have no timing dependencies: the receiver can fetch a message whether or not it was running when the client sent the message.
■ Senders and receivers can be added and deleted dynamically at runtime, thus allowing the messaging system to expand or contract as needed.
■ Messages are placed on the queue in the order sent, but the order in which they are consumed depends on factors such as message expiration date, message priority, and whether a selector is used in consuming messages.
The point-to-point model offers a number of advantages:
■ The fact that multiple receivers can consume messages from the same queue allows you to load-balance message consumption if the order in which messages are received is not important. (This is aMessage Queue extension.)
■ Messages destined for a queue are always retained, even if there are no receivers.
■ Java clients can use a queue browser object to inspect the contents of a queue. They can then consume messages based on the information gained from this inspection. That is, although the consumption model is normally FIFO (first in, first out), consumers can consume messages that are not at the head of the queue if they know what messages they want by using message selectors. Administrative clients can also use the queue browser to monitor the contents of a queue.
Publish/Subscribe Messaging
In the publish/subscribe domain, message producers are called publishers and message consumers are called subscribers. They exchange messages by means of a destination called a topic: publishers produce messages to a topic; subscribers subscribe to a topic and consume messages from a topic.
Figure 2–3 shows a simple messaging operation in the publish/subscribe domain.
MyTopicPublisher publishes Msg1 to the destination MyTopic. Then, MyTopicSubscriber1 and MyTopicSubscriber2 each receive a copy of Msg1 from MyTopic.
While the publish/subscribe model does not require that there be more than one subscriber,two subscribers are shown in the figure to emphasize the fact that this domain allows you to broadcast messages. All subscribers to a topic get a copy of any message published to that topic.Subscribers can be non-durable or durable. The broker retains messages for all active subscribers, but it only retains messages for inactive subscribers if these subscribers are durable.
Figure 2–4 shows a more complex picture of publish/subscribe messaging to illustrate the possibilities offered by this pattern. Several producers publish messages to the Topic1 destination. Several subscribers consume messages from the Topic1 destination. Unless, a subscriber is using a selector to filter messages, each subscriber gets all the messages published to the topic of choice. In Figure 2–4, MyTSubscriber2 has filtered out Msg2.
This more complex picture illustrates a number of additional points about publish/subscribe messaging.
■ More than one producer can publish messages to a topic. Producers can share a connection or use different connections, but they can all access the same topic.
■ More than one subscriber can consume messages from a topic. Subscribers retrieve all messages published to a topic unless they use selectors to filter out messages or the messages expire before they are consumed.
■ Subscribers can share a connection or use different connections, but they can all access the same topic.
■ Durable subscribers can be active or inactive. The broker retains messages for them while they are inactive.
■ Publishers and subscribers can be added and deleted dynamically at runtime, thus allowing the messaging system to expand or contract as needed.
■ Messages are published to a topic in the order sent, but the order in which they are consumed depends on factors such as message expiration date, message priority, and whether a selector is used in consuming messages.
■ Publishers and subscribers have a timing dependency: a topic subscriber can consume only messages published after it has created the subscription.
The main advantage of the publish/subscribe model is that it allows messages to be broadcast to subscribers.
The JMS API defines interfaces and classes that you can use to implement either of the point-to-point or the publish/subscribe domains. These are the domain-specific API’s shown in columns 2 and 3 of Table 2–1. The JMS API defines an additional unified domain, which allows you to program a generic messaging client. The behavior of such a client is determined by the type of the destination to which it produces messages and from which it consumes messages. If the destination is a queue, messaging will behave according to the point-to-point pattern; if the destination is a topic, messaging will behave according to the publish/subscribe pattern.
The unified domain was introduced with JMS version 1.1. If you need to conform to the earlier 1.02b specification, you can use the domain-specific API. Using the domain-specific API also provides a clean programming interface that prevents certain types of programming errors: for example, creating a durable subscriber for a queue destination.However, the domain-specific APIs have the disadvantage that you cannot combine point-to-point and publish/subscribe operations in the same transaction or in the same session. If you need to do that, you should choose the unified domain API. See “The Request-Reply Pattern” on page 44 for an example of
combining the two domains.
Programming Objects
The objects used to implement JMS messaging remain essentially the same across programming domains: connection factories, connections, sessions, producers, consumers, messages, and destinations. These objects are shown in Figure 2–5. The figure shows, from the top down, how objects are derived, starting with the connection factory object.Two of the objects, connection factories and destinations, are shown to reside in an object store. This is to underline the fact that these objects are normally created, configured, and managed as administered objects. We assume that connection factories and destinations are created administratively (rather than programmatically) throughout this chapter.
Table 2–2 summarizes the steps required to send and receive messages.Note that steps 1 through 6 are the same for senders and receivers.
The following sections describe the objects used by producers and consumers: connections, sessions, messages, and destinations. We will then complete the discussion of JMS objects by describing the production and consumption of messages.
Connection Factories and Connections
A client uses a connection factory object (ConnectionFactory) to create a connection. A connection object ( Connection) represents a client’s active connection to the broker. It uses the underlying connection service that is either started by default or is explicitly started by the administrator for this client. Both allocation of communication resources and authentication of the client take place when a connection is created. It is a relatively heavyweight object, and most clients do all their
messaging with a single connection. Connections support concurrent use: any number of producers and consumers can share a connection. When you create a connection factory, you can configure the behavior of all connections derived from it by setting its properties. For Message Queue, these specify the following
information:
■ The name of the host on which the broker resides, the connection service desired, and the port through which the client wants to access that service.
■ How automatic reconnection to the broker should be handled if the connection fails. (This feature reconnects the client to the same (or to a different broker) if a connection is lost. Data failover is not guaranteed: persistent messages and other state information can be lost when reconnecting to a different broker.)
■ The ID of a client that needs the broker to track its durable subscription.
■ The default name and password of the user attempting the connection. This information is used to authenticate the user and authorize operations if a password is not specified at connection time.
■ Whether broker acknowledgements should be suppressed for those clients who are not concerned with reliability.
■ How to manage the flow of control and payload messages between the broker and the client runtime.
■ How queue browsing should be handled. (Java clients only.)
■ Whether certain message header fields should be overridden.
It is possible to override connection factory properties from the command line used to start the client application. It is also possible to override properties for any given connection by setting properties for that connection.
You can use a connection object to create session objects, to set up an exception listener, or to obtain JMS version and provider information.
Sessions
If the connection represents a communication channel between the client and the broker, a session marks a single conversation between them.Mainly, you use a session object to create messages, message producers, and message consumers. When you create a session, you configure reliable delivery through a number of acknowledgement options or through transactions. For more information, see “ReliableMessaging” on page 46.
According to the JMS specification, a session is a single-threaded context for producing and consuming messages. You can create multiple message producers and consumers for a single session, but you are restricted to using them serially. The threading implementation varies slightly for Java and C clients. Consult the appropriate developer’s guide for additional information about threading implementation and restrictions.
You can also use a session object to do the following:
■ Create and configure destinations for those clients that do not use administered objects to define destinations.
■ Create and configure temporary topics and queues; these are used as part of the request-reply pattern. See “The Request-Reply Pattern” on page 44.
■ Support transaction processing.
■ Define a serial order for producing or consuming messages.
■ Serialize the execution of message listeners for asynchronous consumers.
■ Create queue browsers. (Java clients only.)
Messages
A message is composed of three parts: a header, properties, and a body. You must understand this structure in order to compose a message properly and to configure certain messaging behaviors.
Message Header
A header is required of every JMS message. The header contains ten predefined fields, which are listed and described in Table 2–3.
As you can see from reading through this table, message header fields serve a variety of purposes: identifying a message, configuring the routing of messages, providing information about message handling, and so on.
One of the most important fields, JMSDeliveryMode, determines the reliability of message delivery. This field indicates whether a message is persistent.
■ Persistent messages. are guaranteed to be delivered and successfully consumed exactly once. Persistent messages are not lost if the message service fails.
■ Non-persistent messages are guaranteed to be delivered at most once.Non-persistent messages can be lost if the message service fails.
Some message header fields are set by the provider (either the broker or the client runtime) and others are set by the client.Message producers may need to configure header values to obtain certain messaging behaviors; message consumers may need to read header values in order to understand how the message was routed and what further processing it might need.
The header fields (JMSDeliveryMode, JMSExpiration, and JMSPriority) can be set at three different levels:
■ For messages issuing from every connection derived from a connection factory.
■ For each message produced.
■ For all messages issued by a specific message producer.
If these fields are set at more than one level, values set for the connection factory override those set for the individual message; values set for a given message override those set for the message’s producer.
Constant names for message header fields vary with the language implementation. See Sun Java SystemMessage Queue 4.1 Developer’s Guide for Java Clients or Sun Java SystemMessage Queue 4.1 Developer’s Guide for C Clients for more information.
Message Properties
A message can also include optional header fields, called properties, specified as property name and property value pairs. Properties allow clients and providers to extend the message header and can contain any information that the client or the provider finds useful to identify and process a message.Message properties allow a receiving client to ask that only those messages be delivered which fit a given criteria. For instance, a consuming client might indicate an interest for payroll messages concerning part-time employees located inNew Jersey. The provider will not deliver messages that do not meet the specified criteria. The JMS specification defines nine standard properties. Some of these are set by the client and some by the provider. Their names begin with the reserved characters “JMSX.” The client or the
provider can use these properties to determine who sent a message, the state of the message,how often and when it was delivered. These properties are useful to the provider in routing messages and in providing diagnostic information.
Message Queue also defines message properties, these are used to identify compressed messages and how messages should be handled if they cannot be delivered. For more information see “ManagingMessage Size” in Sun Java SystemMessage Queue 4.1 Developer’s Guide for Java Clients.
Message Body
The message body contains the data that clients want to exchange. The type of a JMS message determines what the body may contain and how it should be
processed by the consumer, as specified in Table 2–4. The Session object includes a create method for each type of message body.
Java clients can set a property to have the client runtime compress the body of a message being sent. TheMessage Queue runtime on the consumer side decompresses the message before delivering it.
Producing a Message
Messages are sent or published by a message producer, within the context of a connection and session. Producing a message is fairly straightforward: a client uses a message producer object (MessageProducer) to send messages to a physical destination, represented in the API by a destination object.
When you create the producer, you can specify a default destination that all the producer’s messages are sent to. You can also specify default values for the message header fields that govern persistence, priority, and time-to-live. These defaults are then used by all messages issuing from that producer unless you override them by specifying an alternate destination when sending the message or by setting alternate values for the header fields for a given message.
The message producer can also implement a request-reply pattern by setting the JMSReplyTo message header field. For more information, see “The Request-Reply Pattern” on page 44.
Consuming a Message
Messages are received by a message consumer, within the context of a connection and session. A client uses a message consumer object (MessageConsumer) to receive messages from a specified physical destination, represented in the API as a destination object.
Three factors affect how the broker delivers messages to a consumer:
■ Whether consumption is synchronous or asynchronous
■ Whether a selector is used to filter incoming messages
■ If messages are consumed from a topic destination, whether the subscriber is durable The other major factor that affects message delivery and client design is the degree of reliability needed for the consumer. See “ReliableMessaging” on page 46.
Synchronous and Asynchronous Consumers
A message consumer can support either synchronous or asynchronous consumption of messages.
■ Synchronous consumption means the consumer explicitly requests that a message be delivered and then consumes it.
Depending on the method used to request messages, a synchronous consumer can choose to wait (indefinitely) until a message arrives, to wait a specified amount of time for a message,or to return immediately if there is no message ready to be consumed. (“Consumed” means the object is immediately available to the client.Messages that were successfully sent but which the broker has not finished processing are not ready to be consumed.)
■ Asynchronous consumption means that the message is automatically delivered to a message listener object (MessageListener) that has been registered for the consumer. The client consumes the message when a session thread invokes the onMessage() method of the message listener object.
Using Selectors to Filter Messages
A message consumer can use a message selector to have the message service deliver only those messages whose properties match specific selection criteria. You specify this criteria when you create the consumer.
Selectors use an SQL-like syntax to match against message properties. For example,
color = ”red’
size > 10
Java clients can also specify selectors when browsing a queue; this allows you to see which selected messages are waiting to be consumed.
UsingDurable Subscribers
You can use a session object to create a durable subscriber to a topic. The broker retains messages for these kinds of subscribers even when the subscriber becomes inactive.Because the broker must maintain state for the subscriber and resume delivery of messages when the subscriber is reactivated, the broker must be able to identify a given subscriber throughout its comings and goings. The subscriber’s identity is constructed from the ClientID property of the connection that created it and the subscriber name specified when you create the subscriber.
The Request-Reply Pattern
You can combine producers and consumers in the same connection (or even session when using the unified API). In addition, the JMS API allows you to implement a request-reply pattern for your messaging operations by using temporary destinations.
To set up the request-reply pattern you need to do the following:
1. Create a temporary destination where the consumer can send replies.
2. In the message to be sent, set the JMSReplyTo field of the message header to that temporary destination.
When the message consumer processes the message, it examines the JMSReplyTo field of the message to determine if a reply is required and sends the reply to the specified destination. The request-reply mechanism saves the producer the trouble of setting up an administered object for the reply destination and makes it easy for the consumer to respond to the request.
This pattern is useful when the producer must be sure that a request has been handled before
proceeding.
Figure 2–6 illustrates a request-reply pattern that sends messages to a topic and receives replies in a temporary queue.
As the figure shows, MyTopicPublisher produces Msg1 to the destination MyTopic. MyTopicSubsriber1 and MyTopicSubscriber2 receive the message and send a reply to
MyTempQueue, from where MyTQReceiver retrieves it. This pattern might be useful for an application that published pricing information to a large number of clients and which queued their (reply) orders for sequential processing. Temporary destinations last only as long as the connection that created them. Any producer can send to a temporary destination, but the only consumers that can access temporary destinations are those created by the same connection that created the destination.
Since the request/reply pattern depends on creating temporary destinations, you should not use this pattern in the following cases:
■ If you anticipate that the connection creating the temporary destination might terminate before the reply is sent.
■ If you need to send a persistent message to a temporary destination.
Reliable Messaging
Message delivery occurs in two hops: the first hop takes the message from the producer to a physical destination on the broker; the second hop takes the message from that destination to the consumer. Thus, a message can be lost in one of three ways: on its hop to the broker, while it’s in broker memory if the broker fails, and on its hop from the broker to the consumer.
Reliable delivery guarantees that delivery will not fail at any of these stages. Because non-persistent messages can always be lost if the broker fails, reliable delivery only applies to persistent messages.
Two mechanisms are used to ensure reliable delivery:
■ The client can use acknowledgments or transactions to make sure that message production and consumption is successful.
■ The broker can store messages in a persistent store so that if the broker fails before the message is consumed, it can retrieve the stored copy of the message and retry the operation.
The following sections describe these two aspects of ensuring reliability.
Acknowledgements
Acknowledgements are messages sent between the client and the message service to ensure reliable delivery of messages. Acknowledgements are used differently for producers and for consumers.
In the case of message production, the broker acknowledges that it has received the message, placed it in its destination and stored it persistently. The producer’s send() method blocks until it receives this acknowledgement. These acknowledgements are transparent to the client when persistent messages are sent.
In the case of message consumption, the client acknowledges that it has received delivery of a message from a destination and consumed it, before the broker can delete the message from that destination. JMS specifies different acknowledgement modes that represent different degrees of reliability.
■ In the AUTO_ACKNOWLEDGE mode, the session automatically acknowledges each message consumed by the client. The session thread blocks, waiting for the broker to confirm that it has processed the client acknowledgement for each consumed message.
■ In the CLIENT_ACKNOWLEDGE mode, the client explicitly acknowledges after one or more messages have been consumed by calling the acknowledge() method of a message object. This causes the session to acknowledge all messages that have been consumed by the session since the previous invocation of the method. The session thread blocks, waiting for the broker to confirm that it has processed the client acknowledgement. Message Queue extends this mode by providing a method that allows a client to acknowledge receipt of one message only.
■ In DUPS_OK_ACKNOWLEDGE mode, the session acknowledges after ten messages have beenconsumed. The session thread does not block waiting for a broker acknowledgement,because no broker acknowledgement is required in this mode. Although this mode guarantees that no message will be lost, it does not guarantee that no duplicate messages will be received, hence its name: DUPS_OK.
For clients that are more concerned with performance than reliability, theMessage Queue service extends the JMS API by providing a NO_ACKNOWLEDGE mode. In this mode, the broker does not track client acknowledgements, so there is no guarantee that a message has been successfully processed by the consuming client. Choosing this mode may give you better performance for non persistent messages that are sent to non-durable subscribers.
Transactions
A transaction is a way of grouping the production and/or consumption of one or more messages into an atomic unit. The client and broker acknowledgement process described above applies, as well, to transactions. In this case, client runtime and broker acknowledgements operate implicitly on the level of the transaction. When a transaction commits, a broker acknowledgement is sent automatically.A session can be configured as transacted, and the JMS API provides methods for initiating,
committing, or rolling back a transaction.As messages are produced or consumed within a transaction, the message service tracks the various sends and receives, completing these operations only when the JMS client issues a call to commit the transaction. If a particular send or receive operation within the transaction fails, an
exception is raised. The client code can handle the exception by ignoring it, retrying the operation, or rolling back the entire transaction. When a transaction is committed, all its operations are completed. When a transaction is rolled back, all successful operations are cancelled. The scope of a transaction is always a single session. That is, one or more producer or consumer operations performed in the context of a single session can be grouped into a single transaction.
Since transactions span only a single session, you cannot have an end-to-end transaction encompassing both the production and consumption of a message.
The JMS specification also supports distributed transactions. That is, the production and consumption of messages can be part of a larger, distributed transaction that includes operations involving other resource managers, such as database systems. A transaction manager, like the one supplied by the Java Systems Application Server, must be available to support distributed transactions. In distributed transactions, a distributed transaction manager tracks and manages operations
performed by multiple resource managers (such as a message service and a database manager) using a two-phase commit protocol defined in the Java Transaction API (JTA), XA Resource API Specification. In the Java world, interaction between resource managers and a distributed transaction manager are described in the JTA specification.Support for distributed transactions means that messaging clients can participate in distributed transactions through the XAResource interface defined by JTA. This interface defines a number of methods for implementing two-phase commit. While the API calls are made on the client side, the JMS message service tracks the various send and receive operations within the distributed transaction, tracks the transactional state, and completes the messaging operations only in coordination with a distributed transaction manager—provided by a Java Transaction Service (JTS). As with local transactions, the client can handle exceptions by ignoring them,
retrying operations, or rolling back an entire distributed transaction.
Note :Message Queue supports distributed transactions only when it is used as a JMS provider in a Java Enterprise Edition platform. For additional information on how to use distributed transactions, please consult the documentation furnished by your Application Server provider.
Persistent Storage
The other aspect of reliability is ensuring that the broker does not lose persistent messages before they are delivered to consumers. This means that when a message reaches its physical destination, the broker must place it in a persistent data store. If the broker goes down for any reason, it can recover the message later and deliver it to the appropriate consumers.The broker must also persistently store durable subscriptions. Otherwise, in case of failure, it would not be able to deliver messages to durable subscribers who become active after a message has arrived in a topic destination. Messaging applications that want to guarantee message delivery must specify messages as persistent and deliver them either to topic destinations with durable subscriptions or to queue destinations.
Chapter 3, “Message Queue Service,” describes the default message store supplied by the Message Queue service and how an administrator can set up and configure an alternate store.
A Message’s JourneyThrough the System
By way of summarizing the material presented so far, this section describes how a message is delivered using theMessage Queue service, from a producer to a consumer. In order to paint a complete picture, a further detail is needed: The messages handled by the system in the course of delivery fall into two categories:
■ Payload messages, which are the messages sent by producers to consumers.
■ Control messages, which are private messages passed between the broker and the client runtime to ensure that payload messages are successfully delivered and to control the flow of messages across a connection.
Message delivery steps for a persistent, reliably delivered message are as follows:
Message Production
1. The client runtime delivers the message over the connection from the message producer to the broker.
Message Handling and Routing
2. The broker reads the message from the connection and places it in the appropriate destination.
3. The broker places the (persistent) message in the data store.
4. The broker acknowledges receipt of the message to the client runtime of the message producer.
5. The broker determines the routing for the message.
6. The broker writes out the message from its destination to the appropriate connection, tagging it with a unique identifier for the consumer. Message Consumption
7. The message consumer’s client runtime delivers the message from the connection to the message consumer.
8. The message consumer’s client runtime acknowledges consumption of the message to the broker. Message End-of-Life
9. The broker processes the client acknowledgement, and deletes the (persistent) message when all acknowledgements have been received.
10. The broker confirms to the consumer’s client runtime that the client acknowledgement has been processed.
The broker can discard a message before it is consumed if the administrator deletes the message from a destination or if the administrator removes or redefines a durable subscription, thereby causing a message in a topic destination to be removed without it being delivered. In other situations, you might want the broker to store the messages in a special destination called the dead message queue rather than discard them. A message is placed on the dead message queue
when it expires, when it is removed due to memory limits, or when delivery fails due to the client’s throwing an exception. Storing messages in the dead message queue allows you to troubleshoot the system and recover messages in certain situations.
posted on 2012-06-30 23:28 malaikuangren 阅读(257) 评论(0) 编辑 收藏 举报