From fec45b4bcb07b5fbd3e1d7b1c00c275a5074bf1a Mon Sep 17 00:00:00 2001 From: Jonathan Robie Date: Fri, 30 Apr 2010 22:49:27 +0000 Subject: * Changed title, added subtitle * Added information on logging * Added section showing examples for setting connection settings * Added section showing how to receive messages from multiple sources using session.nextReceiver().fetch() * Added Request / Response section * Added section on performance, including batching of acks and prefetch * Added section on guaranteed delivery * Added section on transactions * Improved description of x-bindings * Added XML Exchange section - but the example does not work ... * Added Java JMS Selector syntax * General editing git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@939865 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/doc/book/src/High-Level-API.xml | 612 ++++++++++++++++++++++++++++++----- 1 file changed, 535 insertions(+), 77 deletions(-) diff --git a/qpid/doc/book/src/High-Level-API.xml b/qpid/doc/book/src/High-Level-API.xml index 8e9d786b85..f658d73050 100644 --- a/qpid/doc/book/src/High-Level-API.xml +++ b/qpid/doc/book/src/High-Level-API.xml @@ -24,14 +24,15 @@ --> - Using Qpid for Messaging + Programming in Apache Qpid + Cross-Platform AMQP Messaging in Java JMS, .NET, C++, and Python
Supported APIs Apache Qpid is a reliable, asynchronous messaging system that supports the AMQP messaging protocol in several common programming - languages. + languages. Qpid is supported on most common platforms. @@ -51,21 +52,22 @@ - For Python and C++, Qpid defines its own - messaging API which is conceptually similar in each supported - language. + For Python and C++, Qpid defines its own messaging API, the + Qpid Messaging API, which is + conceptually similar in each supported language. Support for this API in Ruby will be added - soonRuby currently uses an API that is closely tied - to the AMQP version.. + soon + Ruby currently uses an API that is closely + tied to the AMQP version..
- +
Using the Qpid Messaging API @@ -380,8 +382,8 @@ Message(properties={spout-id:7da2d27d-93e6-4803-8a61-536d87b8d93f:0}, content='' You can run drain in several separate - windows; each will create a subscription for the exchange, and - each will receive all messages sent to the exchange. + windows; each creates a subscription for the exchange, and + each receives all messages sent to the exchange. @@ -451,7 +453,7 @@ options ::= { : , ... } Using subjects - In this example we will show how subjects affect message + In this example we show how subjects affect message flow. First, let's use qpid-config to create a topic exchange. @@ -460,7 +462,7 @@ options ::= { : , ... } $ qpid-config add exchange topic news-service - Now we will use drain to receive messages from news-service that match the subject sports. + Now we use drain to receive messages from news-service that match the subject sports. First Window: $ ./drain -a news-service/sports -t 30 @@ -474,10 +476,9 @@ $ ./spout -a news-service/sports $ ./spout -a news-service/news - Now look at the first window, and you will see the - message with the subject sports has been - received, but not the message with the subject - news: + Now look at the first window, the message with the + subject sports has been received, but not + the message with the subject news: Message(properties={qpid.subject:sports, spout-id:9441674e-a157-4780-a78e-f7ccea998291:0}, content='') @@ -885,7 +886,7 @@ Message(properties={spout-id:ea75d64d-ea37-47f9-96a9-d38e01c97925:0}, content='t True, False - Indicates whether the node will survive a loss of + Indicates whether the node survives a loss of volatile storage e.g. if the broker is restarted. @@ -909,25 +910,29 @@ Message(properties={spout-id:ea75d64d-ea37-47f9-96a9-d38e01c97925:0}, content='t x-bindings - A nested list each of whose entries is a map that may - contain fields (queue, exchange, key and arguments) - describing an AMQP 0-10 binding, using the following format: + A nested list in which each binding is represented by + a map. The entries of the map for a binding contain + the fields that describe an AMQP 0-10 binding. Here is + the format for x-bindings: , - queue: , - key: , - arguments: -} +[ + { + exchange: , + queue: , + key: , + arguments: { : , ..., : } + }, + ... +] ]]> In conjunction with the create option, each of these - bindings will be established as the address is - resolved. In conjunction with the assert option, the - existence of each of these bindings will be verified - during resolution. Again, these are protocol specific. + bindings is established as the address is resolved. In + conjunction with the assert option, the existence of + each of these bindings is verified during + resolution. Again, these are protocol specific. @@ -963,7 +968,7 @@ Message(properties={spout-id:ea75d64d-ea37-47f9-96a9-d38e01c97925:0}, content='t True, False - Indicates whether the link will survive a loss of + Indicates whether the link survives a loss of volatile storage e.g. if the broker is restarted. @@ -1003,7 +1008,7 @@ Message(properties={spout-id:ea75d64d-ea37-47f9-96a9-d38e01c97925:0}, content='t describing an AMQP 0-10 binding. - These bindings will be established during resolution + These bindings are established during resolution independent of the create option. They are considered logically part of the linking process rather than of node creation. @@ -1094,10 +1099,10 @@ options := map Create, Delete, and Assert Policies The create, delete, and assert policies specify who should perfom the associated action: - always: the action will be performed by any messaging client - sender: the action will only be performed by a sender - receiver: the action will only be performed by a receiver - never: the action will never be performed (this is the default) + always: the action is performed by any messaging client + sender: the action is only performed by a sender + receiver: the action is only performed by a receiver + never: the action is never performed (this is the default) @@ -1114,18 +1119,70 @@ options := map
+ Logging + The Qpidd broker and C++ clients can both use environment + variables to enable logging. Use QPID_LOG_ENABLE to set the + level of logging you are interested in (trace, debug, info, + notice, warning, error, or critical): + + +$ export QPID_LOG_ENABLE="warning+" + + + The Qpidd broker and C++ clients use QPID_LOG_OUTPUT to + determine where logging output should be sent. This is either a + file name or the special values stderr, stdout, or syslog: + + +export QPID_LOG_TO_FILE="/tmp/myclient.out" + + +
+ + + +
Reconnect and Failover Connections in the Qpid Messaging API support automatic - reconnection. The following table lists some of the connection - properties that control this. See the reference documentation - for details on how to set these on connections fro each - langauge. + reconnect if a connection is lost. This is done using connection + options. The following example shows how to use connection options in C++ and Python. + + + Specifying Connection Options in C++ and Python + + In C++, these options are set using Connection::setOption(): + + + + In Python, these options are set using named arguments in + the Connection constructor: + + + + See the reference documentation for details on how to set + these on connections for each language. + + + The following table lists the connection options that can + be used. + - Connection properties + Connection Options - property + option value semantics @@ -1202,6 +1259,307 @@ options := map
+
+ Receiving Messages from Multiple Sources + + A receiver can only read from one source, but many + programs need to be able to read messages from many sources, + preserving the original sequence of the messages. In the Qpid + Messaging API, a program can ask a session for the next + receiver; that is, the receiver that is responsible for + the next available message. The following example shows how this + is done in C++ and Python. + + + Receiving Messages from Multiple Sources + + C++: + + + + Python: + + +
+ +
+ Request / Response + Request / Response applications use the reply-to property, + described in , to allow a server + to respond to the client that sent a message. A server sets up a + service queue, with a name known to clients. A client creates a + private queue for the server's response, creates a message for a + request, sets the request's reply-to property to the address of + the client's response queue, and sends the request to the + service queue. The server sends the response to the address + specified in the request's reply-to property. + + + Request / Response Applications in C++ + + This example shows the C++ code for a client and server + that use the request / response pattern. + + The server creates a service queue and waits for a + message to arrive. If it receives a message, it sends a + message back to the sender. + + + + The client creates a sender for the service queue, and + also creates a response queue that is deleted when the + client closes the receiver for the response queue. In the C++ + client, if the address starts with the character + #, it is given a unique name. + + " << response.getContent() << std::endl; +]]> + + The client sends the string ping to + the server. The server sends the response + pong back to the same client, using the + replyTo property. + + + +
+ + + +
+ XML Exchange + The XML Exchange is an AMQP 0-10 custom exchange provided by the Apache Qpid C++ broker. It allows messages to be filtered using XQuery; queries can address either message properties or XML content in the body of the message. + + An instance of the XML Exchange must be added before it can be used: + + +$ qpid-config add exchange xml xml + + + + Here is a Python program that shows how to use the XML Exchange: + + + This program does not work. Not sure if the bug is in my code or the broker. + + + + + Using the XML Exchange in Python + 50 + and $w/temperature_f - $w/dewpoint > 5 + and $w/wind_speed_mph > 7 + and $w/wind_speed_mph < 20 +""" + +address = "subscription; {create: always, delete:always, link: { x-bindings: [{ exchange: xml, queue: subscription, key: xml, arguments: { xquery: %r} }] } }" % query + +connection = Connection(broker) + +try: + connection.open() + session = connection.session() + + sender = session.sender("xml") + receiver = session.receiver(address) + + sender.send(Message("Raleigh-Durham International Airport (KRDU)167035")); + + message = receiver.fetch(timeout=1) + print message.content + session.acknowledge() + +except MessagingError,m: + print m +finally: + connection.close() + ]]> + +
+ +
+ Performance + + Clients can often be made significantly faster by batching acknowledgements and setting the capacity of receivers to allow prefetch. + +
+ Batching Acknowledgements + + Many of the simple examples we have shown retrieve a message and immediately acknowledge it. Because each acknowledgement results in network traffic, you can dramatically increase performance by acknowledging messages in batches. For instance, an application can read a number of related messages, then acknowledge the entire batch, or an application can acknowledge after a certain number of messages have been received or a certain time period has elapsed. Messages are not removed from the broker until they are acknowledged, so guaranteed delivery is still available when batching acknowledgements. +
+ + +
+ Prefetch + + By default, a receiver retrieves the next message from the server, one message at a time, which provides intuitive results when writing and debugging programs, but does not provide optimum performance. To create an input buffer, set the capacity of the receiver to the size of the desired input buffer; for many applications, a capacity of 100 performs well. + + + + + Prefetch + + C++ + +Receiver receiver = session.createReceiver(address); +receiver.setCapacity(100); +Message message = receiver.fetch(); + + + + +
+ +
+ +
+ Reliability + +
+ Guaranteed Delivery + + If a queue is durable, the queue survives a messaging + broker crash, as well as any durable messages that have been + placed on the queue. These messages will be delivered when the + messaging broker is restarted. Delivery is guaranteed if and + only if both the message and the queue are durable. Guaranteed + delivery requires a persistence module, such as the one + available from QpidComponents.org. + + + Guaranteed Delivery + + C++: + + + + + + +
+ +
+ + + +
+ Transactions + In AMQP, transactions cover the semantics of enqueues and + dequeues. + + When sending messages, a transaction tracks enqueues + without actually delivering the messages, a commit places + messages on their queues, and a rollback discards the + enqueues. + + When receiving messages, a transaction tracks dequeues + without actually removing acknowledged messages, a commit + removes all acknowledged messages, and a rollback discards + acknowledgements. A rollback does not release the message, it + must be explicitly released to return it to the queue. + + + Transactions + C++: + + + + +
+ + + + +
The AMQP 0-10 mapping @@ -1261,20 +1619,19 @@ options := map For a topic exchange, if no subject is specified and no x-bindings are defined for the link, the subscription - queue will by be bound using a wildcard matching any - routing key (thus satisfying the expectation that any - message sent to that address will be received from it). If - a subject is specified in the source address however, it - will be used for the binding key (this means that the - subject in the source address may be a binding pattern - incuding wildcards). + queue is bound using a wildcard matching any routing key + (thus satisfying the expectation that any message sent to + that address will be received from it). If a subject is + specified in the source address however, it is used for + the binding key (this means that the subject in the source + address may be a binding pattern including wildcards). For a fanout exchange the binding key is irrelevant to matching. A receiver created from a source address that - resolves to a fanout exchange will receive all messages + resolves to a fanout exchange receives all messages sent to that exchange regardless of any subject the source address may contain. An x-bindings element in the link properties should be used if there is any need to set the @@ -1287,22 +1644,22 @@ options := map either contain a subject or must include a value for the x-bindings option in the link properties. This is because there is no way to receive all messages sent to an - exchange of that type. The subject specified will be used - as the binding key (this means it must match the message + exchange of that type. The subject specified is used as + the binding key (this means it must match the message subject exactly). For a headers exchange, if no subject is specified the - binding arguments will simply contain an x-match entry an - no other entries, causing all messages to match. If a - subject is specified then the binding arguments will - contain an x-match entry set to all and an entry for - qpid.subject whose value is the subject in the source - address (this means the subject in the source address must - match the message subject exactly). For more control the - x-bindings element in the link properties must be used. + binding arguments simply contain an x-match entry and no + other entries, causing all messages to match. If a subject + is specified then the binding arguments contain an x-match + entry set to all and an entry for qpid.subject whose value + is the subject in the source address (this means the + subject in the source address must match the message + subject exactly). For more control the x-bindings element + in the link properties must be used. @@ -1311,15 +1668,16 @@ options := map exchange is not a standard AMQP exchange type. It is a Qpid extension and is currently only supported by the C++ broker. if a subject is specified it is - used as the binding key and an XQuery is defined that will - match any message with that value for qpid.subject. Again - this means that only messages whose subject exactly match - that specified in the source address will be received. For - more control the x-bindings element in the link properties - must be used. A source address that resolves to the XML - exchange must contain either a subject or an x-bindings - element in the link properties as there is no way at - present to receive any message regardless of routing key. + used as the binding key and an XQuery is defined that + matches any message with that value for + qpid.subject. Again this means that only messages whose + subject exactly match that specified in the source address + are received. For more control the x-bindings element in + the link properties must be used. A source address that + resolves to the XML exchange must contain either a subject + or an x-bindings element in the link properties as there + is no way at present to receive any message regardless of + routing key. @@ -1342,7 +1700,7 @@ options := map dp refers to an AMQP 0-10 delivery-properties struct. - +
Mapping to AMQP 0-10 Message Properties @@ -1405,7 +1763,7 @@ options := map linkend="section-addresses"/> to identify sources and targets. This program uses a JNDI file that defines a connection factory for the broker we are using, and the address of the - topic exchange node that we will bind the sender and receiver + topic exchange node that we bind the sender and receiver to. (The syntax of a ConnectionURL is given in .) @@ -1486,9 +1844,7 @@ public class Hello { - Apache Qpid defines JNDI properties that can be used to - specify the parameters for a connection. Here is a typical - JNDI properties file: + Apache Qpid defines JNDI properties that can be used to specify JMS Connections and Destinations. Here is a typical JNDI properties file: @@ -1533,7 +1889,7 @@ destination.topicExchange = amq.topic - The Connection URL that the connection factory will use to perform connections. + The Connection URL that the connection factory uses to perform connections. @@ -1748,7 +2104,7 @@ amqp://guest:guest@test/test?sync_ack='true' If ssl='true', only encrypted - connections will be accepted. + connections are accepted. @@ -1850,7 +2206,7 @@ amqp://guest:guest@test/test?sync_ack='true' ssl_cert_alias - + @@ -1922,6 +2278,108 @@ amqp://guest:guest@test/test?sync_ack='true'
+ +
+ Java JMS Selector Syntax + The AMQP Java JMS Messaging Client supports the following syntax for JMS selectors. + + + Comments: + + + + + + Reserved Words (case insensitive) + + + + + + Literals (case insensitive) + + )? // eg: 5.5 or 5. or 5.5E10 or 5.E10 + | "." (["0"-"9"])+ ()? // eg: .5 or .5E10 + | (["0"-"9"])+ // eg: 5E10 +) +EXPONENT: "E" (["+","-"])? (["0"-"9"])+ +STRING_LITERAL: "'" ( ("''") | ~["'"] )* "'" +]]> + + + + + Identifiers (case insensitive) + + + + + + + Grammar + + andExpression )* ) +andExpression := ( equalityExpression ( equalityExpression )* ) +equalityExpression := ( comparisonExpression ( "=" comparisonExpression + | "<>" comparisonExpression + | + | )* ) +comparisonExpression := + ( addExpression + ( ">" addExpression + | ">=" addExpression + | "<" addExpression + | "<=" addExpression + | stringLitteral ( stringLitteral )? + | ( )? + | addExpression addExpression + | addExpression addExpression + | "(" ( "," )* ")" + | "(" ( "," )* ")" + )* + ) + +addExpression := multExpr ( ( "+" multExpr | "-" multExpr ) )* +multExpr := unaryExpr ( "*" unaryExpr | "/" unaryExpr | "%" unaryExpr )* +unaryExpr := ( "+" unaryExpr | "-" unaryExpr | unaryExpr | primaryExpr ) +primaryExpr := ( literal | variable | "(" orExpression ")" ) +literal := ( + | + | + | + | + | + | + | + ) + +variable := ( | )]]> + + + +
+
-- cgit v1.2.1