|
DEVELOPER: Trends
Do You Queue?
By Cameron O'Rourke
Improve application response time by tapping into queuing technology.
Do your users complain about a slow-running application that you have tried to tune but just can't make run fast enough? Perhaps you need to take a hard look at the amount of processing your application does while the user is waiting. Could some of it be done in the background?
In this column, I'll discuss message queuing and introduce you to the Java API for Messaging as well as Oracle's implementation, Advanced Queuing.
Time Shifting
In general, it makes a lot of sense to separate application processing into that which must be completed right away and that which can be deferred until later.
Anything that does not affect the
rendering of the user's next page can potentially run in the background.
Batch updates, summary computations, and external processing are good background candidates.
Queuing is a technique that lets you efficiently separate application processing into foreground and background tasks. It works by storing, prioritizing, and delivering messages to applications as processing capacity becomes available. This allows you to smooth out the load on the local computer or to distribute tasks to remote computers.
To reduce your users' wait time, your application can enqueue messages describing the background processing required. This work can then be removed from the page rendering process. The messages can be read
and acted upon by a background process, or they can even be handled by a separate system.
The Java Messaging System
The J2EE Java Message Service (JMS)
is actually an interface, rather than a system, for accessing enterprise message systems. JMS abstracts the differences between vendor messaging implementations. The idea is that applications written to the JMS API are portable across different messaging products.
In reality, there is the usual trade-off between portability and functionality. Although JMS provides some measure of portability for the application code (but not the configuration), it generally provides least-common-denominator access to the features of the messaging system.
JMS provides two programming models: point-to-point (p2p) and publish-and-subscribe (pub/sub). The JMS specification refers to these as
messaging domains.
In p2p messaging, each message is sent to a single recipient through a queue. The p2p model ensures that one, and only one, recipient consumes each message. If there are multiple receivers listening on a queue (such as when you have a pool of message-driven beans), the JMS provider will distribute each message to one of the receivers. The p2p messaging model is best for transactional messages.
In pub/sub messaging, one message producer can send a message to one or more registered consumers through a topic. Consumers can subscribe to a topic. Subscriptions can be durable, allowing consumers to disconnect and then later reconnect and retrieve any missed messages. You can think of the pub/sub messaging model as a broadcast serviceit's best used when the publisher is not too concerned about missed messages.
Because JMS is just an interface, it requires an implementation to do the actual work. Oracle JMS (OJMS) is a high-quality JMS provider that is based on Oracle's Advanced Queuing.
Oracle Advanced Queuing
Advanced Queuing is a feature of
the Oracle database that provides message queuing functionality. It
is a very reliable, secure, and
scalable messaging system, because it uses the same database features as any other Oracle-based application.
A big advantage of Advanced Queuing is that it can be accessed
from PL/SQL, Java, or C, so you can enqueue a message from a Java servlet and dequeue that same message in a PL/SQL stored procedure.
Another advantage of Advanced Queuing is that you can use it to propagate messages between remote nodes with Oracle Net Services (SQL*Net), HTTP(S), and SMTP. Advanced Queuing even integrates with non-Oracle messaging systems such as IBM MQSeries through the Messaging Gateway.
Oracle Advanced Queuing provides both single-consumer and multi-consumer queues. A single-consumer queue is directed at a single recipient. A multiconsumer queue can be consumed by multiple recipients. When putting messages into a multiconsumer queue, the application programmer must either explicitly specify the recipients in the message properties or set up rule-based subscriptions that determine the recipients for each message.
The two queue types provided by Advanced Queuing correlate to the two messaging domains exposed by JMS. Table 1 summarizes the relationships between messaging styles.
|
Messaging Style | Common Use | Cardinality | JMS Domain | Oracle Advanced Queuing Type |
|
Point-to-point | Transactions | 1 to 1 | Queue | Single-consumer |
| Publish-and-subscribe | Broadcast | 1 to many | Topic | Multiconsumer |
Table 1: Comparison of messaging styles
Something to keep in mind is that Advanced Queuing provides features and concepts that have no equivalent in JMS. For example, Oracle Advanced Queuing allows a message to have multiple named recipients, whereas JMS exposes no such notion. Although coding to the JMS API is usually sufficient, remember that you may need to write to Oracle's native Java Advanced Queuing API to access all of Oracle's messaging functionality.
Message-Driven Beans
Message-driven beans (MDBs) are a
type of Enterprise JavaBean (EJB) that consumes JMS messages. MDBs are managed by the J2EE application server, which listens for messages and maintains a pool of MDB instances that are automatically invoked to receive and process the messages.
MDBs are easier to write than JMS applications, because the application server handles the MDB's runtime environment, including transactions, security, and concurrency. This provides a big advantage to the developer, who is freed to concentrate on the business logic for processing the messages. As messages arrive in the queue, instances of the MDB are automatically created and destroyed to handle the load.
Note that because MDBs are based on JMS, they inherit the limitations of the JMS API; namely, you can't access all the functionality of the underlying messaging system.
However, you should generally use MDBs whenever you can, because the application server manages the complexity inherent in a multithreaded asynchronous message listener. JMS will still prove useful (despite the greater complexity involved) for code that can't run in the application server, such as standalone client applications.
An Example
Earlier, I pointed out that anything that does not affect the rendering of the user's next page is a good candidate
for queue processing. However, it may not always be obvious how to achieve further improvements in the user's perceived response time.
To make those improvements, change the way you think about the workflow by asking: "What is the bare minimum that needs to be done that will allow my user to continue working?" You may need to challenge assumptions about the work itself.
I was working with an insurance company on a Web application that was used by the company's telephone staff to process member status changes over the telephone. The application had to interface with two different legacy systems to update as well as
validate the data.
In one scenario, a customer calls in wanting to change her address to one in another state. The phone staffer enters the information into a Web form and clicks Submit. The Web application forwards the transaction to two different mainframe applications: one for health plans and another for retirement benefits. When the health plan application validates the address change, the validation determines
that the customer's current plan is not available in the new state.
The problem? All of this interaction with the legacy systems took too much time. And there were reliability problems: If either of the mainframes were offline or any part of the connecting infrastructure was down, the entire phone staff was unable to take calls.
Furthermore, the managers insisted that all of the processing take place before the Web application painted the next page. They argued that the Web application needed to resolve any problems with the transaction while the user was still on the phone.
The solution was to challenge the assumption that all data had to be validated before the user was allowed to continue on to the next task. In this case, we discovered that problems requiring additional input from the customer rarely occurred. The company made a design decision to assume that all would go well, let the customer hang up the phone, and simply call the customer back in the less than 1 percent of cases when there was a problem.
The Web application was redesigned using HTML frames and a small amount of JavaScript that would periodically check the server for issues needing attention.
By rethinking the workflow and applying queuing technology, this company was able to improve its system reliability and response time
to both the users and customers.
Going Further
Here are some important points about Advanced Queuing, OJMS, and JMS to keep in mind:
- When you set up an Advanced Queuing queue, you specify that it will
be a JMS-enabled queue by using one
of the OJMS types (such as SYS.AQ$_JMS_ MAP_MESSAGE).
- You can enqueue/dequeue messages to/from JMS queues from PL/SQL using the DBMS_AQJMS built-in package.
- Not all Advanced Queuing features and properties are implemented via the standard JMS interface. The Java package oracle.jms has classes and interfaces that implement Oracle extensions to the public JMS standard.
Sample Code and Tutorial
You can find code samples and a tutorial showing how to use Advanced Queuing, JMS, and MDBs at devtrends.oracle.com/code/activedb.
Cameron O'Rourke (cameron.orourke@oracle.com) has been an Oracle technologist for more than
11 years.
|