diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..fd63cefc44 --- /dev/null +++ b/.gitignore @@ -0,0 +1,754 @@ +#idea files +hornetq-pom.ipr +hornetq-pom.iws +.idea +*.iml +*/*.iml +*/*/*.iml +*/*/*/*.iml +dependency-reduced-pom.xml +*/dependency-reduced-pom.xml +*/*/dependency-reduced-pom.xml +*/*/*dependency-reduced-pom.xml +.factorypath + +# compilation from native +*/*/bin +*~ + +target +tests/integration-tests/data/ +tests/joram-tests/data/ +org.eclipse.jdt.core.prefs +org.eclipse.jdt.ui.prefs +org.eclipse.m2e.core.prefs +*/.settings/org.eclipse.* +*/*/.settings/org.eclipse.* +examples/*/*/.settings/org.eclipse.* +examples/*/*/.project +examples/*/.project +!etc/org.eclipse.jdt.ui.prefs +!etc/org.eclipse.jdt.core.prefs +org.maven.ide.eclipse.prefs +.classpath +tests/*-tests/hs_err_pid*.log +tests/**/server.lock +hornetq-core/*.log +.checkstyle + +# / +/build +/eclipse-output +/thirdparty +/logs +/ObjectStore +/tmp +/data +/junit*.properties +/target +/.metadata + +integration/hornetq-*-integration/.project + +# /distribution/ +/distribution/target +/distribution/.project +/distribution/jboss-mc/.project + +# /distribution/hornetq/ +/distribution/hornetq/.project + +# /distribution/jnp-client/ +/distribution/jnp-client/target +/distribution/jnp-client/bin +/distribution/jnp-client/.project + +# /docs/ +/docs/.project + +# /docs/eap-manual/ +/docs/eap-manual/build + +# /docs/quickstart-guide/ +/docs/quickstart-guide/build +/docs/quickstart-guide/target + +# /docs/user-manual/ +/docs/user-manual/build +/docs/user-manual/target +/docs/user-manual/bin +/docs/user-manual/.project + +# /examples/ +/examples/bin +/examples/.project + +# /examples/common/ +/examples/common/build + +# /examples/core/embedded/ +/examples/core/embedded/logs +/examples/core/embedded/build + +# /examples/core/embedded-remote/ +/examples/core/embedded-remote/build + +# /examples/core/microcontainer/ +/examples/core/microcontainer/build + +# /examples/core/perf/ +/examples/core/perf/build +/examples/core/perf/data +/examples/core/perf/logs + +# /examples/javaee/ejb-jms-transaction/ +/examples/javaee/ejb-jms-transaction/build + +# /examples/javaee/hajndi/ +/examples/javaee/hajndi/build + +# /examples/javaee/jca-config/ +/examples/javaee/jca-config/build + +# /examples/javaee/jms-bridge/ +/examples/javaee/jms-bridge/build + +# /examples/javaee/mdb-cmt-tx-local/ +/examples/javaee/mdb-cmt-tx-local/build + +# /examples/javaee/mdb-cmt-tx-required/ +/examples/javaee/mdb-cmt-tx-required/build + +# /examples/javaee/servlet-ssl/ +/examples/javaee/servlet-ssl/build + +# /examples/javaee/servlet-transport/ +/examples/javaee/servlet-transport/build + +# /examples/javaee/xarecovery/ +/examples/javaee/xarecovery/build + +# /examples/ +/examples/build + +# /examples/applet/ +/examples/applet/build + +# /examples/applet/server0/ +/examples/applet/server0/data + +# /examples/application-layer-failover/ +/examples/application-layer-failover/build +/examples/application-layer-failover/logs + +# /examples/application-layer-failover/server0/ +/examples/application-layer-failover/server0/data +/examples/application-layer-failover/server0/logs + +# /examples/application-layer-failover/server1/ +/examples/application-layer-failover/server1/data +/examples/application-layer-failover/server1/logs +/examples/application-layer-failover/server1/KILL_ME + +# /examples/bridge/ +/examples/bridge/build +/examples/bridge/logs + +# /examples/bridge/server0/ +/examples/bridge/server0/data +/examples/bridge/server0/logs + +# /examples/bridge/server1/ +/examples/bridge/server1/data +/examples/bridge/server1/logs + +# /examples/browser/ +/examples/browser/build +/examples/browser/logs + +# /examples/browser/server0/ +/examples/browser/server0/data +/examples/browser/server0/logs + +# /examples/client-kickoff/ +/examples/client-kickoff/build +/examples/client-kickoff/logs + +# /examples/client-kickoff/server0/ +/examples/client-kickoff/server0/data +/examples/client-kickoff/server0/logs + +# /examples/client-side-load-balancing/ +/examples/client-side-load-balancing/build +/examples/client-side-load-balancing/logs + +# /examples/client-side-load-balancing/server0/ +/examples/client-side-load-balancing/server0/data +/examples/client-side-load-balancing/server0/logs + +# /examples/client-side-load-balancing/server1/ +/examples/client-side-load-balancing/server1/data +/examples/client-side-load-balancing/server1/logs + +# /examples/client-side-load-balancing/server2/ +/examples/client-side-load-balancing/server2/data +/examples/client-side-load-balancing/server2/logs + +# /examples/clustered-durable-subscription/ +/examples/clustered-durable-subscription/build +/examples/clustered-durable-subscription/logs + +# /examples/clustered-durable-subscription/server0/ +/examples/clustered-durable-subscription/server0/data +/examples/clustered-durable-subscription/server0/logs + +# /examples/clustered-durable-subscription/server1/ +/examples/clustered-durable-subscription/server1/data +/examples/clustered-durable-subscription/server1/logs + +# /examples/clustered-queue/ +/examples/clustered-queue/build +/examples/clustered-queue/logs + +# /examples/clustered-jgroups/ +/examples/clustered-jgroups/server0 +/examples/clustered-jgroups/server1 + +# /examples/clustered-queue/server0/ +/examples/clustered-queue/server0/data +/examples/clustered-queue/server0/logs + +# /examples/clustered-queue/server1/ +/examples/clustered-queue/server1/data +/examples/clustered-queue/server1/logs + +# /examples/clustered-topic/ +/examples/clustered-topic/build +/examples/clustered-topic/logs + +# /examples/clustered-topic/server0/ +/examples/clustered-topic/server0/data +/examples/clustered-topic/server0/logs + +# /examples/clustered-topic/server1/ +/examples/clustered-topic/server1/data +/examples/clustered-topic/server1/logs + +# /examples/consumer-rate-limit/ +/examples/consumer-rate-limit/build +/examples/consumer-rate-limit/logs + +# /examples/consumer-rate-limit/server0/ +/examples/consumer-rate-limit/server0/data +/examples/consumer-rate-limit/server0/logs + +# /examples/dead-letter/ +/examples/dead-letter/build +/examples/dead-letter/logs + +# /examples/dead-letter/server0/ +/examples/dead-letter/server0/data +/examples/dead-letter/server0/logs + +# /examples/delayed-redelivery/ +/examples/delayed-redelivery/build +/examples/delayed-redelivery/logs + +# /examples/delayed-redelivery/server0/ +/examples/delayed-redelivery/server0/data +/examples/delayed-redelivery/server0/logs + +# /examples/divert/ +/examples/divert/build +/examples/divert/logs + +# /examples/divert/server0/ +/examples/divert/server0/data +/examples/divert/server0/logs + +# /examples/divert/server1/ +/examples/divert/server1/data +/examples/divert/server1/logs + +# /examples/durable-subscription/ +/examples/durable-subscription/build +/examples/durable-subscription/logs + +# /examples/durable-subscription/server0/ +/examples/durable-subscription/server0/data +/examples/durable-subscription/server0/logs + +# /examples/embedded/ +/examples/embedded/logs +/examples/embedded/build + +# /examples/expiry/ +/examples/expiry/build +/examples/expiry/logs + +# /examples/expiry/server0/ +/examples/expiry/server0/data +/examples/expiry/server0/logs + +# /examples/http-transport/ +/examples/http-transport/build +/examples/http-transport/logs + +# /examples/http-transport/server0/ +/examples/http-transport/server0/data +/examples/http-transport/server0/logs + +# /examples/instantiate-connection-factory/ +/examples/instantiate-connection-factory/build +/examples/instantiate-connection-factory/logs + +# /examples/instantiate-connection-factory/server0/ +/examples/instantiate-connection-factory/server0/data +/examples/instantiate-connection-factory/server0/logs + +# /examples/interceptor/ +/examples/interceptor/build +/examples/interceptor/logs + +# /examples/interceptor/server0/ +/examples/interceptor/server0/data +/examples/interceptor/server0/logs + +# /examples/jaas/ +/examples/jaas/build +/examples/jaas/logs + +# /examples/jaas/server0/ +/examples/jaas/server0/data +/examples/jaas/server0/logs + +# /examples/jms-bridge/ +/examples/jms-bridge/build +/examples/jms-bridge/data + +# /examples/jmx/ +/examples/jmx/build +/examples/jmx/logs + +# /examples/jmx/server0/ +/examples/jmx/server0/data +/examples/jmx/server0/logs + +# /examples/large-message/ +/examples/large-message/build +/examples/large-message/logs +/examples/large-message/huge_message_received.dat +/examples/large-message/huge_message_to_send.dat + +# /examples/large-message/server0/ +/examples/large-message/server0/logs +/examples/large-message/server0/data + +# /examples/last-value-queue/ +/examples/last-value-queue/build +/examples/last-value-queue/logs + +# /examples/last-value-queue/server0/ +/examples/last-value-queue/server0/data +/examples/last-value-queue/server0/logs + +# /examples/management/ +/examples/management/build +/examples/management/logs + +# /examples/management/server0/ +/examples/management/server0/data +/examples/management/server0/logs + +# /examples/management-notifications/ +/examples/management-notifications/build +/examples/management-notifications/logs + +# /examples/management-notifications/server0/ +/examples/management-notifications/server0/logs +/examples/management-notifications/server0/data + +# /examples/message-counters/ +/examples/message-counters/build +/examples/message-counters/logs + +# /examples/message-counters/server0/ +/examples/message-counters/server0/data +/examples/message-counters/server0/logs + +# /examples/message-group/ +/examples/message-group/build +/examples/message-group/logs + +# /examples/message-group/server0/ +/examples/message-group/server0/data +/examples/message-group/server0/logs + +# /examples/message-priority/ +/examples/message-priority/build +/examples/message-priority/logs + +# /examples/message-priority/server0/ +/examples/message-priority/server0/data +/examples/message-priority/server0/logs + +# /examples/no-consumer-buffering/ +/examples/no-consumer-buffering/build +/examples/no-consumer-buffering/logs + +# /examples/no-consumer-buffering/server0/ +/examples/no-consumer-buffering/server0/data +/examples/no-consumer-buffering/server0/logs + +# /examples/non-transaction-failover/ +/examples/non-transaction-failover/build + +# /examples/non-transaction-failover/server0/ +/examples/non-transaction-failover/server0/data + +# /examples/non-transaction-failover/server1/ +/examples/non-transaction-failover/server1/data + +# /examples/paging/ +/examples/paging/build +/examples/paging/logs + +# /examples/paging/server0/ +/examples/paging/server0/data +/examples/paging/server0/logs + +# /examples/perf/ +/examples/perf/build +/examples/perf/data + +# /examples/pre-acknowledge/ +/examples/pre-acknowledge/build +/examples/pre-acknowledge/logs + +# /examples/pre-acknowledge/server0/ +/examples/pre-acknowledge/server0/data +/examples/pre-acknowledge/server0/logs + +# /examples/producer-rate-limit/ +/examples/producer-rate-limit/build +/examples/producer-rate-limit/logs + +# /examples/producer-rate-limit/server0/ +/examples/producer-rate-limit/server0/data +/examples/producer-rate-limit/server0/logs + +# /examples/queue/ +/examples/queue/build +/examples/queue/logs + +# /examples/queue/server0/ +/examples/queue/server0/data +/examples/queue/server0/logs + +# /examples/queue-message-redistribution/ +/examples/queue-message-redistribution/build +/examples/queue-message-redistribution/logs + +# /examples/queue-message-redistribution/server0/ +/examples/queue-message-redistribution/server0/data +/examples/queue-message-redistribution/server0/logs + +# /examples/queue-message-redistribution/server1/ +/examples/queue-message-redistribution/server1/data +/examples/queue-message-redistribution/server1/logs + +# /examples/queue-requestor/ +/examples/queue-requestor/build +/examples/queue-requestor/logs + +# /examples/queue-requestor/server0/ +/examples/queue-requestor/server0/data +/examples/queue-requestor/server0/logs + +# /examples/queue-selector/ +/examples/queue-selector/build +/examples/queue-selector/logs + +# /examples/queue-selector/server0/ +/examples/queue-selector/server0/data +/examples/queue-selector/server0/logs + +# /examples/reattach-node/ +/examples/reattach-node/build +/examples/reattach-node/logs + +# /examples/reattach-node/server0/ +/examples/reattach-node/server0/data +/examples/reattach-node/server0/logs + +# /examples/request-reply/ +/examples/request-reply/build +/examples/request-reply/logs + +# /examples/request-reply/server0/ +/examples/request-reply/server0/data +/examples/request-reply/server0/logs + +# /examples/scheduled-message/ +/examples/scheduled-message/build +/examples/scheduled-message/logs + +# /examples/scheduled-message/server0/ +/examples/scheduled-message/server0/data +/examples/scheduled-message/server0/logs + +# /examples/security/ +/examples/security/build +/examples/security/logs + +# /examples/security/server0/ +/examples/security/server0/data +/examples/security/server0/logs + +# /examples/send-acknowledgements/ +/examples/send-acknowledgements/build +/examples/send-acknowledgements/logs + +# /examples/send-acknowledgements/server0/ +/examples/send-acknowledgements/server0/data +/examples/send-acknowledgements/server0/logs + +# /examples/ssl-enabled/ +/examples/ssl-enabled/build +/examples/ssl-enabled/logs + +# /examples/ssl-enabled/server0/ +/examples/ssl-enabled/server0/data +/examples/ssl-enabled/server0/logs + +# /examples/static-selector/ +/examples/static-selector/build +/examples/static-selector/logs + +# /examples/static-selector/server0/ +/examples/static-selector/server0/data +/examples/static-selector/server0/logs + +# /examples/static-selector-jms/ +/examples/static-selector-jms/logs +/examples/static-selector-jms/build + +# /examples/static-selector-jms/server0/ +/examples/static-selector-jms/server0/data +/examples/static-selector-jms/server0/logs + +# /examples/stomp/ +/examples/stomp/build + +# /examples/stomp/server0/ +/examples/stomp/server0/data + +# /examples/symmetric-cluster/ +/examples/symmetric-cluster/build +/examples/symmetric-cluster/logs + +# /examples/symmetric-cluster/server0/ +/examples/symmetric-cluster/server0/data +/examples/symmetric-cluster/server0/logs + +# /examples/symmetric-cluster/server1/ +/examples/symmetric-cluster/server1/data +/examples/symmetric-cluster/server1/logs + +# /examples/symmetric-cluster/server2/ +/examples/symmetric-cluster/server2/data +/examples/symmetric-cluster/server2/logs + +# /examples/symmetric-cluster/server3/ +/examples/symmetric-cluster/server3/data +/examples/symmetric-cluster/server3/logs + +# /examples/symmetric-cluster/server4/ +/examples/symmetric-cluster/server4/data +/examples/symmetric-cluster/server4/logs + +# /examples/symmetric-cluster/server5/ +/examples/symmetric-cluster/server5/data +/examples/symmetric-cluster/server5/logs + +# /examples/temp-queue/ +/examples/temp-queue/build +/examples/temp-queue/logs + +# /examples/temp-queue/server0/ +/examples/temp-queue/server0/data +/examples/temp-queue/server0/logs + +# /examples/topic/ +/examples/topic/build +/examples/topic/logs + +# /examples/topic/server0/ +/examples/topic/server0/data +/examples/topic/server0/logs + +# /examples/topic-hierarchies/ +/examples/topic-hierarchies/build +/examples/topic-hierarchies/logs + +# /examples/topic-hierarchies/server0/ +/examples/topic-hierarchies/server0/data +/examples/topic-hierarchies/server0/logs + +# /examples/topic-selector-example1/ +/examples/topic-selector-example1/build +/examples/topic-selector-example1/logs + +# /examples/topic-selector-example1/server0/ +/examples/topic-selector-example1/server0/data +/examples/topic-selector-example1/server0/logs + +# /examples/topic-selector-example2/ +/examples/topic-selector-example2/build +/examples/topic-selector-example2/logs + +# /examples/topic-selector-example2/server0/ +/examples/topic-selector-example2/server0/data +/examples/topic-selector-example2/server0/logs + +# /examples/transaction-failover/ +/examples/transaction-failover/build + +# /examples/transaction-failover/server0/ +/examples/transaction-failover/server0/data + +# /examples/transaction-failover/server1/ +/examples/transaction-failover/server1/data + +# /examples/transactional/ +/examples/transactional/build +/examples/transactional/logs + +# /examples/transactional/server0/ +/examples/transactional/server0/data +/examples/transactional/server0/logs + +# /examples/xa-heuristic/ +/examples/xa-heuristic/build +/examples/xa-heuristic/logs + +# /examples/xa-heuristic/server0/ +/examples/xa-heuristic/server0/data +/examples/xa-heuristic/server0/logs + +# /examples/xa-receive/ +/examples/xa-receive/build +/examples/xa-receive/logs + +# /examples/xa-receive/server0/ +/examples/xa-receive/server0/data +/examples/xa-receive/server0/logs + +# /examples/xa-send/ +/examples/xa-send/build +/examples/xa-send/logs + +# /examples/xa-send/server0/ +/examples/xa-send/server0/data +/examples/xa-send/server0/logs + +# /examples/xa-with-jta/ +/examples/xa-with-jta/server0/data +/examples/xa-with-jta/build +/examples/xa-with-jta/logs +/examples/xa-with-jta/ObjectStore + +# /examples/xa-with-jta/server0/ +/examples/xa-with-jta/server0/data +/examples/xa-with-jta/server0/logs + +# examples/browser/data/ +examples/browser/data/ + +# examples/client-kickoff/data/ +examples/client-kickoff/data/ + +# examples/consumer-rate-limit/data/ +examples/consumer-rate-limit/data/ + +# examples/data/ +examples/data/ + +# examples/dead-letter/data/ +examples/dead-letter/data/ + +# examples/delayed-redelivery/data/ +examples/delayed-redelivery/data/ + +# examples/durable-subscription/data/ +examples/durable-subscription/data/ + +# examples/expiry/data/ +examples/expiry/data/ + +# examples/http-transport/data/ +examples/http-transport/data/ + +# examples/instantiate-connection-factory/data/ +examples/instantiate-connection-factory/data/ + +# examples/interceptor/data/ +examples/interceptor/data/ + +# examples/jaas/data/ +examples/jaas/data/ + +# examples/jmx/data/ +examples/jmx/data/ + +examples/move.sh +examples/move2.sh +examples/pom-template.xml + +# /examples/soak/normal/ +/examples/soak/normal/build + +# /examples/soak/tx-restarts/ +/examples/soak/tx-restarts/build + +# /hornetq-protocols/ +/hornetq-protocols/hornetq-amqp-protocol/.project +/hornetq-protocols/hornetq-stomp-protocol/.project + +# /hornetq-ra/hornetq-ra-jar/ +/hornetq-ra/hornetq-ra-jar/target +/hornetq-ra/hornetq-ra-jar/.project + +# /hornetq-ra/hornetq-ra-rar/ +/hornetq-ra/hornetq-ra-rar/target +/hornetq-ra/hornetq-ra-rar/.project + +# /hornetq-rest/hornetq-rest/ +/hornetq-rest/target +/hornetq-rest/.project +/hornetq-rest/data/ + +# /hornetq-rest/ +/hornetq-*/.project +/hornetq-*/target + +/tests/.project +/tests/*-tests/.project + +/docs/rest-manual/.project +/docs/quickstart-guide/.project + +native/autom4te.cache +native/src/.libs +native/src/.deps +.settings/org.eclipse.core.resources.prefs + +*.iml +*/*.iml +*/*/*.iml +*/*/*/*.iml + +hornetq.log +*/hornetq.log +*/*/hornetq.log +*/*/*/hornetq.log diff --git a/.project b/.project new file mode 100644 index 0000000000..d928224b6f --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + hornetq + + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/de.loskutov.anyedit.AnyEditTools.prefs b/.settings/de.loskutov.anyedit.AnyEditTools.prefs new file mode 100644 index 0000000000..6858acb592 --- /dev/null +++ b/.settings/de.loskutov.anyedit.AnyEditTools.prefs @@ -0,0 +1,14 @@ +activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk,MANIFEST.MF +convertActionOnSaave=AnyEdit.CnvrtTabToSpaces +eclipse.preferences.version=1 +inActiveContentFilterList= +javaTabWidthForJava=true +org.eclipse.jdt.ui.editor.tab.width=3 +projectPropsEnabled=true +removeTrailingSpaces=true +replaceAllSpaces=false +replaceAllTabs=false +saveAndAddLine=false +saveAndConvert=true +saveAndTrim=true +useModulo4Tabs=false diff --git a/.settings/intellij_settings.jar b/.settings/intellij_settings.jar new file mode 100644 index 0000000000..4a3bf10fcc Binary files /dev/null and b/.settings/intellij_settings.jar differ diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000000..288a13f562 --- /dev/null +++ b/NOTICE @@ -0,0 +1,14 @@ +HornetQ +Copyright 2009 Red Hat, Inc. Licensed under the Apache License, version 2.0. +Unless required by applicable law, HornetQ is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, either express or +implied, including the implied warranties of TITLE, NON-INFRINGEMENT, +MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. + +Certain portions of HornetQ are based on code made available +under the GNU Lesser General Public License, version 2.1 or later +(http://www.fsf.org/licensing/licenses/lgpl.html). +"JBoss" and "Red Hat" are trademarks of Red Hat, Inc. and/or its +affiliates, registered in the U.S. and other countries. Your +permissions under the licensing terms governing HornetQ do +not include a license, express or implied, to any Red Hat trademark. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000000..d37b3a5354 --- /dev/null +++ b/README.md @@ -0,0 +1,171 @@ +# HornetQ + +If you need information about the HornetQ project please go to + +http://community.jboss.org/wiki/HornetQ + +http://www.jboss.org/hornetq/ + +This file describes some minimum 'stuff one needs to know' to get +started coding in this project. + +## Source + +The project's source code is hosted at: + +https://github.com/hornetq + +### Git usage: + +Pull requests should be merged without fast forwards '--no-ff'. An easy way to achieve that is to use + +```% git config branch.master.mergeoptions --no-ff``` + +## Maven + +The minimum required Maven version is 3.0.0. + +Do note that there are some compatibility issues with Maven 3.X still +unsolved [1]. This is specially true for the 'site' plugin [2]. + +[1]: +[2]: + +## Tests + +To run the unit tests: + +```% mvn -Phudson-tests test``` + +Generating reports from unit tests: + +```% mvn install site``` + + +Running tests individually + +```% mvn -Phudson-tests -DfailIfNoTests=false -Dtest= test ``` + +where <test-name> is the name of the Test class without its package name + + +## Examples + +To run an example firstly make sure you have run + +```% mvn -Prelease install``` + +If the project version has already been released then this is unnecessary. + +then you will need to set the following maven options, on Linux by + +```export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=512m"``` + +and the finally run the examples by + +```% mvn verify``` + +You can also run individual examples by running the same command from the directory of which ever example you want to run. +NB for this make sure you have installed examples/common. + +### Recreating the examples + +If you are trying to copy the examples somewhere else and modifying them. Consider asking Maven to explicitly list all the dependencies: + +``` +# if trying to modify the 'topic' example: +cd examples/jms/topic && mvn dependency:list +``` + +## To build a release artifact + +```% mvn -Prelease install``` + +## To build the release bundle + +```% mvn -Prelease package``` + +## Eclipse + +We recommend using Eclipse Kepler (4.3), due to the built-in support +for Maven and Git. Note that there are still some Maven plugins used +by sub-projects (e.g. documentation) which are not supported even in +Eclipse Kepler (4.3). + +Eclipse [m2e] is already included in "Eclipse IDE for Java Developers", or it +can be installed from [Eclipse Kepler release repository]. + +[m2e]: http://eclipse.org/m2e/ +[Eclipse Kepler release repository]: http://download.eclipse.org/releases/kepler + +### Annotation Pre-Processing + +HornetQ uses [JBoss Logging] and that requires source code generation from Java +annotations. In order for it to 'just work' in Eclipse you need to install the +_Maven Integration for Eclipse JDT Annotation Processor Toolkit_ [m2e-apt]. See +this [JBoss blog post] for details. + +[JBoss Logging]: +[m2e-apt]: https://github.com/jbosstools/m2e-apt +[JBoss blog post]: https://community.jboss.org/en/tools/blog/2012/05/20/annotation-processing-support-in-m2e-or-m2e-apt-100-is-out + +### M2E Connector for Javacc-Maven-Plugin + +Eclipse Indigo (3.7) has out-of-the-box support for it. + +As of this writing, Eclipse Kepler (4.3) still lacks support for +Maven's javacc plugin. The available [m2e connector for +javacc-maven-plugin] requires a downgrade of Maven components to be +installed. manual installation instructions (as of this writing you +need to use the development update site). See [this post] for how to +do this with Eclipse Juno (4.2). + +The current recommended solution for Eclipse Kepler is to mark +`javacc-maven-plugin` as ignored by Eclipse, run Maven from the +command line and then modify the project `hornetq-core-client` adding +the folder `target/generated-sources/javacc` to its build path. + +[m2e connector for javacc-maven-plugin]: https://github.com/objectledge/maven-extensions +[this post]: +http://dev.eclipse.org/mhonarc/lists/m2e-users/msg02725.html + +### Use _Project Working Sets_ + +Importing all HornetQ subprojects will create _too many_ projects in Eclipse, +cluttering your _Package Explorer_ and _Project Explorer_ views. One way to address +that is to use [Eclipse's Working Sets] feature. A good introduction to it can be +found at a [Dzone article on Eclipse Working Sets]. + +[Eclipse's Working Sets]: http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.platform.doc.user%2Fconcepts%2Fcworkset.htm +[Dzone article on Eclipse Working Sets]: http://eclipse.dzone.com/articles/categorise-projects-package + +### Code Formatting + +Eclipse code formatting and (basic) project configuration files can be found at +the ```etc/``` folder. You should manually copy them _after importing all your +projects_: + +``` +for settings_dir in `find . -type d -name .settings`; do + \cp -v etc/org.eclipse.jdt.* $settings_dir +done +``` + +Do not use the [maven-eclipse-plugin] to copy the files as it conflicts with [m2e]. + +[maven-eclipse-plugin]: https://maven.apache.org/plugins/maven-eclipse-plugin/ +[m2e]: http://eclipse.org/m2e/ + +## GitHub procedures + +The best way to submit changes to HornetQ is through pull requests on +GitHub. After review a pull request should either get merged or be +rejected. + +When a pull request needs to be reworked, say you have missed +something, the pull request is then closed. When you finished +addressing the required changes you should reopen your original pull +request and it will then be re-evaluated. At that point if the request +is approved we will then merge it. + +Make sure you always rebase your branch on master before submitting pull requests. diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000000..1f839877e9 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,61 @@ +# A check list of things to be done before a release. # + +Things to do before issuing a new MAJOR release: + +* check if all new Configuration parameters are documented; + +* use your IDE to regenerate equals/hashCode for ConfigurationImpl (this + is just much safer than trying to inspect the code). + +* check if all public API classes have a proper Javadoc. + + +## Tagging a release in Git ## + +We must avoid having multiple commits with the same final release version in the POMs. To achieve that, the commit changing the pom versions to the final release version, should be merged together with a second commit changing to version in all pom's to ``X.Y.Z-SNAPSHOT``. + +Assuming current version is ``X.Y.Z-SNAPSHOT`` + +0. Update the release notes. +1. Prepare a single commit changing all version tags in all pom's. +2. tag this commit locally by 'git tag -a HornetQ_X_Y_Z_Final -m "release for x.y.z.Final' or what ever the version is +3. remember to update the version in the main pom, think of a cool name if you can +4. update the hornetq-maven-plugin plugin in the main pom to one that is released, if needed release a new version of the plugin. +5. Either use ``git revert`` to create a new commit reverting the commit with the version changes. Or change again all versions to ``R.S.T-SNAPSHOT``. +6. push both commits with version changes together, including them in the same _pull-request_. +7. push the committed tag upstream 'git push upstream HornetQ_X_Y_Z_Final' +8. download and unpack the tag from github +9. firstly upload the maven artifacts to the staged repository 'mvn -Pmaven-release deploy' (you will need the repository details in your settings.xml' +10. go to nexus (https://repository.jboss.org/nexus/index.html), log in, select staging repositories, select the staging profile that you uploaded and close it. +11. build the standalone release 'mvn -Prelease package' to build the zip and tar.gz + +testing the standalone release (this should be done on windows as well as linux if possible) + +1. unpack the zip or tar.gz +2. start and stop the server (run.sh and stop.sh) for each configuration +3. run the jms examples (follow the instructions under examples/jms/README.md), if you have a failure (memory etc) you can use mvn -rf to restart +4. run the javaee examples (follow instructions under examples/javaee/README.md) +5. check the manuals have been created properly +6. check the javadocs are created correctly (including the diagrams) + +testing the release for AS7 + +1. update the hornetq version in you local AS7 clone (there may be integration work you may have to include that is in the hornetq AS7 clone) +2. commit this and push to your repo +3. go to http://lightning.mw.lab.eng.bos.redhat.com/jenkins/job/as7-param-all-tests/ and run against your repo (using the staged repo). +4. go to http://lightning.mw.lab.eng.bos.redhat.com/jenkins/job/tck6-as7-jms/ and run against your repo (using the staged repo). (note this takes 5 hours) + +If everything is ok then release by: + +1. Upload the binaries and docs to jboss.org (instructions can be found at https://mojo.redhat.com/docs/DOC-81955) +2. go to https://www.jboss.org/author/.magnolia/pages/adminCentral.html and update the download/docs pages and add a release announcement if needed. +3. when you are happy activate the changes +4. go to nexus and release the maven artifacts from the staging repository +5. do announcements twitter/blog + +if there is a problem + +1. delete the tag locally 'git tag -d HornetQ_X_Y_Z_Final" +2. delete the tag remotely 'git push origin :refs/tags/HornetQ_X_Y_Z_Final" +3. go to nexus and drop the profile +4. fix what's broken and start again diff --git a/distribution/hornetq/pom.xml b/distribution/hornetq/pom.xml new file mode 100644 index 0000000000..644b6b4d72 --- /dev/null +++ b/distribution/hornetq/pom.xml @@ -0,0 +1,186 @@ + + + + 4.0.0 + + + + org.hornetq + hornetq-distribution + 2.5.0-SNAPSHOT + + + hornetq + pom + Actual HornetQ Distribution + + + ${project.build.directory}/${project.artifactId}-${project.version}-bin/${project.artifactId}-${project.version}/schema + src/main/resources/config/stand-alone + src/main/resources/config/jboss-as-6 + + + + + org.hornetq + hornetq-core-client + ${project.version} + + + org.hornetq + hornetq-amqp-protocol + ${project.version} + + + org.hornetq + hornetq-stomp-protocol + ${project.version} + + + org.apache.qpid + proton-api + + + org.apache.qpid + proton-j-impl + + + org.apache.qpid + proton-jms + + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + maven-assembly-plugin + 2.2 + + src/main/assembly/dep.xml + gnu + + + + package + + single + + + + + + org.codehaus.mojo + xml-maven-plugin + + + package + + validate + + + + + + + ${standalone}/clustered + ${schemaLocation}/hornetq-configuration.xsd + + hornetq-configuration.xml + + + + ${standalone}/non-clustered + ${schemaLocation}/hornetq-configuration.xsd + + hornetq-configuration.xml + + + + ${as6}/clustered + ${schemaLocation}/hornetq-configuration.xsd + + hornetq-configuration.xml + + + + ${as6}/non-clustered + ${schemaLocation}/hornetq-configuration.xsd + + hornetq-configuration.xml + + + + ${standalone}/clustered + ${schemaLocation}/hornetq-jms.xsd + + hornetq-jms.xml + + + + ${standalone}/non-clustered + ${schemaLocation}/hornetq-jms.xsd + + hornetq-jms.xml + + + + ${as6}/clustered + ${schemaLocation}/hornetq-jms.xsd + + hornetq-jms.xml + + + + ${as6}/non-clustered + ${schemaLocation}/hornetq-jms.xsd + + hornetq-jms.xml + + + + ${standalone}/clustered + ${schemaLocation}/hornetq-users.xsd + + hornetq-users.xml + + + + ${standalone}/non-clustered + ${schemaLocation}/hornetq-users.xsd + + hornetq-users.xml + + + + + + + + + + diff --git a/distribution/hornetq/src/main/assembly/dep.xml b/distribution/hornetq/src/main/assembly/dep.xml new file mode 100644 index 0000000000..f2ee1d1c99 --- /dev/null +++ b/distribution/hornetq/src/main/assembly/dep.xml @@ -0,0 +1,508 @@ + + + + + bin + + dir + zip + tar.gz + + true + + + true + + org.hornetq:hornetq-commons + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-journal + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-native + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-tools + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-bootstrap + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-server + + + false + + true + + + **/*.xsd + + + + + + true + + org.hornetq:hornetq-native + + + false + bin + true + + + **/*.so + + + + + + true + + org.hornetq:hornetq-core-client + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-server + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-jboss-as-integration + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-jms-client + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-jms-server + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-jms-server + + + false + + true + + + **/*.xsd + + + + + + true + + org.hornetq:hornetq-jms-client + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-ra + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-service-sar + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-spring-integration + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-twitter-integration + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-vertx-integration + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq.rest:hornetq-rest + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-amqp-protocol + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-aerogear-integration + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-stomp-protocol + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-selector + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:jnp-client + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:jboss-mc + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:jboss-mc + + + false + lib + false + ${module.artifactId}.${module.extension} + + + + true + + org.hornetq:hornetq-core-client + + + javadoc + false + docs/api/hornetq-client + + + + true + + org.hornetq:hornetq-server + + + javadoc + false + docs/api/hornetq-server + + + + true + + org.hornetq:hornetq-jms-client + + + javadoc + false + docs/api/hornetq-jms-client + + + + true + + org.hornetq:hornetq-jms-server + + + javadoc + false + docs/api/hornetq-jms-server + + + + + + + org.jboss.spec.javax.jms:jboss-jms-api_2.0_spec + + lib + false + jboss-jms-api.jar + + + + org.jboss.naming:jnpserver + + lib + false + jnpserver.jar + + + + io.netty:netty-all + + lib + false + netty.jar + + + + org.apache.qpid:proton-api + + lib + false + proton-api.jar + + + + org.apache.qpid:proton-jms + + lib + false + proton-jms.jar + + + + org.apache.qpid:proton-j-impl + + lib + false + proton-j-impl.jar + + + + + src/main/resources/config + config + keep + + **/trunk/** + *.properties + + + + src/main/resources/bin + bin + keep + + + src/main/resources/licenses + licenses + keep + + + src/main/resources/examples + examples + keep + + + ../../examples + examples + keep + + **/target/** + **/**/*.iml + **/**/*.dat + + + + + ../../docs/user-manual/target/docbook/publish/en + docs/user-manual + keep + + + ../../docs/quickstart-guide/target/docbook/publish/en + docs/quickstart-guide + keep + + + ../../docs/rest-manual/target/docbook/publish/en + docs/rest-manual + keep + + + diff --git a/distribution/hornetq/src/main/resources/bin/run.bat b/distribution/hornetq/src/main/resources/bin/run.bat new file mode 100644 index 0000000000..0772410a56 --- /dev/null +++ b/distribution/hornetq/src/main/resources/bin/run.bat @@ -0,0 +1,21 @@ +@ echo off +setlocal ENABLEDELAYEDEXPANSION +set HORNETQ_HOME=.. +IF "a%1"== "a" ( +set CONFIG_DIR=%HORNETQ_HOME%\config\stand-alone\non-clustered +) ELSE ( +SET CONFIG_DIR=%1 +) +set CLASSPATH=%CONFIG_DIR%;%HORNETQ_HOME%\schemas\ +REM you can use the following line if you want to run with different ports +REM set CLUSTER_PROPS="-Djnp.port=1099 -Djnp.rmiPort=1098 -Djnp.host=localhost -Dhornetq.remoting.netty.host=localhost -Dhornetq.remoting.netty.port=5445" +set JVM_ARGS=%CLUSTER_PROPS% -XX:+UseParallelGC -XX:+AggressiveOpts -XX:+UseFastAccessorMethods -Xms512M -Xmx1024M -Dhornetq.config.dir=%CONFIG_DIR% -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Djava.util.logging.config.file=%CONFIG_DIR%\logging.properties -Djava.library.path=. +REM export JVM_ARGS="-Xmx512M -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Djava.util.logging.config.file=%CONFIG_DIR%\logging.properties -Dhornetq.config.dir=$CONFIG_DIR -Djava.library.path=. -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" +for /R ..\lib %%A in (*.jar) do ( +SET CLASSPATH=!CLASSPATH!;%%A +) +mkdir ..\logs +echo *********************************************************************************** +echo "java %JVM_ARGS% -classpath %CLASSPATH% org.hornetq.integration.bootstrap.HornetQBootstrapServer hornetq-beans.xml" +echo *********************************************************************************** +java %JVM_ARGS% -classpath "%CLASSPATH%" org.hornetq.integration.bootstrap.HornetQBootstrapServer hornetq-beans.xml diff --git a/distribution/hornetq/src/main/resources/bin/run.sh b/distribution/hornetq/src/main/resources/bin/run.sh new file mode 100755 index 0000000000..87e5aa869c --- /dev/null +++ b/distribution/hornetq/src/main/resources/bin/run.sh @@ -0,0 +1,35 @@ +#!/bin/sh +#------------------------------------------------ +# Simple shell-script to run HornetQ standalone +#------------------------------------------------ + +export HORNETQ_HOME=.. +mkdir -p ../logs + +# By default, the server is started in the non-clustered standalone configuration + +if [ a"$1" = a ]; then CONFIG_DIR=$HORNETQ_HOME/config/stand-alone/non-clustered; else CONFIG_DIR="$1"; fi +if [ a"$2" = a ]; then FILENAME=hornetq-beans.xml; else FILENAME="$2"; fi + +if [ ! -d $CONFIG_DIR ]; then + echo script needs to be run from the HORNETQ_HOME/bin directory >&2 + exit 1 +fi + +RESOLVED_CONFIG_DIR=`cd "$CONFIG_DIR"; pwd` +export CLASSPATH=$RESOLVED_CONFIG_DIR:$HORNETQ_HOME/schemas/ + +# Use the following line to run with different ports +#export CLUSTER_PROPS="-Djnp.port=1099 -Djnp.rmiPort=1098 -Djnp.host=localhost -Dhornetq.remoting.netty.host=localhost -Dhornetq.remoting.netty.port=5445" + +export JVM_ARGS="$CLUSTER_PROPS -XX:+UseParallelGC -XX:+AggressiveOpts -XX:+UseFastAccessorMethods -Xms512M -Xmx1024M -Dhornetq.config.dir=$RESOLVED_CONFIG_DIR -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Dlogging.configuration=file://$RESOLVED_CONFIG_DIR/logging.properties -Djava.library.path=./lib/linux-i686:./lib/linux-x86_64" +#export JVM_ARGS="-Xmx512M -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Dlogging.configuration=$CONFIG_DIR/logging.properties -Dhornetq.config.dir=$CONFIG_DIR -Djava.library.path=. -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" + +for i in `ls $HORNETQ_HOME/lib/*.jar`; do + CLASSPATH=$i:$CLASSPATH +done + +echo "***********************************************************************************" +echo "java $JVM_ARGS -classpath $CLASSPATH org.hornetq.integration.bootstrap.HornetQBootstrapServer $FILENAME" +echo "***********************************************************************************" +java $JVM_ARGS -classpath $CLASSPATH -Dcom.sun.management.jmxremote org.hornetq.integration.bootstrap.HornetQBootstrapServer $FILENAME diff --git a/distribution/hornetq/src/main/resources/bin/stop.bat b/distribution/hornetq/src/main/resources/bin/stop.bat new file mode 100644 index 0000000000..4a1aa8eb41 --- /dev/null +++ b/distribution/hornetq/src/main/resources/bin/stop.bat @@ -0,0 +1,9 @@ +@ echo off +setlocal ENABLEDELAYEDEXPANSION +set HORNETQ_HOME=.. +IF "a%1"== "a" ( +set CONFIG_DIR=%HORNETQ_HOME%\config\stand-alone\non-clustered +) ELSE ( +SET CONFIG_DIR=%1 +) +dir >> %CONFIG_DIR%\STOP_ME \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/bin/stop.sh b/distribution/hornetq/src/main/resources/bin/stop.sh new file mode 100755 index 0000000000..9f5524897f --- /dev/null +++ b/distribution/hornetq/src/main/resources/bin/stop.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +export HORNETQ_HOME=.. +if [ a"$1" = a ]; then CONFIG_DIR=$HORNETQ_HOME/config/stand-alone/non-clustered; else CONFIG_DIR="$1"; fi +touch $CONFIG_DIR/STOP_ME; \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/hornetq-configuration.xml b/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/hornetq-configuration.xml new file mode 100644 index 0000000000..fb54135088 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/hornetq-configuration.xml @@ -0,0 +1,122 @@ + + + + + + HornetQ.main.config + + ${jboss.server.data.dir}/${hornetq.data.dir:hornetq}/bindings + + ${jboss.server.data.dir}/${hornetq.data.dir:hornetq}/journal + + 10 + + ${jboss.server.data.dir}/${hornetq.data.dir:hornetq}/largemessages + + ${jboss.server.data.dir}/${hornetq.data.dir:hornetq}/paging + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + + org.hornetq.core.remoting.impl.invm.InVMConnectorFactory + + + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + + + org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory + + + + + + + + 231.7.7.7 + 9876 + 5000 + netty + + + + + + 231.7.7.7 + 9876 + 10000 + + + + + +
jms
+ netty + +
+
+ + + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + 10 + BLOCK + + + +
diff --git a/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/hornetq-jboss-beans.xml b/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/hornetq-jboss-beans.xml new file mode 100644 index 0000000000..50768e0c06 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/hornetq-jboss-beans.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + ${jboss.server.home.url}/deploy/hornetq/hornetq-configuration.xml + + + + + + + JBossSecurityJNDIContextEstablishment + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jboss.jca:name='jms-ra.rar',service=RARDeployment + + HornetQServer + + + diff --git a/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/hornetq-jms.xml b/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/hornetq-jms.xml new file mode 100644 index 0000000000..8d4bd7af8a --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/hornetq-jms.xml @@ -0,0 +1,47 @@ + + + + true + + + + + + + + + + + true + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + diff --git a/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/jms-ds.xml b/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/jms-ds.xml new file mode 100644 index 0000000000..f387cf9efb --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/jboss-as-6/clustered/jms-ds.xml @@ -0,0 +1,26 @@ + + + + + DefaultJMSProvider + org.jboss.jms.jndi.JNDIProviderAdapter + java:/XAConnectionFactory + java:/XAConnectionFactory + java:/XAConnectionFactory + + + + JmsXA + + jms-ra.rar + org.hornetq.ra.HornetQRAConnectionFactory + javax.jms.Topic + java:/DefaultJMSProvider + 20 + JmsXARealm + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/hornetq-configuration.xml b/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/hornetq-configuration.xml new file mode 100644 index 0000000000..a92796f3f0 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/hornetq-configuration.xml @@ -0,0 +1,97 @@ + + + + + + HornetQ.main.config + + ${jboss.server.data.dir}/hornetq/bindings + + ${jboss.server.data.dir}/hornetq/journal + + 10 + + ${jboss.server.data.dir}/hornetq/largemessages + + ${jboss.server.data.dir}/hornetq/paging + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + + org.hornetq.core.remoting.impl.invm.InVMConnectorFactory + + + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + + + org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory + + + + + + + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + 10 + BLOCK + + + + diff --git a/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/hornetq-jboss-beans.xml b/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/hornetq-jboss-beans.xml new file mode 100644 index 0000000000..238792c3f3 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/hornetq-jboss-beans.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + ${jboss.server.home.url}/deploy/hornetq/hornetq-configuration.xml + + + + + + + JBossSecurityJNDIContextEstablishment + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jboss.jca:name='jms-ra.rar',service=RARDeployment + + HornetQServer + + diff --git a/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/hornetq-jms.xml b/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/hornetq-jms.xml new file mode 100644 index 0000000000..8fcc22798a --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/hornetq-jms.xml @@ -0,0 +1,46 @@ + + + + true + + + + + + + + + + + true + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + diff --git a/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/jms-ds.xml b/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/jms-ds.xml new file mode 100644 index 0000000000..f387cf9efb --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/jboss-as-6/non-clustered/jms-ds.xml @@ -0,0 +1,26 @@ + + + + + DefaultJMSProvider + org.jboss.jms.jndi.JNDIProviderAdapter + java:/XAConnectionFactory + java:/XAConnectionFactory + java:/XAConnectionFactory + + + + JmsXA + + jms-ra.rar + org.hornetq.ra.HornetQRAConnectionFactory + javax.jms.Topic + java:/DefaultJMSProvider + 20 + JmsXARealm + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-beans.xml b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-beans.xml new file mode 100644 index 0000000000..423c8cb6fc --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-beans.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${jnp.port:1099} + ${jnp.host:localhost} + ${jnp.rmiPort:1098} + ${jnp.host:localhost} + + + + + + + + + + + + + diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-configuration.xml b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-configuration.xml new file mode 100644 index 0000000000..474d507616 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-configuration.xml @@ -0,0 +1,94 @@ + + + ${data.dir:../data}/paging + + ${data.dir:../data}/bindings + + ${data.dir:../data}/journal + + 10 + + ${data.dir:../data}/large-messages + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + + + + + 231.7.7.7 + 9876 + 5000 + netty + + + + + + 231.7.7.7 + 9876 + 10000 + + + + + +
jms
+ netty + +
+
+ + + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + 10 + BLOCK + + + + + +
diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-jms.xml b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-jms.xml new file mode 100644 index 0000000000..044d7e88ed --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-jms.xml @@ -0,0 +1,53 @@ + + + + true + + + + + + + + + + false + + + + + + + + + + true + + + + + + + + + + false + + + + + + + + + + + + + + + + + diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-users.xml b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-users.xml new file mode 100644 index 0000000000..934306c4b5 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/hornetq-users.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/clustered/jndi.properties b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/jndi.properties new file mode 100644 index 0000000000..e2a9832f8e --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/jndi.properties @@ -0,0 +1,2 @@ +java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/clustered/logging.properties b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/logging.properties new file mode 100644 index 0000000000..3b725aff65 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/clustered/logging.properties @@ -0,0 +1,56 @@ +# +# JBoss, Home of Professional Open Source. +# Copyright 2010, Red Hat, Inc., and individual contributors +# as indicated by the @author tags. See the copyright.txt file in the +# distribution for a full listing of individual contributors. +# +# This is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this software; if not, write to the Free +# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA, or see the FSF site: http://www.fsf.org. +# + +# Additional logger names to configure (root logger is always configured) +# Root logger option +loggers=org.jboss.logging,org.hornetq.core.server,org.hornetq.utils,org.hornetq.journal,org.hornetq.jms,org.hornetq.integration.bootstrap + +# Root logger level +logger.level=INFO +# HornetQ logger levels +logger.org.hornetq.core.server.level=INFO +logger.org.hornetq.journal.level=INFO +logger.org.hornetq.utils.level=INFO +logger.org.hornetq.jms.level=INFO +logger.org.hornetq.integration.bootstrap.level=INFO +# Root logger handlers +logger.handlers=FILE,CONSOLE + +# Console handler configuration +handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler +handler.CONSOLE.properties=autoFlush +handler.CONSOLE.level=DEBUG +handler.CONSOLE.autoFlush=true +handler.CONSOLE.formatter=PATTERN + +# File handler configuration +handler.FILE=org.jboss.logmanager.handlers.FileHandler +handler.FILE.level=DEBUG +handler.FILE.properties=autoFlush,fileName +handler.FILE.autoFlush=true +handler.FILE.fileName=logs/hornetq.log +handler.FILE.formatter=PATTERN + +# Formatter pattern configuration +formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter +formatter.PATTERN.properties=pattern +formatter.PATTERN.pattern=%d{HH:mm:ss,SSS} %-5p [%c] %s%E%n diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-beans.xml b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-beans.xml new file mode 100644 index 0000000000..2cbcb12b25 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-beans.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${jnp.port:1099} + ${jnp.host:localhost} + ${jnp.rmiPort:1098} + ${jnp.host:localhost} + + + + + + + + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-configuration.xml b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-configuration.xml new file mode 100644 index 0000000000..8b0922d344 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-configuration.xml @@ -0,0 +1,67 @@ + + + ${data.dir:../data}/paging + + ${data.dir:../data}/bindings + + ${data.dir:../data}/journal + + 10 + + ${data.dir:../data}/large-messages + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + + + + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + 10 + BLOCK + + + + diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-jms.xml b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-jms.xml new file mode 100644 index 0000000000..044d7e88ed --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-jms.xml @@ -0,0 +1,53 @@ + + + + true + + + + + + + + + + false + + + + + + + + + + true + + + + + + + + + + false + + + + + + + + + + + + + + + + + diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-users.xml b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-users.xml new file mode 100644 index 0000000000..934306c4b5 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/hornetq-users.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/jndi.properties b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/jndi.properties new file mode 100644 index 0000000000..e2a9832f8e --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/jndi.properties @@ -0,0 +1,2 @@ +java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/logging.properties b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/logging.properties new file mode 100644 index 0000000000..e9b25803da --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/non-clustered/logging.properties @@ -0,0 +1,56 @@ +# +# JBoss, Home of Professional Open Source. +# Copyright 2010, Red Hat, Inc., and individual contributors +# as indicated by the @author tags. See the copyright.txt file in the +# distribution for a full listing of individual contributors. +# +# This is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this software; if not, write to the Free +# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA, or see the FSF site: http://www.fsf.org. +# + +# Additional logger names to configure (root logger is always configured) +# Root logger option +loggers=org.jboss.logging,org.hornetq.core.server,org.hornetq.utils,org.hornetq.journal,org.hornetq.jms,org.hornetq.integration.bootstrap + +# Root logger level +logger.level=INFO +# HornetQ logger levels +logger.org.hornetq.core.server.level=INFO +logger.org.hornetq.journal.level=INFO +logger.org.hornetq.utils.level=INFO +logger.org.hornetq.jms.level=INFO +logger.org.hornetq.integration.bootstrap.level=INFO +# Root logger handlers +logger.handlers=FILE,CONSOLE + +# Console handler configuration +handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler +handler.CONSOLE.properties=autoFlush +handler.CONSOLE.level=FINE +handler.CONSOLE.autoFlush=true +handler.CONSOLE.formatter=PATTERN + +# File handler configuration +handler.FILE=org.jboss.logmanager.handlers.FileHandler +handler.FILE.level=FINE +handler.FILE.properties=autoFlush,fileName +handler.FILE.autoFlush=true +handler.FILE.fileName=logs/hornetq.log +handler.FILE.formatter=PATTERN + +# Formatter pattern configuration +formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter +formatter.PATTERN.properties=pattern +formatter.PATTERN.pattern=%d{HH:mm:ss,SSS} %-5p [%c] %s%E%n diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-beans.xml b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-beans.xml new file mode 100644 index 0000000000..423c8cb6fc --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-beans.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${jnp.port:1099} + ${jnp.host:localhost} + ${jnp.rmiPort:1098} + ${jnp.host:localhost} + + + + + + + + + + + + + diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-configuration.xml b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-configuration.xml new file mode 100644 index 0000000000..5605f0069c --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-configuration.xml @@ -0,0 +1,101 @@ + + + false + + ${hornetq.backup:false} + + ${data.dir:../data}/paging + + ${data.dir:../data}/bindings + + ${data.dir:../data}/journal + + 10 + + ${data.dir:../data}/large-messages + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + + + + + 231.7.7.7 + 9876 + 5000 + netty + + + + + + 231.7.7.7 + 9876 + 10000 + + + + + +
jms
+ netty + +
+
+ + + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + 10 + BLOCK + + + + + +
diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-jms.xml b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-jms.xml new file mode 100644 index 0000000000..044d7e88ed --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-jms.xml @@ -0,0 +1,53 @@ + + + + true + + + + + + + + + + false + + + + + + + + + + true + + + + + + + + + + false + + + + + + + + + + + + + + + + + diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-users.xml b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-users.xml new file mode 100644 index 0000000000..934306c4b5 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/hornetq-users.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/replicated/jndi.properties b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/jndi.properties new file mode 100644 index 0000000000..e2a9832f8e --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/jndi.properties @@ -0,0 +1,2 @@ +java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/replicated/logging.properties b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/logging.properties new file mode 100644 index 0000000000..3b725aff65 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/replicated/logging.properties @@ -0,0 +1,56 @@ +# +# JBoss, Home of Professional Open Source. +# Copyright 2010, Red Hat, Inc., and individual contributors +# as indicated by the @author tags. See the copyright.txt file in the +# distribution for a full listing of individual contributors. +# +# This is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this software; if not, write to the Free +# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA, or see the FSF site: http://www.fsf.org. +# + +# Additional logger names to configure (root logger is always configured) +# Root logger option +loggers=org.jboss.logging,org.hornetq.core.server,org.hornetq.utils,org.hornetq.journal,org.hornetq.jms,org.hornetq.integration.bootstrap + +# Root logger level +logger.level=INFO +# HornetQ logger levels +logger.org.hornetq.core.server.level=INFO +logger.org.hornetq.journal.level=INFO +logger.org.hornetq.utils.level=INFO +logger.org.hornetq.jms.level=INFO +logger.org.hornetq.integration.bootstrap.level=INFO +# Root logger handlers +logger.handlers=FILE,CONSOLE + +# Console handler configuration +handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler +handler.CONSOLE.properties=autoFlush +handler.CONSOLE.level=DEBUG +handler.CONSOLE.autoFlush=true +handler.CONSOLE.formatter=PATTERN + +# File handler configuration +handler.FILE=org.jboss.logmanager.handlers.FileHandler +handler.FILE.level=DEBUG +handler.FILE.properties=autoFlush,fileName +handler.FILE.autoFlush=true +handler.FILE.fileName=logs/hornetq.log +handler.FILE.formatter=PATTERN + +# Formatter pattern configuration +formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter +formatter.PATTERN.properties=pattern +formatter.PATTERN.pattern=%d{HH:mm:ss,SSS} %-5p [%c] %s%E%n diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-beans.xml b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-beans.xml new file mode 100644 index 0000000000..423c8cb6fc --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-beans.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${jnp.port:1099} + ${jnp.host:localhost} + ${jnp.rmiPort:1098} + ${jnp.host:localhost} + + + + + + + + + + + + + diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-configuration.xml b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-configuration.xml new file mode 100644 index 0000000000..dea7a7b19d --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-configuration.xml @@ -0,0 +1,101 @@ + + + true + + ${hornetq.backup:false} + + ${data.dir:../data}/paging + + ${data.dir:../data}/bindings + + ${data.dir:../data}/journal + + 10 + + ${data.dir:../data}/large-messages + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + + + + + 231.7.7.7 + 9876 + 5000 + netty + + + + + + 231.7.7.7 + 9876 + 10000 + + + + + +
jms
+ netty + +
+
+ + + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + 10 + BLOCK + + + + + +
diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-jms.xml b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-jms.xml new file mode 100644 index 0000000000..044d7e88ed --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-jms.xml @@ -0,0 +1,53 @@ + + + + true + + + + + + + + + + false + + + + + + + + + + true + + + + + + + + + + false + + + + + + + + + + + + + + + + + diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-users.xml b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-users.xml new file mode 100644 index 0000000000..934306c4b5 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/hornetq-users.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/jndi.properties b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/jndi.properties new file mode 100644 index 0000000000..e2a9832f8e --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/jndi.properties @@ -0,0 +1,2 @@ +java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/logging.properties b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/logging.properties new file mode 100644 index 0000000000..3b725aff65 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/stand-alone/shared-store/logging.properties @@ -0,0 +1,56 @@ +# +# JBoss, Home of Professional Open Source. +# Copyright 2010, Red Hat, Inc., and individual contributors +# as indicated by the @author tags. See the copyright.txt file in the +# distribution for a full listing of individual contributors. +# +# This is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this software; if not, write to the Free +# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA, or see the FSF site: http://www.fsf.org. +# + +# Additional logger names to configure (root logger is always configured) +# Root logger option +loggers=org.jboss.logging,org.hornetq.core.server,org.hornetq.utils,org.hornetq.journal,org.hornetq.jms,org.hornetq.integration.bootstrap + +# Root logger level +logger.level=INFO +# HornetQ logger levels +logger.org.hornetq.core.server.level=INFO +logger.org.hornetq.journal.level=INFO +logger.org.hornetq.utils.level=INFO +logger.org.hornetq.jms.level=INFO +logger.org.hornetq.integration.bootstrap.level=INFO +# Root logger handlers +logger.handlers=FILE,CONSOLE + +# Console handler configuration +handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler +handler.CONSOLE.properties=autoFlush +handler.CONSOLE.level=DEBUG +handler.CONSOLE.autoFlush=true +handler.CONSOLE.formatter=PATTERN + +# File handler configuration +handler.FILE=org.jboss.logmanager.handlers.FileHandler +handler.FILE.level=DEBUG +handler.FILE.properties=autoFlush,fileName +handler.FILE.autoFlush=true +handler.FILE.fileName=logs/hornetq.log +handler.FILE.formatter=PATTERN + +# Formatter pattern configuration +formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter +formatter.PATTERN.properties=pattern +formatter.PATTERN.pattern=%d{HH:mm:ss,SSS} %-5p [%c] %s%E%n diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-beans.xml b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-beans.xml new file mode 100644 index 0000000000..9705de0151 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-beans.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + ${jnp.port:1199} + ${jnp.host:localhost} + ${jnp.rmiPort:1198} + ${jnp.host:localhost} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-configuration.xml b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-configuration.xml new file mode 100644 index 0000000000..f0a2dc2fea --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-configuration.xml @@ -0,0 +1,88 @@ + + + + + true + + true + + true + + 10 + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + + + 231.7.7.7 + 9876 + 5000 + netty + + + + + + 231.7.7.7 + 9876 + 60000 + + + + + +
jms
+ netty + +
+
+ + + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + 10 + BLOCK + + + +
diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-jms.xml b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-jms.xml new file mode 100644 index 0000000000..3346589ad9 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-jms.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-users.xml b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-users.xml new file mode 100644 index 0000000000..934306c4b5 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/hornetq-users.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/jndi.properties b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/jndi.properties new file mode 100644 index 0000000000..629072e931 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/jndi.properties @@ -0,0 +1,15 @@ +# +# Copyright 2009 Red Hat, Inc. +# Red Hat licenses this file to you under the Apache License, version +# 2.0 (the "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# + +java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/logging.properties b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/logging.properties new file mode 100644 index 0000000000..dd49eadadf --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered-backup/logging.properties @@ -0,0 +1,34 @@ +############################################################ +# Default Logging Configuration File +# +# You can use a different file by specifying a filename +# with the java.util.logging.config.file system property. +# For example java -Djava.util.logging.config.file=myfile +############################################################ + +############################################################ +# Global properties +############################################################ + +# "handlers" specifies a comma separated list of log Handler +# classes. These handlers will be installed during VM startup. +# Note that these classes must be on the system classpath. +# By default we only configure a ConsoleHandler, which will only +# show messages at the INFO and above levels. +handlers=java.util.logging.ConsoleHandler,java.util.logging.FileHandler +java.util.logging.ConsoleHandler.formatter=org.hornetq.integration.logging.HornetQLoggerFormatter +java.util.logging.FileHandler.level=INFO +java.util.logging.FileHandler.pattern=logs/hornetq.log +java.util.logging.FileHandler.formatter=org.hornetq.integration.logging.HornetQLoggerFormatter +# Default global logging level. +# This specifies which kinds of events are logged across +# all loggers. For any given facility this global level +# can be overriden by a facility specific level +# Note that the ConsoleHandler also has a separate level +# setting to limit messages printed to the console. +.level= INFO + +############################################################ +# Handler specific properties. +# Describes specific configuration info for Handlers. +############################################################ diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-beans.xml b/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-beans.xml new file mode 100644 index 0000000000..58afc780a5 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-beans.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + ${jnp.port:1099} + ${jnp.host:localhost} + ${jnp.rmiPort:1098} + ${jnp.host:localhost} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-configuration.xml b/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-configuration.xml new file mode 100644 index 0000000000..41fe395d12 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-configuration.xml @@ -0,0 +1,73 @@ + + + false + + true + + 10 + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + + + 231.7.7.7 + 9876 + 5000 + netty + + + + + + 231.7.7.7 + 9876 + 60000 + + + + + +
jms
+ netty + +
+
+ + + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + 10 + BLOCK + + + +
diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-jms.xml b/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-jms.xml new file mode 100644 index 0000000000..3346589ad9 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-jms.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-users.xml b/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-users.xml new file mode 100644 index 0000000000..934306c4b5 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered/hornetq-users.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered/jndi.properties b/distribution/hornetq/src/main/resources/config/trunk/clustered/jndi.properties new file mode 100644 index 0000000000..e2a9832f8e --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered/jndi.properties @@ -0,0 +1,2 @@ +java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/clustered/logging.properties b/distribution/hornetq/src/main/resources/config/trunk/clustered/logging.properties new file mode 100644 index 0000000000..dd49eadadf --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/clustered/logging.properties @@ -0,0 +1,34 @@ +############################################################ +# Default Logging Configuration File +# +# You can use a different file by specifying a filename +# with the java.util.logging.config.file system property. +# For example java -Djava.util.logging.config.file=myfile +############################################################ + +############################################################ +# Global properties +############################################################ + +# "handlers" specifies a comma separated list of log Handler +# classes. These handlers will be installed during VM startup. +# Note that these classes must be on the system classpath. +# By default we only configure a ConsoleHandler, which will only +# show messages at the INFO and above levels. +handlers=java.util.logging.ConsoleHandler,java.util.logging.FileHandler +java.util.logging.ConsoleHandler.formatter=org.hornetq.integration.logging.HornetQLoggerFormatter +java.util.logging.FileHandler.level=INFO +java.util.logging.FileHandler.pattern=logs/hornetq.log +java.util.logging.FileHandler.formatter=org.hornetq.integration.logging.HornetQLoggerFormatter +# Default global logging level. +# This specifies which kinds of events are logged across +# all loggers. For any given facility this global level +# can be overriden by a facility specific level +# Note that the ConsoleHandler also has a separate level +# setting to limit messages printed to the console. +.level= INFO + +############################################################ +# Handler specific properties. +# Describes specific configuration info for Handlers. +############################################################ diff --git a/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-beans.xml b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-beans.xml new file mode 100644 index 0000000000..195019f2fd --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-beans.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + 1099 + localhost + 1098 + localhost + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-configuration.xml b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-configuration.xml new file mode 100644 index 0000000000..d6788f3af5 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-configuration.xml @@ -0,0 +1,59 @@ + + + 10 + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + + + + + + + + + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + 10 + BLOCK + + + + diff --git a/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-jms.xml b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-jms.xml new file mode 100644 index 0000000000..3a3dbeb697 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-jms.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-users.xml b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-users.xml new file mode 100644 index 0000000000..934306c4b5 --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/hornetq-users.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/non-clustered/jndi.properties b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/jndi.properties new file mode 100644 index 0000000000..e2a9832f8e --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/jndi.properties @@ -0,0 +1,2 @@ +java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/config/trunk/non-clustered/logging.properties b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/logging.properties new file mode 100644 index 0000000000..00f9c3da5c --- /dev/null +++ b/distribution/hornetq/src/main/resources/config/trunk/non-clustered/logging.properties @@ -0,0 +1,38 @@ +############################################################ +# Default Logging Configuration File +# +# You can use a different file by specifying a filename +# with the java.util.logging.config.file system property. +# For example java -Djava.util.logging.config.file=myfile +############################################################ + +############################################################ +# Global properties +############################################################ + +# "handlers" specifies a comma separated list of log Handler +# classes. These handlers will be installed during VM startup. +# Note that these classes must be on the system classpath. +# By default we only configure a ConsoleHandler, which will only +# show messages at the INFO and above levels. +handlers=java.util.logging.ConsoleHandler,java.util.logging.FileHandler +java.util.logging.ConsoleHandler.formatter=org.hornetq.integration.logging.HornetQLoggerFormatter +java.util.logging.FileHandler.level=INFO +java.util.logging.FileHandler.formatter=org.hornetq.integration.logging.HornetQLoggerFormatter +# cycle through 10 files of 20MiB max which append logs +java.util.logging.FileHandler.count=10 +java.util.logging.FileHandler.limit=20971520 +java.util.logging.FileHandler.append=true +java.util.logging.FileHandler.pattern=logs/hornetq.%g.log +# Default global logging level. +# This specifies which kinds of events are logged across +# all loggers. For any given facility this global level +# can be overriden by a facility specific level +# Note that the ConsoleHandler also has a separate level +# setting to limit messages printed to the console. +.level= INFO + +############################################################ +# Handler specific properties. +# Describes specific configuration info for Handlers. +############################################################ diff --git a/distribution/hornetq/src/main/resources/examples/common/config/ant.properties b/distribution/hornetq/src/main/resources/examples/common/config/ant.properties new file mode 100644 index 0000000000..88ef1a7030 --- /dev/null +++ b/distribution/hornetq/src/main/resources/examples/common/config/ant.properties @@ -0,0 +1,4 @@ +hornetq.example.logserveroutput=true +hornetq.jars.dir=${imported.basedir}/../../lib +jars.dir=${imported.basedir}/../../lib +aio.library.path=${imported.basedir}/../../bin \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/licenses/LGPL.txt b/distribution/hornetq/src/main/resources/licenses/LGPL.txt new file mode 100644 index 0000000000..9ef3d701d1 --- /dev/null +++ b/distribution/hornetq/src/main/resources/licenses/LGPL.txt @@ -0,0 +1,503 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + diff --git a/distribution/hornetq/src/main/resources/licenses/LICENSE.txt b/distribution/hornetq/src/main/resources/licenses/LICENSE.txt new file mode 100644 index 0000000000..7a4a3ea242 --- /dev/null +++ b/distribution/hornetq/src/main/resources/licenses/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/licenses/LICENSE_twitter4j.txt b/distribution/hornetq/src/main/resources/licenses/LICENSE_twitter4j.txt new file mode 100644 index 0000000000..3a9829d611 --- /dev/null +++ b/distribution/hornetq/src/main/resources/licenses/LICENSE_twitter4j.txt @@ -0,0 +1,26 @@ +Twitter4J includes software from JSON.org to parse JSON response from the Twitter API. You can see the license term at http://www.JSON.org/license.html + +Copyright (c) 2007-2010, Yusuke Yamamoto +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Yusuke Yamamoto nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Yusuke Yamamoto ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Yusuke Yamamoto BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/distribution/hornetq/src/main/resources/licenses/base64.txt b/distribution/hornetq/src/main/resources/licenses/base64.txt new file mode 100644 index 0000000000..308461ba8a --- /dev/null +++ b/distribution/hornetq/src/main/resources/licenses/base64.txt @@ -0,0 +1,10 @@ +For org.hornetq.utils.Base64 + +I am placing this code in the Public Domain. Do with it as you will. +This software comes with no guarantees or warranties but with +plenty of well-wishing instead! +Please visit http://iharder.net/base64 +periodically to check for updates or to contribute improvements. + +@author Robert Harder +@author rob@iharder.net \ No newline at end of file diff --git a/distribution/hornetq/src/main/resources/licenses/json.txt b/distribution/hornetq/src/main/resources/licenses/json.txt new file mode 100644 index 0000000000..31b40d4b25 --- /dev/null +++ b/distribution/hornetq/src/main/resources/licenses/json.txt @@ -0,0 +1,23 @@ +For classes org.hornetq.utils.json.* + +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/distribution/jboss-mc/pom.xml b/distribution/jboss-mc/pom.xml new file mode 100644 index 0000000000..1a3fc0ae97 --- /dev/null +++ b/distribution/jboss-mc/pom.xml @@ -0,0 +1,123 @@ + + 4.0.0 + + + + org.hornetq + hornetq-distribution + 2.5.0-SNAPSHOT + + + jboss-mc + jar + JBoss Microcontainer jar + + + + + org.jboss.microcontainer + jboss-kernel + + + org.jboss.microcontainer + jboss-dependency + + + org.jboss + jboss-reflect + + + org.jboss + jboss-common-core + + + org.jboss + jboss-mdr + + + org.jboss + jbossxb + + + sun-jaxb + jaxb-api + + + org.jboss.logging + jboss-logging + + + org.jboss.logmanager + jboss-logmanager + + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + org.jboss.netty:netty + org.jboss.logging:jboss-logging-spi + + + + + + org.jboss.microcontainer:jboss-kernel + + + org.jboss.microcontainer:jboss-dependency + + + org.jboss:jboss-reflect + + + org.jboss:jboss-common-core + + + org.jboss:jboss-mdr + + + org.jboss:jbossxb + + + sun-jaxb:jaxb-api + + + org.jboss.logging:jboss-logging + + + org.jboss.logmanager:jboss-logmanager + + + + + + + + + + + diff --git a/distribution/jnp-client/pom.xml b/distribution/jnp-client/pom.xml new file mode 100644 index 0000000000..896ec997ec --- /dev/null +++ b/distribution/jnp-client/pom.xml @@ -0,0 +1,75 @@ + + 4.0.0 + + + + org.hornetq + hornetq-distribution + 2.5.0-SNAPSHOT + + + jnp-client + jar + JBoss jnp client jar + + + + org.jboss.naming + jnpserver + + + org.jboss.logging + jboss-logging + + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + org.jboss.naming:jnpserver + org.jboss.logging:jboss-logging + + + + + org.jboss.naming:jnpserver + + org/jnp/interfaces/**/*.class + org/jboss/naming/**/*.class + org/jnp/server/NamingServer_Stub.class + + + + org.jboss.logging:jboss-logging + + org/jboss/logging/**/*.class + + + + + + + + + + + + diff --git a/distribution/pom.xml b/distribution/pom.xml new file mode 100644 index 0000000000..498d7611be --- /dev/null +++ b/distribution/pom.xml @@ -0,0 +1,53 @@ + + 4.0.0 + + + org.hornetq + hornetq-pom + 2.5.0-SNAPSHOT + + + hornetq-distribution + pom + HornetQ Distribution + + + true + true + + + + + org.jboss.spec.javax.jms + jboss-jms-api_2.0_spec + + + org.jboss.naming + jnpserver + + + io.netty + netty-all + + + + + jnp-client + jboss-mc + hornetq + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + + diff --git a/docs/README.html b/docs/README.html new file mode 100644 index 0000000000..eca86ff683 --- /dev/null +++ b/docs/README.html @@ -0,0 +1,25 @@ + + + + + HornetQ 2.4.1.Final Release Notes + + + +

Release Notes - HornetQ - Version 2.4.1 Final

+ +
+ +

22th January 2014

+ +These are the release notes for HornetQ 2.4.1.Final

+ +For full description of the contents please see the +HornetQ project JIRA.

+ +2.4.1.Final is a patch release built on 2.4.0.Final. + +
+ +For more info on what this release has to offer please refer to the quick start guide or the user manual. Enjoy!! diff --git a/docs/design-guide/en/Author_Group.xml b/docs/design-guide/en/Author_Group.xml new file mode 100644 index 0000000000..2d9b1bddd8 --- /dev/null +++ b/docs/design-guide/en/Author_Group.xml @@ -0,0 +1,30 @@ + + + + +%BOOK_ENTITIES; +]> + + + Andy + Taylor + + Red Hat, Inc. + Core Developer + JBoss + + ataylor@redhat.com + + diff --git a/docs/design-guide/en/Book_Info.xml b/docs/design-guide/en/Book_Info.xml new file mode 100644 index 0000000000..43d56b6ffc --- /dev/null +++ b/docs/design-guide/en/Book_Info.xml @@ -0,0 +1,44 @@ + + + + +%BOOK_ENTITIES; +]> + + HornetQ Design Guide + Putting the buzz in messaging + HornetQ + 2.1.0 + 1 + + This Design guide is to help current and future developers how HornetQ's architectures are designed to + help the future development and maintenance of the project + + + + + + + + HornetQ Logo + + + + + &YEAR; + &HOLDER; + + + diff --git a/docs/design-guide/en/HornetQ_Design_Guide.ent b/docs/design-guide/en/HornetQ_Design_Guide.ent new file mode 100644 index 0000000000..e77312fd0b --- /dev/null +++ b/docs/design-guide/en/HornetQ_Design_Guide.ent @@ -0,0 +1,5 @@ + + + + + diff --git a/docs/design-guide/en/HornetQ_Design_Guide.xml b/docs/design-guide/en/HornetQ_Design_Guide.xml new file mode 100644 index 0000000000..255c25d4d2 --- /dev/null +++ b/docs/design-guide/en/HornetQ_Design_Guide.xml @@ -0,0 +1,26 @@ + + + + + +%BOOK_ENTITIES; + +]> + + + + + + diff --git a/docs/design-guide/en/about.xml b/docs/design-guide/en/about.xml new file mode 100644 index 0000000000..4542d0d684 --- /dev/null +++ b/docs/design-guide/en/about.xml @@ -0,0 +1,24 @@ + + + + + +%BOOK_ENTITIES; +]> + + + About HornetQ + What is HornetQ? + \ No newline at end of file diff --git a/docs/design-guide/en/clustering.xml b/docs/design-guide/en/clustering.xml new file mode 100644 index 0000000000..18428f69b6 --- /dev/null +++ b/docs/design-guide/en/clustering.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Getting Started + This chapter discusses the architecture behind clustering +
+ Discovery + Discovery is done in 2 steps, initial discovery where the server locates another node in the cluster and + topology discovery where the node finds out about all other nodes in the cluster +
+ Initial Discovery + blah blah blah, UDP, static connectors etc etc +
+
+ Topology Discovery + blah blah blah, topology etc + + + +
+
+
diff --git a/docs/design-guide/en/diagrams/design-docs.odg b/docs/design-guide/en/diagrams/design-docs.odg new file mode 100644 index 0000000000..7e9e6a0a84 Binary files /dev/null and b/docs/design-guide/en/diagrams/design-docs.odg differ diff --git a/docs/design-guide/en/images/hornetQ_logo_600px.png b/docs/design-guide/en/images/hornetQ_logo_600px.png new file mode 100644 index 0000000000..b71f4ba130 Binary files /dev/null and b/docs/design-guide/en/images/hornetQ_logo_600px.png differ diff --git a/docs/design-guide/en/images/topology-update.jpg b/docs/design-guide/en/images/topology-update.jpg new file mode 100644 index 0000000000..3cef419720 Binary files /dev/null and b/docs/design-guide/en/images/topology-update.jpg differ diff --git a/docs/design-guide/en/notice.xml b/docs/design-guide/en/notice.xml new file mode 100644 index 0000000000..5d75298fe6 --- /dev/null +++ b/docs/design-guide/en/notice.xml @@ -0,0 +1,32 @@ + + + +%BOOK_ENTITIES; +]> + + + Legal Notice + + Copyright © 2010 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. + \ No newline at end of file diff --git a/docs/design-guide/pom.xml b/docs/design-guide/pom.xml new file mode 100644 index 0000000000..4c4b6ff83f --- /dev/null +++ b/docs/design-guide/pom.xml @@ -0,0 +1,306 @@ + + + + + + 4.0.0 + org.jboss.project + ${docname}-${translation} + 1.0 + jdocbook + ${bookname}-(${translation}) + + + en + HornetQ_Design_Guide + HornetQ Design Guide + + + + + jboss-public-repository-group + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + default + + true + never + + + true + never + + + + + + jboss-public-repository-group + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + default + + true + + + true + + + + + + + + + + all + + true + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${docname}.pdf + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + html_single + classpath:/xslt/org/jboss/xhtml-single.xsl + index.html + + + + + + + + + + + html + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + + + + + + + + + html-single + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + + + + + pdf + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.1.0 + true + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${docname}.pdf + + + + + + + + + + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + org.jboss.pressgang + pressgang-xslt + 1.2.0 + + + org.jboss + jbossorg-jdocbook-style + 1.1.1 + jdocbook-style + + + + ${project.basedir} + ${docname}.xml + en + + ${project.basedir}/en + + images/*.png + images/*.jpg + + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${pdf.name} + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + html_single + classpath:/xslt/org/jboss/xhtml-single.xsl + index.html + + + + true + saxon + 1.72.0 + - + + + javax.xml.parsers.DocumentBuilderFactory + org.apache.xerces.jaxp.DocumentBuilderFactoryImpl + + + javax.xml.parsers.SAXParserFactory + org.apache.xerces.jaxp.SAXParserFactoryImpl + + + + + + + + + + + diff --git a/docs/diagrams/standard_image.odg b/docs/diagrams/standard_image.odg new file mode 100644 index 0000000000..ecab22a145 Binary files /dev/null and b/docs/diagrams/standard_image.odg differ diff --git a/docs/diagrams/widgets.odg b/docs/diagrams/widgets.odg new file mode 100644 index 0000000000..76f7722e52 Binary files /dev/null and b/docs/diagrams/widgets.odg differ diff --git a/docs/eap-manual/en/Author_Group.xml b/docs/eap-manual/en/Author_Group.xml new file mode 100644 index 0000000000..67034eae66 --- /dev/null +++ b/docs/eap-manual/en/Author_Group.xml @@ -0,0 +1,30 @@ + + + + +%BOOK_ENTITIES; +]> + + + Andy + Taylor + + Red Hat, Inc. + Core Developer + JBoss + + ataylor@redhat.com + + diff --git a/docs/eap-manual/en/Book_Info.xml b/docs/eap-manual/en/Book_Info.xml new file mode 100644 index 0000000000..869f4baa1e --- /dev/null +++ b/docs/eap-manual/en/Book_Info.xml @@ -0,0 +1,44 @@ + + + + + +%BOOK_ENTITIES; +]> + + HornetQ Eap Manual + Putting the buzz in messaging + HornetQ + 2.1.0 + 1 + + This is a guide to using HornetQ within EAP + + + + + + + + HornetQ Logo + + + + + &YEAR; + &HOLDER; + + + diff --git a/docs/eap-manual/en/HornetQ_EAP_Manual.ent b/docs/eap-manual/en/HornetQ_EAP_Manual.ent new file mode 100644 index 0000000000..1c0d787cb5 --- /dev/null +++ b/docs/eap-manual/en/HornetQ_EAP_Manual.ent @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docs/eap-manual/en/HornetQ_EAP_Manual.xml b/docs/eap-manual/en/HornetQ_EAP_Manual.xml new file mode 100644 index 0000000000..296057b7fa --- /dev/null +++ b/docs/eap-manual/en/HornetQ_EAP_Manual.xml @@ -0,0 +1,24 @@ + + + + + +%BOOK_ENTITIES; + +]> + + + + diff --git a/docs/eap-manual/en/clusters.xml b/docs/eap-manual/en/clusters.xml new file mode 100644 index 0000000000..db38cdd455 --- /dev/null +++ b/docs/eap-manual/en/clusters.xml @@ -0,0 +1,569 @@ + + + + + + HornetQ and EAP Cluster Configuration +
+ Configuring Failover + + This chapter explains how to configure HornetQ within EAP with live backup-groups. Currently in this version + HornetQ only supports shared store for backup nodes so we assume that in the rest of this chapter. + + There are 2 main ways to configure HornetQ servers to have a backup server: + + + Colocated. This is when an EAP instance has both a live and backup(s) running. + + + Dedicated. This is when an EAP instance has either a live or backup running but never both. + + +
+ Colocated Live and Backup in Symmetrical cluster + + The colocated symmetrical topology will be the most widely used topology, this is where an EAP instance has + a live node running plus 1 or more backup node. Each backup node will belong to a live node on another EAP + instance. In a simple cluster of 2 + EAP instances this would mean that each EAP instance would have a live server and 1 backup server as in + diagram1. + + + + + + Here the continuous lines show before failover and the dotted lines show the state of the cluster after + failover has occurred. To start with the 2 live servers are connected forming a cluster with each live server + connected to its local applications (via JCA). Also remote clients are connected to the live servers. After + failover the backup connects to the still available live server (which happens to be in the same vm) and takes + over as the live server in the cluster. Any remote clients also failover. + + + One thing to mention is that in that depending on what consumers/producers and MDB's etc are available messages + will be distributed between the nodes to make sure that all clients are satisfied from a JMS perspective. That is + if a producer is sending messages to a queue on a backup server that has no consumers, the messages will be + distributed to a live node elsewhere. + + + The following diagram is slightly more complex but shows the same configuration with 3 servers. Note that the + cluster connections ave been removed to make the configuration clearer but in reality all live servers will + form a cluster. + + + + + + With more than 2 servers it is up to the user as to how many backups per live server are configured, you can + have + as many backups as required but usually 1 would suffice. In 3 node topology you may have each EAP instance + configured + with 2 backups in a 4 node 3 backups and so on. The following diagram demonstrates this. + + + + +
+ Configuration +
+ Live Server Configuration + + First let's start with the configuration of the live server, we will use the EAP 'all' configuration as + our starting point. Since this version only supports shared store for failover we need to configure + this in the + hornetq-configuration.xml + file like so: + + + <shared-store>true</shared-store> + + + Obviously this means that the location of the journal files etc will have to be configured to be some + where + where + this lives backup can access. You may change the lives configuration in + hornetq-configuration.xml + to + something like: + + + <large-messages-directory>/media/shared/data/large-messages</large-messages-directory> + <bindings-directory>/media/shared/data/bindings</bindings-directory> + <journal-directory>/media/shared/data/journal</journal-directory> + <paging-directory>/media/shared/data/paging</paging-directory> + + + How these paths are configured will of course depend on your network settings or file system. + + + Now we need to configure how remote JMS clients will behave if the server is shutdown in a normal + fashion. + By + default + Clients will not failover if the live server is shutdown. Depending on there connection factory + settings + they will either fail or try to reconnect to the live server. + + If you want clients to failover on a normal server shutdown the you must configure the + failover-on-shutdown + flag to true in the + hornetq-configuration.xml + file like so: + + + <failover-on-shutdown>false</failover-on-shutdown> + + Don't worry if you have this set to false (which is the default) but still want failover to occur, + simply + kill + the + server process directly or call + forceFailover + via jmx or the admin console on the core server object. + + We also need to configure the connection factories used by the client to be HA. This is done by + adding + certain attributes to the connection factories inhornetq-jms.xml. Let's look at an + example: + + + <connection-factory name="NettyConnectionFactory"> + <xa>true</xa> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="/ConnectionFactory"/> + <entry name="/XAConnectionFactory"/> + </entries> + + <ha>true</ha> + <!-- Pause 1 second between connect attempts --> + <retry-interval>1000</retry-interval> + + <!-- Multiply subsequent reconnect pauses by this multiplier. This can be used to + implement an exponential back-off. For our purposes we just set to 1.0 so each reconnect + pause is the same length --> + <retry-interval-multiplier>1.0</retry-interval-multiplier> + + <!-- Try reconnecting an unlimited number of times (-1 means "unlimited") --> + <reconnect-attempts>-1</reconnect-attempts> + </connection-factory> + + + We have added the following attributes to the connection factory used by the client: + + + + ha + - This tells the client it support HA and must always be true for failover + to occur + + + + + retry-interval + - this is how long the client will wait after each unsuccessful + reconnect to the server + + + + + retry-interval-multiplier + - is used to configure an exponential back off for + reconnect attempts + + + + + reconnect-attempts + - how many reconnect attempts should a client make before failing, + -1 means unlimited. + + + +
+
+ Backup Server Configuration + + Now let's look at how to create and configure a backup server on the same eap instance. This is running + on the same eap instance as the live server from the previous chapter but is configured as the backup + for a live server running on a different eap instance. + + + The first thing to mention is that the backup only needs a hornetq-jboss-beans.xml + and a hornetq-configuration.xml configuration file. This is because any JMS components + are created from the Journal when the backup server becomes live. + + + Firstly we need to define a new HornetQ Server that EAP will deploy. We do this by creating a new + hornetq-jboss-beans.xml + configuration. We will place this under a new directory + hornetq-backup1 + which will need creating + in the + deploy + directory but in reality it doesn't matter where this is put. This will look like: + + + <?xml version="1.0" encoding="UTF-8"?> + + <deployment xmlns="urn:jboss:bean-deployer:2.0"> + + <!-- The core configuration --> + <bean name="BackupConfiguration" class="org.hornetq.core.config.impl.FileConfiguration"> + <property + name="configurationUrl">${jboss.server.home.url}/deploy/hornetq-backup1/hornetq-configuration.xml</property> + </bean> + + + <!-- The core server --> + <bean name="BackupHornetQServer" class="org.hornetq.core.server.impl.HornetQServerImpl"> + <constructor> + <parameter> + <inject bean="BackupConfiguration"/> + </parameter> + <parameter> + <inject bean="MBeanServer"/> + </parameter> + <parameter> + <inject bean="HornetQSecurityManager"/> + </parameter> + </constructor> + <start ignored="true"/> + <stop ignored="true"/> + </bean> + + <!-- The JMS server --> + <bean name="BackupJMSServerManager" class="org.hornetq.jms.server.impl.JMSServerManagerImpl"> + <constructor> + <parameter> + <inject bean="BackupHornetQServer"/> + </parameter> + </constructor> + </bean> + + </deployment> + + + The first thing to notice is the BackupConfiguration bean. This is configured to pick up the + configuration + for + the + server which we will place in the same directory. + + + After that we just configure a new HornetQ Server and JMS server. + + + + Notice that the names of the beans have been changed from that of the live servers configuration. + This + is + so + there is no clash. Obviously if you add more backup servers you will need to rename those as well, + backup1, + backup2 etc. + + + + Now let's add the server configuration in + hornetq-configuration.xml + and add it to the same directory + deploy/hornetq-backup1 + and configure it like so: + + + <configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd"> + + <jmx-domain>org.hornetq.backup1</jmx-domain> + + <clustered>true</clustered> + + <backup>true</backup> + + <shared-store>true</shared-store> + + <allow-failback>true</allow-failback> + + <bindings-directory>/media/shared/data/hornetq-backup/bindings</bindings-directory> + + <journal-directory>/media/shared/data/hornetq-backup/journal</journal-directory> + + <journal-min-files>10</journal-min-files> + + <large-messages-directory>/media/shared/data/hornetq-backup/largemessages</large-messages-directory> + + <paging-directory>/media/shared/data/hornetq-backup/paging</paging-directory> + + <connectors> + <connector name="netty-connector"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class> + <param key="host" value="${jboss.bind.address:localhost}"/> + <param key="port" value="${hornetq.remoting.backup.netty.port:5446}"/> + </connector> + + <connector name="in-vm"> + <factory-class>org.hornetq.core.remoting.impl.invm.InVMConnectorFactory</factory-class> + <param key="server-id" value="${hornetq.server-id:0}"/> + </connector> + + </connectors> + + <acceptors> + <acceptor name="netty"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + <param key="host" value="${jboss.bind.address:localhost}"/> + <param key="port" value="${hornetq.remoting.backup.netty.port:5446}"/> + </acceptor> + </acceptors> + + <broadcast-groups> + <broadcast-group name="bg-group1"> + <group-address>231.7.7.7</group-address> + <group-port>9876</group-port> + <broadcast-period>1000</broadcast-period> + <connector-ref>netty-connector</connector-ref> + </broadcast-group> + </broadcast-groups> + + <discovery-groups> + <discovery-group name="dg-group1"> + <group-address>231.7.7.7</group-address> + <group-port>9876</group-port> + <refresh-timeout>60000</refresh-timeout> + </discovery-group> + </discovery-groups> + + <cluster-connections> + <cluster-connection name="my-cluster"> + <address>jms</address> + <connector-ref>netty-connector</connector-ref> + <discovery-group-ref discovery-group-name="dg-group1"/> + <!--max hops defines how messages are redistributed, the default is 1 meaning only distribute to directly + connected nodes, to disable set to 0--> + <!--<max-hops>0</max-hops>--> + </cluster-connection> + </cluster-connections> + + <security-settings> + <security-setting match="#"> + <permission type="createNonDurableQueue" roles="guest"/> + <permission type="deleteNonDurableQueue" roles="guest"/> + <permission type="consume" roles="guest"/> + <permission type="send" roles="guest"/> + </security-setting> + </security-settings> + + <address-settings> + <!--default for catch all--> + <address-setting match="#"> + <dead-letter-address>jms.queue.DLQ</dead-letter-address> + <expiry-address>jms.queue.ExpiryQueue</expiry-address> + <redelivery-delay>0</redelivery-delay> + <max-size-bytes>10485760</max-size-bytes> + <message-counter-history-day-limit>10</message-counter-history-day-limit> + <address-full-policy>BLOCK</address-full-policy> + </address-setting> + </address-settings> + + </configuration> + + + + The second thing you can see is we have added a + jmx-domain + attribute, this is used when + adding objects, such as the HornetQ server and JMS server to jmx, we change this from the default + org.hornetq + to avoid naming clashes with the live server + + + The first important part of the configuration is to make sure that this server starts as a backup + server not + a live server, via the + backup + attribute. + + + After that we have the same cluster configuration as live, that is + clustered + is true and + shared-store + is true. However you can see we have added a new configuration element + allow-failback. When this is set to true then this backup server will automatically + stop + and fall back into backup node if failover occurs and the live server has become available. If false + then + the user will have to stop the server manually. + + + Next we can see the configuration for the journal location, as in the live configuration this must + point to + the same directory as this backup's live server. + + + Now we see the connectors configuration, we have 3 defined which are needed for the following + + + + + netty-connector. + This is the connector used to connect to this backup server once live. + + + + After that you will see the acceptors defined, This is the acceptor where clients will reconnect. + + + The Broadcast groups, Discovery group and cluster configurations are as per normal, details of these + can be found in the HornetQ user manual. + + + notice the commented out max-hops in the cluster connection, set this to 0 if + you want to disable server side load balancing. + + + When the backup becomes it will be not be servicing any JEE components on this eap instance. Instead any + existing messages will be redistributed around the cluster and new messages forwarded to and from the backup + to service any remote clients it has (if it has any). + +
+
+ Configuring multiple backups + + In this instance we have assumed that there are only 2 nodes where each node has a backup for the other + node. However you may want to configure a server too have multiple backup nodes. For example you may want + 3 nodes where each node has 2 backups, one for each of the other 2 live servers. For this you would simply + copy the backup configuration and make sure you do the following: + + + + + Make sure that you give all the beans in the hornetq-jboss-beans.xml configuration + file a unique name, i.e. + + + +
+
+ Running the shipped example + + EAP ships with an example configuration for this topology. Look under extras/hornetq/resources/examples/symmetric-cluster-with-backups-colocated + and follow the read me + +
+
+
+
+ Dedicated Live and Backup in Symmetrical cluster + + In reality the configuration for this is exactly the same as the backup server in the previous section, the only + difference is that a backup will reside on an eap instance of its own rather than colocated with another live server. + Of course this means that the eap instance is passive and not used until the backup comes live and is only + really useful for pure JMS applications. + + The following diagram shows a possible configuration for this: + + + + + Here you can see how this works with remote JMS clients. Once failover occurs the HornetQ backup Server takes + running within another eap instance takes over as live. + + + This is fine with applications that are pure JMS and have no JMS components such as MDB's. If you are using + JMS components then there are 2 ways that this can be done. The first is shown in the following diagram: + + + + + + Because there is no live hornetq server running by default in the eap instance running the backup server it + makes no sense to host any applications in it. However you can host applications on the server running the live + hornetq server. If failure occurs to an live hornetq server then remote jms clients will failover as previously + explained however what happens to any messages meant for or sent from JEE components. Well when the backup comes + live, messages will be distributed to and from the backup server over HornetQ cluster connections and handled + appropriately. + + + The second way to do this is to have both live and backup server remote form the eap instance as shown in the + following diagram. + + + + + + Here you can see that all the Application (via JCA) will be serviced by a HornetQ server in its own eap instance. + +
+ Configuration of dedicated Live and backup + + The live server configuration is exactly the same as in the previous example. The only difference of course + is that there is no backup in the eap instance. + + + For the backup server the hornetq-configuration.xml is unchanged, however since there is + no live server we need to make sure that the hornetq-jboss-beans.xml instantiates all + the beans needed. For this simply use the same configuration as in the live server changing only the + location of the hornetq-configuration.xml parameter for the Configuration + bean. + + + As before there will be no hornetq-jms.xml or jms-ds.xml configuration. + + + If you want both hornetq servers to be in there own dedicated server where they are remote to applications, + as in the last diagram. Then simply edit the jms-ds.xml and change the following lines to + + + <config-property name="ConnectorClassName" type="java.lang.String">org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property> + <config-property name="ConnectionParameters" type="java.lang.String">host=127.0.0.1;port=5446</config-property> + + + This will change the outbound JCA connector, to configure the inbound connector for MDB's edit the + ra.xml config file and change the following parameters. + + + <config-property> + <description>The transport type</description> + <config-property-name>ConnectorClassName</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property-value> + </config-property> + <config-property> + <description>The transport configuration. These values must be in the form of key=val;key=val;</description> + <config-property-name>ConnectionParameters</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>host=127.0.0.1;port=5446</config-property-value> + </config-property> + + + In both cases the host and port should match your live server. If you are using Discovery then set the + appropriate parameters for DiscoveryAddress and DiscoveryPort to match + your configured broadcast groups. + +
+
+ Running the shipped example + + EAP ships with an example configuration for this topology. Look under + extras/hornetq/resources/examples/cluster-with-dedicated-backup + and follow the read me + +
+
+
+
diff --git a/docs/eap-manual/en/diagrams/ha-topologies1.odg b/docs/eap-manual/en/diagrams/ha-topologies1.odg new file mode 100644 index 0000000000..f42e64f527 Binary files /dev/null and b/docs/eap-manual/en/diagrams/ha-topologies1.odg differ diff --git a/docs/eap-manual/en/images/simple-colocated.jpg b/docs/eap-manual/en/images/simple-colocated.jpg new file mode 100644 index 0000000000..ed998e52c7 Binary files /dev/null and b/docs/eap-manual/en/images/simple-colocated.jpg differ diff --git a/docs/eap-manual/en/images/simple-colocated2.jpg b/docs/eap-manual/en/images/simple-colocated2.jpg new file mode 100644 index 0000000000..76e6ee3e9d Binary files /dev/null and b/docs/eap-manual/en/images/simple-colocated2.jpg differ diff --git a/docs/eap-manual/en/images/simple-colocated3.jpg b/docs/eap-manual/en/images/simple-colocated3.jpg new file mode 100644 index 0000000000..d07a9ebbb7 Binary files /dev/null and b/docs/eap-manual/en/images/simple-colocated3.jpg differ diff --git a/docs/eap-manual/en/images/simple-dedicated-jca-remote.jpg b/docs/eap-manual/en/images/simple-dedicated-jca-remote.jpg new file mode 100644 index 0000000000..6a98b3a093 Binary files /dev/null and b/docs/eap-manual/en/images/simple-dedicated-jca-remote.jpg differ diff --git a/docs/eap-manual/en/images/simple-dedicated-jca.jpg b/docs/eap-manual/en/images/simple-dedicated-jca.jpg new file mode 100644 index 0000000000..4d6387f689 Binary files /dev/null and b/docs/eap-manual/en/images/simple-dedicated-jca.jpg differ diff --git a/docs/eap-manual/en/images/simple-dedicated.jpg b/docs/eap-manual/en/images/simple-dedicated.jpg new file mode 100644 index 0000000000..ea97b2ca04 Binary files /dev/null and b/docs/eap-manual/en/images/simple-dedicated.jpg differ diff --git a/docs/eap-manual/en/master.xml b/docs/eap-manual/en/master.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/eap-manual/pom.xml b/docs/eap-manual/pom.xml new file mode 100644 index 0000000000..4c85f52ef1 --- /dev/null +++ b/docs/eap-manual/pom.xml @@ -0,0 +1,305 @@ + + + + + + 4.0.0 + org.jboss.project + ${docname}-${translation} + 1.0 + jdocbook + ${bookname}-(${translation}) + + + en + HornetQ_EAP_Manual + HornetQ EAP Manual + + + + + jboss-public-repository-group + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + default + + true + never + + + true + never + + + + + + jboss-public-repository-group + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + default + + true + + + true + + + + + + + + + + all + + true + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${docname}.pdf + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + html_single + classpath:/xslt/org/jboss/xhtml-single.xsl + index.html + + + + + + + + + + + html + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + + + + + + + + + html-single + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + + + + + pdf + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.1.0 + true + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${docname}.pdf + + + + + + + + + + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + org.jboss.pressgang + pressgang-xslt + 1.2.0 + + + org.jboss + jbossorg-jdocbook-style + 1.1.1 + jdocbook-style + + + + ${project.basedir} + ${docname}.xml + en + + ${project.basedir}/en + + images/*.png + + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${pdf.name} + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + html_single + classpath:/xslt/org/jboss/xhtml-single.xsl + index.html + + + + true + saxon + 1.72.0 + - + + + javax.xml.parsers.DocumentBuilderFactory + org.apache.xerces.jaxp.DocumentBuilderFactoryImpl + + + javax.xml.parsers.SAXParserFactory + org.apache.xerces.jaxp.SAXParserFactoryImpl + + + + + + + + + + + diff --git a/docs/pom.xml b/docs/pom.xml new file mode 100644 index 0000000000..de0fd318e1 --- /dev/null +++ b/docs/pom.xml @@ -0,0 +1,51 @@ + + + + 4.0.0 + + + org.hornetq + hornetq-pom + 2.5.0-SNAPSHOT + + + org.hornetq.docs + hornetq-docs + pom + HornetQ Documentation + + + true + true + + + + user-manual + quickstart-guide + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + + diff --git a/docs/quickstart-guide/en/Author_Group.xml b/docs/quickstart-guide/en/Author_Group.xml new file mode 100644 index 0000000000..b0dac5f0b4 --- /dev/null +++ b/docs/quickstart-guide/en/Author_Group.xml @@ -0,0 +1,45 @@ + + +%BOOK_ENTITIES; +]> + + + Clebert + Suconic + + Red Hat, Inc. + Project Lead + JBoss + + csuconic@redhat.com + + + Andy + Taylor + + Red Hat, Inc. + Core Developer + JBoss + + ataylor@redhat.com + + + Tim + Fox + + + Jeff + Mesnil + + + Howard + Gao + + Red Hat, Inc. + Core Developer + JBoss + + ghoward@redhat.com + + diff --git a/docs/quickstart-guide/en/Book_Info.xml b/docs/quickstart-guide/en/Book_Info.xml new file mode 100644 index 0000000000..5f2ce4b6c7 --- /dev/null +++ b/docs/quickstart-guide/en/Book_Info.xml @@ -0,0 +1,31 @@ + + +%BOOK_ENTITIES; +]> + + HornetQ QuickStart Guide + Putting the buzz in messaging + HornetQ + 2.1.0 + 1 + + This Quickstart guide will help you get HornetQ up and running in a few minutes and will explain the basics needed + to get started. + + + + + + + + HornetQ Logo + + + + + &YEAR; + &HOLDER; + + + diff --git a/docs/quickstart-guide/en/HornetQ_QuickStart_Guide.ent b/docs/quickstart-guide/en/HornetQ_QuickStart_Guide.ent new file mode 100644 index 0000000000..f3d2b4ac5d --- /dev/null +++ b/docs/quickstart-guide/en/HornetQ_QuickStart_Guide.ent @@ -0,0 +1,5 @@ + + + + + diff --git a/docs/quickstart-guide/en/HornetQ_QuickStart_Guide.xml b/docs/quickstart-guide/en/HornetQ_QuickStart_Guide.xml new file mode 100644 index 0000000000..62114fa821 --- /dev/null +++ b/docs/quickstart-guide/en/HornetQ_QuickStart_Guide.xml @@ -0,0 +1,17 @@ + + + +%BOOK_ENTITIES; + +]> + + + + + + + + + + diff --git a/docs/quickstart-guide/en/about.xml b/docs/quickstart-guide/en/about.xml new file mode 100644 index 0000000000..b55905c4c2 --- /dev/null +++ b/docs/quickstart-guide/en/about.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + + About HornetQ + What is HornetQ? + + + HornetQ is an open source project to build a multi-protocol, embeddable, very high + performance, clustered, asynchronous messaging system. + + + For answers to more questions about what HornetQ is and what it isn't please visit + the FAQs wiki + page. + + + Why use HornetQ? Here are just a few of the reasons: + + + 100% open source software. HornetQ is licenced using the Apache Software License v2.0 + to minimise barriers to adoption. + + + HornetQ is designed with usability in mind. + + + Written in Java. Runs on any platform with a Java 6+ runtime, that's everything + from Windows desktops to IBM mainframes. + + + Amazing performance. Our class beating high performance journal provides persistent + messaging performance at rates normally seen for non persistent messaging, our non + persistent messaging performance rocks the boat too. + + + Full feature set. All the features you'd expect in any serious messaging system, + and others you won't find anywhere else. + + + Elegant, clean-cut design with minimal third party dependencies. Run HornetQ + stand-alone, run it in integrated in your favourite JEE application server, or run + it embedded inside your own product. It's up to you. + + + Seamless high availability. We provide a HA solution with automatic client + failover so you can guarantee zero message loss or duplication in event of server + failure. + + + Hugely flexible clustering. Create clusters of servers that know how to load + balance messages. Link geographically distributed clusters over unreliable + connections to form a global network. Configure routing of messages in a highly + flexible way. + + + For a full list of features, please see the features wiki + page . + + + \ No newline at end of file diff --git a/docs/quickstart-guide/en/download.xml b/docs/quickstart-guide/en/download.xml new file mode 100644 index 0000000000..bc0beec900 --- /dev/null +++ b/docs/quickstart-guide/en/download.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Download + The official HornetQ project page is http://hornetq.org/. +
+ Software Download + The software can be download from the Download page:http://hornetq.org/downloads.html +
+
+ Project Information + + + + Please take a look at our project wiki + + + If you have any user questions please use our user + forum + + + If you have development related questions, please use our developer forum + + + Pop in and chat to us in our IRC channel + + + Our project blog + + + Follow us on twitter + + + HornetQ Git repository is https://github.com/hornetq/hornetq + + + All release tags are available from https://github.com/hornetq/hornetq/tags + + + +
+
diff --git a/docs/quickstart-guide/en/examples.xml b/docs/quickstart-guide/en/examples.xml new file mode 100644 index 0000000000..8dcccea707 --- /dev/null +++ b/docs/quickstart-guide/en/examples.xml @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Running the Examples + In the directory examples there are 2 sets of examples, these are + + + JMS Examples - these demonstrate functionality while sending and consumng JMS + messages. + + + Java EE Examples - these demonstrate application server integration, e.g. MDBs, EJBs, + Servlets, etc. + + +
+ The JMS examples + The JMS Examples all follow the same format. Each examples is contained in its own + directory which contains the following. + + + pom.xml + This is the Maven build file used to run the example + + + src directory + This contains the source code for the example + + + resources/hornetq/server0 configuration directory + This contains the configuration files needed to run the server for the example. + There may be multiple configuration directories server0, server1 etc for clustered examples etc. + + + Each example will start one or more stand-alone servers and stop them after the example + has completed. + As a quick start we'll run the queue example. For all other examples refer to the main + user manual. + Firstly open a Shell or a Command prompt and navigate to the examples/jms/queue directory. + Type the command mvn verify and you should see the following output: + + +[INFO] Scanning for projects... +[INFO] +[INFO] ------------------------------------------------------------------------ +[INFO] Building HornetQ JMS Queue Example 2.3.0.BETA-SNAPSHOT +[INFO] ------------------------------------------------------------------------ +[INFO] +[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hornetq-jms-queue-example --- +[INFO] Using 'UTF-8' encoding to copy filtered resources. +[INFO] Copying 3 resources +[INFO] +[INFO] --- maven-compiler-plugin:3.0:compile (default-compile) @ hornetq-jms-queue-example --- +[INFO] Nothing to compile - all classes are up to date +[INFO] +[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hornetq-jms-queue-example --- +[INFO] Using 'UTF-8' encoding to copy filtered resources. +[INFO] skip non existing resourceDirectory /home/andy/projects/hornetq-master/examples/jms/queue/src/test/resources +[INFO] +[INFO] --- maven-compiler-plugin:3.0:testCompile (default-testCompile) @ hornetq-jms-queue-example --- +[INFO] No sources to compile +[INFO] +[INFO] --- maven-surefire-plugin:2.13:test (default-test) @ hornetq-jms-queue-example --- +[INFO] +[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hornetq-jms-queue-example --- +[INFO] Building jar: /home/andy/projects/hornetq-master/examples/jms/queue/target/hornetq-jms-queue-example-2.3.0.BETA-SNAPSHOT.jar +[INFO] +[INFO] >>> maven-source-plugin:2.2.1:jar (attach-sources) @ hornetq-jms-queue-example >>> +[INFO] +[INFO] <<< maven-source-plugin:2.2.1:jar (attach-sources) @ hornetq-jms-queue-example <<< +[INFO] +[INFO] --- maven-source-plugin:2.2.1:jar (attach-sources) @ hornetq-jms-queue-example --- +[INFO] Building jar: /home/andy/projects/hornetq-master/examples/jms/queue/target/hornetq-jms-queue-example-2.3.0.BETA-SNAPSHOT-sources.jar +[INFO] +[INFO] >>> maven-source-plugin:2.2.1:jar (default) @ hornetq-jms-queue-example >>> +[INFO] +[INFO] <<< maven-source-plugin:2.2.1:jar (default) @ hornetq-jms-queue-example <<< +[INFO] +[INFO] --- maven-source-plugin:2.2.1:jar (default) @ hornetq-jms-queue-example --- +[WARNING] Artifact org.hornetq.examples.jms:hornetq-jms-queue-example:java-source:sources:2.3.0.BETA-SNAPSHOT already attached to project, ignoring duplicate +[INFO] +[INFO] --- hornetq-maven-plugin:1.1.1-SNAPSHOT:start (start) @ hornetq-jms-queue-example --- +[file:/home/andy/projects/hornetq-master/examples/jms/queue/target/classes/hornetq/server0/] +Apr 17, 2013 10:51:01 AM org.hornetq.core.deployers.impl.FileConfigurationParser parseMainConfig +WARN: HQ222018: AIO was not located on this platform, it will fall back to using pure Java NIO. If your platform is Linux, install LibAIO to enable the AIO journal +Apr 17, 2013 10:51:01 AM org.hornetq.core.server.impl.HornetQServerImpl start +INFO: HQ221000: live server is starting with configuration HornetQ Configuration (clustered=false,backup=false,sharedStore=true,journalDirectory=/home/andy/projects/hornetq-master/examples/jms/queue/target//server0/data/messaging/journal,bindingsDirectory=/home/andy/projects/hornetq-master/examples/jms/queue/target//server0/data/messaging/bindings,largeMessagesDirectory=/home/andy/projects/hornetq-master/examples/jms/queue/target//server0/data/messaging/largemessages,pagingDirectory=/home/andy/projects/hornetq-master/examples/jms/queue/target//server0/data/messaging/paging) +Apr 17, 2013 10:51:01 AM org.hornetq.core.server.impl.HornetQServerImpl$SharedStoreLiveActivation run +INFO: HQ221006: Waiting to obtain live lock +Apr 17, 2013 10:51:01 AM org.hornetq.core.persistence.impl.journal.JournalStorageManager <init> +INFO: HQ221013: Using NIO Journal +Apr 17, 2013 10:51:01 AM org.hornetq.core.server.impl.HornetQServerImpl initialisePart1 +WARN: HQ222007: Security risk! HornetQ is running with the default cluster admin user and default password. Please see the HornetQ user guide, cluster chapter, for instructions on how to change this. +Apr 17, 2013 10:51:01 AM org.hornetq.core.server.impl.FileLockNodeManager startLiveNode +INFO: HQ221034: Waiting to obtain live lock +Apr 17, 2013 10:51:01 AM org.hornetq.core.server.impl.FileLockNodeManager startLiveNode +INFO: HQ221035: Live Server Obtained live lock +Apr 17, 2013 10:51:02 AM org.hornetq.core.server.impl.HornetQServerImpl deployQueue +INFO: HQ221003: trying to deploy queue jms.queue.exampleQueue +Apr 17, 2013 10:51:02 AM org.hornetq.core.remoting.impl.netty.NettyAcceptor start +INFO: HQ221020: Started Netty Acceptor version 3.6.2.Final-c0d783c localhost:5445 for CORE protocol +Apr 17, 2013 10:51:02 AM org.hornetq.core.server.impl.HornetQServerImpl$SharedStoreLiveActivation run +INFO: HQ221007: Server is now live +Apr 17, 2013 10:51:02 AM org.hornetq.core.server.impl.HornetQServerImpl start +INFO: HQ221001: HornetQ Server version 2.3.0.SNAPSHOT (black'n'yellow, 123) [a57893ff-7783-11e2-9787-07ca142fc9f7] +[INFO] +[INFO] --- hornetq-maven-plugin:1.1.1-SNAPSHOT:runClient (runClient) @ hornetq-jms-queue-example --- +Apr 17, 2013 10:51:02 AM org.hornetq.common.example.HornetQExample getContext +INFO: using jnp://localhost:1099 for jndi +Sent message: This is a text message +Received message: This is a text message +example complete + +##################### +### SUCCESS! ### +##################### +[INFO] +[INFO] --- hornetq-maven-plugin:1.1.1-SNAPSHOT:stop (stop) @ hornetq-jms-queue-example --- +Apr 17, 2013 10:51:03 AM org.hornetq.core.server.management.impl.ManagementServiceImpl stop +WARN: HQ222113: On ManagementService stop, there are 1 unexpected registered MBeans: [core.acceptor.netty-acceptor] +Apr 17, 2013 10:51:03 AM org.hornetq.core.server.impl.HornetQServerImpl stop +INFO: HQ221002: HornetQ Server version 2.3.0.SNAPSHOT (black'n'yellow, 123) [a57893ff-7783-11e2-9787-07ca142fc9f7] stopped +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 4.428s +[INFO] Finished at: Wed Apr 17 10:51:03 BST 2013 +[INFO] Final Memory: 11M/456M +[INFO] ------------------------------------------------------------------------ + + + Congratulations! You have successfully run your first HornetQ example. Try some of the + others. +
+
+ The Java EE Examples + The Java EE Examples are examples that require a JEE application server to run. They + include MDB, Servlet, EJB examples etc. For this you will need the JBoss Application Server 7.1.x + installed and uses Arquillian to run the example. How to do this is explained in the previous chapters. + We'll use the MDB example for the purposes of this guide. For the other examples refer + to the user guide. Before going any further ensure that the JBoss Application Server is + running. + The first thing we need to do is set the JBOSS_HOME environment property to the location of the JBoss + Application Server, in a Linux shell this would be something like: + export JBOSS_HOME=/home/jbossas7.1/build/output/jboss-7.1.0 + Yoy can then run the example via maven by running mvn test + In the shell window you should see something like the following output: + +[INFO] Scanning for projects... +[INFO] +[INFO] ------------------------------------------------------------------------ +[INFO] Building HornetQ JEE MDB Example 2.3.0.BETA-SNAPSHOT +[INFO] ------------------------------------------------------------------------ +[INFO] +[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hornetq-jee-mdb-bmt-example --- +[INFO] Using 'UTF-8' encoding to copy filtered resources. +[INFO] skip non existing resourceDirectory /home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/src/main/resources +[INFO] +[INFO] --- maven-compiler-plugin:3.0:compile (default-compile) @ hornetq-jee-mdb-bmt-example --- +[INFO] Nothing to compile - all classes are up to date +[INFO] +[INFO] --- maven-resources-plugin:2.6:copy-resources (as-node-0) @ hornetq-jee-mdb-bmt-example --- +[INFO] Using 'UTF-8' encoding to copy filtered resources. +[INFO] Copying 1112 resources +[INFO] Copying 5 resources +[INFO] +[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hornetq-jee-mdb-bmt-example --- +[INFO] Using 'UTF-8' encoding to copy filtered resources. +[INFO] Copying 1 resource +[INFO] +[INFO] --- maven-compiler-plugin:3.0:testCompile (default-testCompile) @ hornetq-jee-mdb-bmt-example --- +[INFO] Changes detected - recompiling the module! +[INFO] Compiling 1 source file to /home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/test-classes +[INFO] +[INFO] --- maven-surefire-plugin:2.12:test (default-test) @ hornetq-jee-mdb-bmt-example --- +[INFO] Surefire report directory: /home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/surefire-reports + +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running org.hornetq.javaee.example.server.ExampleRunnerTest +log4j:WARN No appenders could be found for logger (org.jboss.logging). +log4j:WARN Please initialize the log4j system properly. +log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. +Apr 17, 2013 10:58:04 AM org.jboss.arquillian.container.impl.MapObject populate +WARNING: Configuration contain properties not supported by the backing object org.jboss.as.arquillian.container.managed.ManagedContainerConfiguration +Unused property entries: {waitForPortsTimeoutInSeconds=8, waitForPorts=8787 9999} +Supported property names: [jbossHome, outputToConsole, enableAssertions, password, managementPort, javaHome, javaVmArguments, username, serverConfig, allowConnectingToRunningServer, managementAddress, startupTimeoutInSeconds, modulePath] +Apr 17, 2013 10:58:04 AM org.jboss.as.arquillian.container.managed.ManagedDeployableContainer startInternal +INFO: Starting container with: [/home/andy/devtools/jdk1.6.0_25//bin/java, -Djboss.inst=/home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0, -ea, -Djboss.home.dir=/home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0, -Dorg.jboss.boot.log.file=/home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/log/boot.log, -Dlogging.configuration=file:/home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/configuration/logging.properties, -Djboss.modules.dir=/home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/modules, -Djboss.bundles.dir=/home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/bundles, -jar, /home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/jboss-modules.jar, -mp, /home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/modules, -jaxpmodule, javax.xml.jaxp-provider, org.jboss.as.standalone, -server-config, standalone-example.xml] +10:58:04,525 INFO [org.jboss.modules] JBoss Modules version 1.1.1.GA +10:58:04,664 INFO [org.jboss.msc] JBoss MSC version 1.0.2.GA +10:58:04,703 INFO [org.jboss.as] JBAS015899: JBoss AS 7.1.1.Final "Brontes" starting +10:58:05,492 INFO [org.xnio] XNIO Version 3.0.3.GA +10:58:05,494 INFO [org.jboss.as.server] JBAS015888: Creating http management service using socket-binding (management-http) +10:58:05,502 INFO [org.xnio.nio] XNIO NIO Implementation Version 3.0.3.GA +10:58:05,509 INFO [org.jboss.remoting] JBoss Remoting version 3.2.3.GA +10:58:05,527 INFO [org.jboss.as.logging] JBAS011502: Removing bootstrap log handlers +10:58:05,530 INFO [org.jboss.as.configadmin] (ServerService Thread Pool -- 32) JBAS016200: Activating ConfigAdmin Subsystem +10:58:05,560 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 37) JBAS010280: Activating Infinispan subsystem. +10:58:05,562 INFO [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 33) JBAS010403: Deploying JDBC-compliant driver class org.h2.Driver (version 1.3) +10:58:05,573 INFO [org.jboss.as.jacorb] (ServerService Thread Pool -- 38) JBAS016300: Activating JacORB Subsystem +10:58:05,595 INFO [org.jboss.as.connector] (MSC service thread 1-12) JBAS010408: Starting JCA Subsystem (JBoss IronJacamar 1.0.9.Final) +10:58:05,612 INFO [org.jboss.as.naming] (ServerService Thread Pool -- 48) JBAS011800: Activating Naming Subsystem +10:58:05,625 INFO [org.jboss.as.osgi] (ServerService Thread Pool -- 49) JBAS011940: Activating OSGi Subsystem +10:58:05,649 INFO [org.jboss.as.security] (ServerService Thread Pool -- 54) JBAS013101: Activating Security Subsystem +10:58:05,657 INFO [org.jboss.as.naming] (MSC service thread 1-8) JBAS011802: Starting Naming Service +10:58:05,663 INFO [org.jboss.as.mail.extension] (MSC service thread 1-16) JBAS015400: Bound mail session [java:jboss/mail/Default] +10:58:05,675 INFO [org.jboss.as.security] (MSC service thread 1-14) JBAS013100: Current PicketBox version=4.0.7.Final +10:58:05,683 INFO [org.jboss.as.webservices] (ServerService Thread Pool -- 58) JBAS015537: Activating WebServices Extension +10:58:05,705 INFO [org.jboss.jaxr] (MSC service thread 1-8) JBAS014000: Started JAXR subsystem, binding JAXR connection factory into JNDI as: java:jboss/jaxr/ConnectionFactory +10:58:05,831 INFO [org.jboss.ws.common.management.AbstractServerConfig] (MSC service thread 1-4) JBoss Web Services - Stack CXF Server 4.0.2.GA +10:58:05,943 INFO [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-6) Starting Coyote HTTP/1.1 on http-localhost.localdomain-127.0.0.1-8080 +10:58:05,966 INFO [org.jboss.as.jacorb] (MSC service thread 1-2) JBAS016330: CORBA ORB Service started +10:58:05,988 INFO [org.hornetq.core.server.impl.HornetQServerImpl] (MSC service thread 1-11) live server is starting with configuration HornetQ Configuration (clustered=false,backup=false,sharedStore=true,journalDirectory=/home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messagingjournal,bindingsDirectory=/home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messagingbindings,largeMessagesDirectory=/home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messaginglargemessages,pagingDirectory=/home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/messagingpaging) +10:58:05,996 INFO [org.hornetq.core.server.impl.HornetQServerImpl] (MSC service thread 1-11) Waiting to obtain live lock +10:58:06,037 INFO [org.hornetq.core.persistence.impl.journal.JournalStorageManager] (MSC service thread 1-11) Using AIO Journal +10:58:06,122 INFO [org.jboss.as.jacorb] (MSC service thread 1-14) JBAS016328: CORBA Naming Service started +10:58:06,184 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-7) JBAS010400: Bound data source [java:jboss/datasources/ExampleDS] +10:58:06,204 INFO [org.hornetq.core.server.impl.AIOFileLockNodeManager] (MSC service thread 1-11) Waiting to obtain live lock +10:58:06,205 INFO [org.hornetq.core.server.impl.AIOFileLockNodeManager] (MSC service thread 1-11) Live Server Obtained live lock +10:58:06,434 INFO [org.jboss.as.remoting] (MSC service thread 1-2) JBAS017100: Listening on localhost.localdomain/127.0.0.1:4447 +10:58:06,434 INFO [org.jboss.as.remoting] (MSC service thread 1-15) JBAS017100: Listening on /127.0.0.1:9999 +10:58:06,436 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-16) JBAS015012: Started FileSystemDeploymentService for directory /home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/deployments +10:58:08,790 INFO [org.hornetq.core.remoting.impl.netty.NettyAcceptor] (MSC service thread 1-11) Started Netty Acceptor version 3.2.5.Final-a96d88c localhost.localdomain:5445 for CORE protocol +10:58:08,793 INFO [org.hornetq.core.remoting.impl.netty.NettyAcceptor] (MSC service thread 1-11) Started Netty Acceptor version 3.2.5.Final-a96d88c localhost.localdomain:5455 for CORE protocol +10:58:08,795 INFO [org.hornetq.core.server.impl.HornetQServerImpl] (MSC service thread 1-11) Server is now live +10:58:08,797 INFO [org.hornetq.core.server.impl.HornetQServerImpl] (MSC service thread 1-11) HornetQ Server version 2.2.13.Final (HQ_2_2_13_FINAL_AS7, 122) [5c499e88-9c63-11e2-bfa3-fe5400591699]) started +10:58:08,822 INFO [org.jboss.as.messaging] (MSC service thread 1-4) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/RemoteConnectionFactory +10:58:08,824 INFO [org.jboss.as.messaging] (MSC service thread 1-4) JBAS011601: Bound messaging object to jndi name java:/RemoteConnectionFactory +10:58:08,825 INFO [org.jboss.as.messaging] (MSC service thread 1-10) JBAS011601: Bound messaging object to jndi name java:/ConnectionFactory +10:58:08,830 INFO [org.hornetq.core.server.impl.HornetQServerImpl] (MSC service thread 1-3) trying to deploy queue jms.queue.testQueue +10:58:08,836 INFO [org.jboss.as.messaging] (MSC service thread 1-3) JBAS011601: Bound messaging object to jndi name java:/queue/test +10:58:08,840 INFO [org.jboss.as.messaging] (MSC service thread 1-3) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/queues/testQueue +10:58:08,859 INFO [org.jboss.as.deployment.connector] (MSC service thread 1-9) JBAS010406: Registered connection factory java:/JmsXA +10:58:08,866 INFO [org.hornetq.ra.HornetQResourceAdapter] (MSC service thread 1-9) HornetQ resource adaptor started +10:58:08,867 INFO [org.jboss.as.connector.services.ResourceAdapterActivatorService$ResourceAdapterActivator] (MSC service thread 1-9) IJ020002: Deployed: file://RaActivatorhornetq-ra +10:58:08,870 INFO [org.jboss.as.deployment.connector] (MSC service thread 1-5) JBAS010401: Bound JCA ConnectionFactory [java:/JmsXA] +10:58:08,898 INFO [org.jboss.as.server.deployment] (MSC service thread 1-10) JBAS015876: Starting deployment of "ONT001-1.0.war" +10:58:09,146 INFO [org.jboss.wsf.stack.cxf.metadata.MetadataBuilder] (MSC service thread 1-1) Add Service + id=com.hpm.webservices.BasicWSImpl + address=http://localhost:8080/hpm/BasicWService + implementor=com.hpm.webservices.BasicWSImpl + invoker=org.jboss.wsf.stack.cxf.JBossWSInvoker + serviceName={http://ont001-hpm.rhcloud.com/BasicWS}BasicWService + portName={http://ont001-hpm.rhcloud.com/BasicWS}BasicWS + wsdlLocation=null + mtomEnabled=false +10:58:09,361 INFO [org.apache.cxf.service.factory.ReflectionServiceFactoryBean] (MSC service thread 1-1) Creating Service {http://ont001-hpm.rhcloud.com/BasicWS}BasicWService from WSDL: WEB-INF/wsdl/BasicWService.wsdl +10:58:09,517 INFO [org.jboss.wsf.stack.cxf.transport.AddressRewritingEndpointInfo] (MSC service thread 1-1) Setting new service endpoint address in wsdl: http://ONT001-HPM.rhcloud.com:80/BasicWService +10:58:09,656 INFO [org.jboss.wsf.stack.cxf.transport.AddressRewritingEndpointInfo] (MSC service thread 1-1) Setting new service endpoint address in wsdl: http://localhost:8080/hpm/BasicWService +10:58:09,688 INFO [org.apache.cxf.endpoint.ServerImpl] (MSC service thread 1-1) Setting the server's publish address to be http://localhost:8080/hpm/BasicWService +10:58:09,729 INFO [org.jboss.wsf.stack.cxf.deployment.WSDLFilePublisher] (MSC service thread 1-1) WSDL published to: file:/home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/wsdl/ONT001-1.0.war/BasicWService.wsdl +10:58:09,735 INFO [org.jboss.as.webservices] (MSC service thread 1-11) JBAS015539: Starting service jboss.ws.port-component-link +10:58:09,748 INFO [org.jboss.as.webservices] (MSC service thread 1-10) JBAS015539: Starting service jboss.ws.endpoint."ONT001-1.0.war"."com.hpm.webservices.BasicWSImpl" +10:58:09,753 INFO [org.jboss.ws.common.management.DefaultEndpointRegistry] (MSC service thread 1-10) register: jboss.ws:context=hpm,endpoint=com.hpm.webservices.BasicWSImpl +10:58:09,829 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /hpm +10:58:09,834 INFO [org.jboss.as] (MSC service thread 1-7) JBAS015951: Admin console listening on http://127.0.0.1:9990 +10:58:09,835 INFO [org.jboss.as] (MSC service thread 1-7) JBAS015874: JBoss AS 7.1.1.Final "Brontes" started in 5506ms - Started 216 of 296 services (79 services are passive or on-demand) +10:58:09,979 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "ONT001-1.0.war" +mdb.jar: +/org/ +/org/hornetq/ +/org/hornetq/javaee/ +/org/hornetq/javaee/example/ +/org/hornetq/javaee/example/server/ +/org/hornetq/javaee/example/server/MDB_BMTExample.class +10:58:11,612 INFO [org.jboss.as.repository] (management-handler-thread - 2) JBAS014900: Content added at location /home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/f0/e2d589ab9490193e109c8bc833f725c87defae/content +10:58:11,620 INFO [org.jboss.as.server.deployment] (MSC service thread 1-8) JBAS015876: Starting deployment of "arquillian-service" +10:58:11,811 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.jmx:main") which may be changed or removed in future versions without notice. +10:58:11,812 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.server:main") which may be changed or removed in future versions without notice. +10:58:11,813 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.osgi:main") which may be changed or removed in future versions without notice. +10:58:11,815 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.jandex:main") which may be changed or removed in future versions without notice. +10:58:11,817 WARN [org.jboss.as.dependency.private] (MSC service thread 1-1) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.osgi.framework:main") which may be changed or removed in future versions without notice. +10:58:11,953 INFO [org.jboss.as.server] (management-handler-thread - 2) JBAS018559: Deployed "arquillian-service" +10:58:12,328 INFO [org.jboss.as.repository] (management-handler-thread - 3) JBAS014900: Content added at location /home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/59/7dcdb0f420ed57aea638b2599f7a86eecf6c85/content +10:58:12,333 INFO [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015876: Starting deployment of "mdb.jar" +10:58:12,401 INFO [org.jboss.as.arquillian] (MSC service thread 1-14) Arquillian deployment detected: ArquillianConfig[service=jboss.arquillian.config."mdb.jar",unit=mdb.jar,tests=[org.hornetq.javaee.example.server.ExampleRunnerTest]] +10:58:12,418 INFO [org.jboss.as.ejb3] (MSC service thread 1-15) JBAS014142: Started message driven bean 'MDB_BMTExample' with 'hornetq-ra' resource adapter +10:58:12,562 INFO [org.jboss.as.server] (management-handler-thread - 3) JBAS018559: Deployed "mdb.jar" +Sent message: This is a text message +10:58:13,229 INFO [org.jboss.as.naming] (Remoting "localhost" task-3) JBAS011806: Channel end notification received, closing channel Channel ID 57be4578 (inbound) of Remoting connection 3ac552d5 to /127.0.0.1:58571 +10:58:13,255 INFO [stdout] (Thread-0 (HornetQ-client-global-threads-1402019528)) message This is a text message received +10:58:13,257 INFO [stdout] (Thread-0 (HornetQ-client-global-threads-1402019528)) we're in the middle of a transaction: org.jboss.tm.usertx.client.ServerVMClientUserTransaction@6b04d3c8 +10:58:14,292 INFO [org.jboss.as.server.deployment] (MSC service thread 1-5) JBAS015877: Stopped deployment mdb.jar in 33ms +10:58:14,413 INFO [org.jboss.as.repository] (management-handler-thread - 1) JBAS014901: Content removed from location /home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/59/7dcdb0f420ed57aea638b2599f7a86eecf6c85/content +10:58:14,415 INFO [org.jboss.as.server] (management-handler-thread - 1) JBAS018558: Undeployed "mdb.jar" +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.609 sec +10:58:14,436 INFO [org.jboss.as.server.deployment] (MSC service thread 1-5) JBAS015877: Stopped deployment arquillian-service in 6ms +10:58:14,530 INFO [org.jboss.as.repository] (management-handler-thread - 2) JBAS014901: Content removed from location /home/andy/projects/hornetq-master/examples/javaee/mdb-bmt/target/jbossas-node0/standalone/data/content/f0/e2d589ab9490193e109c8bc833f725c87defae/content +10:58:14,532 INFO [org.jboss.as.server] (management-handler-thread - 2) JBAS018558: Undeployed "arquillian-service" + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 + +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 23.441s +[INFO] Finished at: Wed Apr 17 10:58:16 BST 2013 +[INFO] Final Memory: 19M/361M +[INFO] ------------------------------------------------------------------------ + +Congratulations! you have successfully deployed and run a Java EE example. +
+
diff --git a/docs/quickstart-guide/en/images/hornetQ_logo_600px.png b/docs/quickstart-guide/en/images/hornetQ_logo_600px.png new file mode 100644 index 0000000000..b71f4ba130 Binary files /dev/null and b/docs/quickstart-guide/en/images/hornetQ_logo_600px.png differ diff --git a/docs/quickstart-guide/en/installation.xml b/docs/quickstart-guide/en/installation.xml new file mode 100644 index 0000000000..80d48444d6 --- /dev/null +++ b/docs/quickstart-guide/en/installation.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Installation + This section describes how to install HornetQ. +
+ Prerequisites + + HornetQ only runs on Java 7 or later. + + By default, HornetQ server runs with 1GiB of memory. If your computer has less memory, + or you want to run it with more available RAM, modify the value in bin/run.sh accordingly. + For persistence, HornetQ uses its own fast journal, which you can configure to use + libaio (which is the default when running on Linux) or Java NIO. In order to use the libaio + module on Linux, you'll need to install libaio, if it's not already installed. + If you're not running on Linux then you don't need to worry about this. + You can install libaio using the following steps as the root user: + Using yum, (e.g. on Fedora or Red Hat Enterprise Linux): + yum install libaio + Using aptitude, (e.g. on Ubuntu or Debian system): + apt-get install libaio +
+
+ Stand-alone HornetQ Server + After downloading the distribution, unzip it into your chosen directory. At this point + it should be possible to run straight out of the + box, the following describes the directory structure: + + |___ bin + | + |___ config + | |___ jboss-as-4 + | |___ jboss-as-5 + | |___ stand-alone + | + |___ docs + | |___ api + | |___ quickstart-guide + | |___ user-manual + | + |___ examples + | |___ core + | |___ javaee + | |___ jms + | + |___ lib + | + |___ licenses + | + |___ schemas + + + + bin -- binaries and scripts needed to run HornetQ. + + + config -- configuration files needed to configure HornetQ. This + contains configurations to run HornetQ either in stand-alone or inside JBoss AS 4 and 5. + Please refer to the reference guide for details on configuration. + + + docs -- guides and javadocs for HornetQ + + + examples -- JMS and Java EE examples. Please refer to the + 'running examples' chapter for details on how to run them. + + + lib -- jars and libraries needed to run HornetQ + + + licenses -- licenses for HornetQ + + + schemas -- XML Schemas used to validate HornetQ configuration + files + + +
+
diff --git a/docs/quickstart-guide/en/introduction.xml b/docs/quickstart-guide/en/introduction.xml new file mode 100644 index 0000000000..faded49f77 --- /dev/null +++ b/docs/quickstart-guide/en/introduction.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Getting Started + This short guide explains how to download, install and quickly get started with + HornetQ. + After downloading and installing we highly recommend you run the examples to get + acquainted with HornetQ. We ship with over 70 examples demonstrating most of the + features. + This guide is not intended to be a replacement for the user manual. The user manual goes + into much more depth, so please consult that for further information. + diff --git a/docs/quickstart-guide/en/master.xml b/docs/quickstart-guide/en/master.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/quickstart-guide/en/notice.xml b/docs/quickstart-guide/en/notice.xml new file mode 100644 index 0000000000..f5c5f05e48 --- /dev/null +++ b/docs/quickstart-guide/en/notice.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + + Legal Notice + + Copyright © 2010 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. + \ No newline at end of file diff --git a/docs/quickstart-guide/en/running.xml b/docs/quickstart-guide/en/running.xml new file mode 100644 index 0000000000..39f8797f23 --- /dev/null +++ b/docs/quickstart-guide/en/running.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Starting The Server +
+ Standalone HornetQ + To run a stand-alone server, open up a shell or command prompt and navigate into the + bin directory. Then execute ./run.sh (or run.bat on Windows) and you should see the following output + + bin$ ./run.sh + + 15:05:54,108 INFO @main [HornetQBootstrapServer] Starting HornetQ server + ... + 15:06:02,566 INFO @main [HornetQServerImpl] HornetQ Server version + 2.0.0.CR3 (yellowjacket, 111) started + + HornetQ is now running. + Both the run and the stop scripts use the config under config/stand-alone/non-clustered by default. The configuration can be changed + by running ./run.sh ../config/stand-alone/clustered or another config of + your choosing. This is the same for the stop script and the windows bat files. +
+
+ HornetQ In Wildfly + HornetQ is the Default Messaging Provider in the Wildfly Application Server + To run the server you need to run the standalone-full.xml configuration by running the command './standalone.sh -c standalone-full.xml'. + You will see something like:/ + + bin$ ./standalone.sh -c standalone-full.xml + ========================================================================= + + JBoss Bootstrap Environment + + JBOSS_HOME: /home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT + + JAVA: java + + JAVA_OPTS: -server -XX:+UseCompressedOops -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true + + ========================================================================= + + 14:47:33,642 INFO [org.jboss.modules] (main) JBoss Modules version 1.3.0.Final + 14:47:34,780 INFO [org.jboss.msc] (main) JBoss MSC version 1.2.0.Beta2 + 14:47:34,875 INFO [org.jboss.as] (MSC service thread 1-6) JBAS015899: WildFly 8.0.0.Beta1-SNAPSHOT "WildFly" starting + 14:47:40,382 INFO [org.jboss.as.server] (Controller Boot Thread) JBAS015888: Creating http management service using socket-binding (management-http) + 14:47:40,383 INFO [org.xnio] (MSC service thread 1-15) XNIO version 3.1.0.CR7 + 14:47:40,402 INFO [org.xnio.nio] (MSC service thread 1-15) XNIO NIO Implementation Version 3.1.0.CR7 + 14:47:40,488 INFO [org.jboss.remoting] (MSC service thread 1-15) JBoss Remoting version 4.0.0.Beta1 + 14:47:40,547 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 36) JBAS010280: Activating Infinispan subsystem. + 14:47:40,560 INFO [org.jboss.as.naming] (ServerService Thread Pool -- 47) JBAS011800: Activating Naming Subsystem + 14:47:40,560 INFO [org.jboss.as.security] (ServerService Thread Pool -- 52) JBAS013171: Activating Security Subsystem + 14:47:40,567 INFO [org.jboss.as.jacorb] (ServerService Thread Pool -- 37) JBAS016300: Activating JacORB Subsystem + 14:47:40,571 INFO [org.jboss.as.jsf] (ServerService Thread Pool -- 43) JBAS012605: Activated the following JSF Implementations: [main] + 14:47:40,574 INFO [org.jboss.as.webservices] (ServerService Thread Pool -- 56) JBAS015537: Activating WebServices Extension + 14:47:40,721 INFO [org.jboss.as.connector.logging] (MSC service thread 1-6) JBAS010408: Starting JCA Subsystem (IronJacamar 1.1.0.Final) + 14:47:41,321 INFO [org.jboss.as.naming] (MSC service thread 1-4) JBAS011802: Starting Naming Service + 14:47:41,323 INFO [org.jboss.as.mail.extension] (MSC service thread 1-11) JBAS015400: Bound mail session [java:jboss/mail/Default] + 14:47:41,552 INFO [org.wildfly.extension.undertow] (MSC service thread 1-10) JBAS017502: Undertow 1.0.0.Beta16 starting + 14:47:41,552 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 55) JBAS017502: Undertow 1.0.0.Beta16 starting + 14:47:41,573 INFO [org.jboss.as.security] (MSC service thread 1-6) JBAS013170: Current PicketBox version=4.0.17.SP1 + 14:47:41,775 INFO [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 31) JBAS010403: Deploying JDBC-compliant driver class org.h2.Driver (version 1.3) + 14:47:41,777 INFO [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-16) JBAS010417: Started Driver service with driver-name = h2 + 14:47:42,085 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 55) JBAS017527: Creating file handler for path /home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/welcome-content + 14:47:42,086 INFO [org.wildfly.extension.undertow] (MSC service thread 1-2) JBAS017525: Started server default-server. + 14:47:42,088 INFO [org.wildfly.extension.undertow] (MSC service thread 1-13) JBAS017531: Host default-host starting + 14:47:42,471 INFO [org.wildfly.extension.undertow] (MSC service thread 1-7) JBAS017519: Undertow HTTP listener default listening on /127.0.0.1:8080 + 14:47:42,823 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-10) JBAS015012: Started FileSystemDeploymentService for directory /home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/deployments + 14:47:42,882 INFO [org.jboss.as.remoting] (MSC service thread 1-16) JBAS017100: Listening on 127.0.0.1:9999 + 14:47:43,037 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ221000: live server is starting with configuration HornetQ Configuration (clustered=false,backup=false,sharedStore=true,journalDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messagingjournal,bindingsDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messagingbindings,largeMessagesDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messaginglargemessages,pagingDirectory=/home/andy/projects/wildfly/build/target/wildfly-8.0.0.Beta1-SNAPSHOT/standalone/data/messagingpaging) + 14:47:43,062 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ221006: Waiting to obtain live lock + 14:47:43,103 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ221012: Using AIO Journal + 14:47:43,313 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support CORE + 14:47:43,426 INFO [org.jboss.ws.common.management] (MSC service thread 1-3) JBWS022052: Starting JBoss Web Services - Stack CXF Server 4.2.1.Final + 14:47:43,448 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support AMQP + 14:47:43,451 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support STOMP + 14:47:43,453 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ224067: Adding protocol support STOMP_WS + 14:47:43,567 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ221034: Waiting to obtain live lock + 14:47:43,567 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ221035: Live Server Obtained live lock + 14:47:43,777 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-8) JBAS010400: Bound data source [java:jboss/datasources/ExampleDS] + 14:47:43,781 INFO [org.jboss.as.jacorb] (MSC service thread 1-1) JBAS016330: CORBA ORB Service started + 14:47:44,115 INFO [org.jboss.as.jacorb] (MSC service thread 1-13) JBAS016328: CORBA Naming Service started + 14:47:44,345 INFO [org.wildfly.extension.undertow] (MSC service thread 1-3) JBAS018210: Register web context: /hornetq-server + 14:47:44,361 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ221020: Started Netty Acceptor version 3.6.6.Final-90e1eb2 127.0.0.1:5455 for CORE protocol + 14:47:44,362 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ221020: Started Netty Acceptor version 3.6.6.Final-90e1eb2 127.0.0.1:5445 for CORE protocol + 14:47:44,364 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ221020: Started Netty Acceptor version 3.6.6.Final-90e1eb2 org.hornetq.default.servlet:5445 for CORE protocol + 14:47:44,366 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ221007: Server is now live + 14:47:44,366 INFO [org.hornetq.core.server] (ServerService Thread Pool -- 58) HQ221001: HornetQ Server version 2.4.0.Beta2 (Andromedian Flyer, 123) [bcc1cd10-2bfb-11e3-ad5f-9f88840f9e1a] + 14:47:44,435 INFO [org.jboss.as.messaging] (ServerService Thread Pool -- 58) JBAS011601: Bound messaging object to jndi name java:/ConnectionFactory + 14:47:44,437 INFO [org.jboss.as.messaging] (ServerService Thread Pool -- 59) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/ServletConnectionFactory + 14:47:44,439 INFO [org.jboss.as.messaging] (ServerService Thread Pool -- 60) JBAS011601: Bound messaging object to jndi name java:jboss/exported/jms/RemoteConnectionFactory + 14:47:44,462 INFO [org.jboss.as.connector.deployment] (MSC service thread 1-3) JBAS010406: Registered connection factory java:/JmsXA + 14:47:44,531 INFO [org.hornetq.ra] (MSC service thread 1-3) HornetQ resource adaptor started + 14:47:44,532 INFO [org.jboss.as.connector.services.resourceadapters.ResourceAdapterActivatorService$ResourceAdapterActivator] (MSC service thread 1-3) IJ020002: Deployed: file://RaActivatorhornetq-ra + 14:47:44,535 INFO [org.jboss.as.connector.deployment] (MSC service thread 1-12) JBAS010401: Bound JCA ConnectionFactory [java:/JmsXA] + 14:47:44,536 INFO [org.jboss.as.messaging] (MSC service thread 1-15) JBAS011601: Bound messaging object to jndi name java:jboss/DefaultJMSConnectionFactory + 14:47:44,719 INFO [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management + 14:47:44,720 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990 + 14:47:44,721 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.0.0.Beta1-SNAPSHOT "WildFly" started in 12184ms - Started 213 of 249 services (73 services are lazy, passive or on-demand) + + +
+
diff --git a/docs/quickstart-guide/pom.xml b/docs/quickstart-guide/pom.xml new file mode 100644 index 0000000000..d2e1d02cf7 --- /dev/null +++ b/docs/quickstart-guide/pom.xml @@ -0,0 +1,300 @@ + + + + 4.0.0 + + + org.hornetq.docs + hornetq-docs + 2.5.0-SNAPSHOT + + + org.hornetq.docs + quickstart-guide + 1.0 + jdocbook + quickstart-guide + + + en + HornetQ_QuickStart_Guide + HornetQ QuickStart Guide + + + + + jboss-public-repository-group + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + default + + true + never + + + true + never + + + + + + jboss-public-repository-group + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + default + + true + + + true + + + + + + + + + + all + + true + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.3.5 + true + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${docname}.pdf + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + html_single + classpath:/xslt/org/jboss/xhtml-single.xsl + index.html + + + + + + + + + + + html + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + + + + + + + + + html-single + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + + + + + pdf + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${docname}.pdf + + + + + + + + + + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + org.jboss.pressgang + pressgang-xslt + 2.0.2 + + + org.jboss + jbossorg-jdocbook-style + 1.1.1 + jdocbook-style + + + + ${project.basedir} + ${docname}.xml + en + + ${project.basedir}/en + + images/*.png + + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${pdf.name} + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + html_single + classpath:/xslt/org/jboss/xhtml-single.xsl + index.html + + + + true + saxon + 1.72.0 + - + false + + + javax.xml.parsers.DocumentBuilderFactory + org.apache.xerces.jaxp.DocumentBuilderFactoryImpl + + + javax.xml.parsers.SAXParserFactory + org.apache.xerces.jaxp.SAXParserFactoryImpl + + + + + + + + + + + diff --git a/docs/quickstart-guide/quickstart-guide.xpr b/docs/quickstart-guide/quickstart-guide.xpr new file mode 100644 index 0000000000..24c58474d6 --- /dev/null +++ b/docs/quickstart-guide/quickstart-guide.xpr @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/quickstart-guide/zh/about.xml b/docs/quickstart-guide/zh/about.xml new file mode 100644 index 0000000000..393d60bdf8 --- /dev/null +++ b/docs/quickstart-guide/zh/about.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + 关于HornetQ + 什么是HornetQ? + + + HornetQ是一个开源项目。它的目标是一个多协议、可嵌入、高性能、可集群的异步的消息系统。 + + + 有关HornetQ是什么及不是什么的更多的问题,请访问 + FAQs wiki + 页 + + + 为什么要使用HornetQ? 以下给出了几个理由: + + + HornetQ是100%的开源软件。 HornetQ 采用 Apache v 2.0开源协议,对用户的限制最小。 + + + HornetQ的设计强调可用性。 + + + 采用Java语言编写。可以在任何Java 6+ 的平台上运行。这几乎包括了从Windows到IBM mainframes的每个平台。 + + + 性能出众。不但对非持久化消息的处理性能达到了非常高的性能。独特高效的日志(journal)使持久消息处理接近非持久消息的性能。 + + + 功能全面。不仅拥有其它成熟消息产品所具有的全部功能,而且还有很多独特的功能。 + + + HornetQ的设计遵从了简约的原则。对第三方软件的依赖极少。根据不同的需要, + HornetQ可以单独运行,也可以运行于JEE应用服务器中。它还可以嵌入到你自己的应用程序中。 + + + 完美的可获得性。HornetQ提供自动客户端失效备援(automatic client failover)功能,能保证在服务器故障时没有消息丢失或消息重复。 + + + 超级灵活的集群方案。可以控制集群进行消息负载均衡的方式。分布在不同地理位置的各个集群间可以通过非可靠的网络连接形成一个全球网络。 + 还可以非常灵活地配置消息路由。 + + + 请访问 wiki来全面了解HornetQ的所有功能介绍。 + + + diff --git a/docs/quickstart-guide/zh/download.xml b/docs/quickstart-guide/zh/download.xml new file mode 100644 index 0000000000..a15a51a758 --- /dev/null +++ b/docs/quickstart-guide/zh/download.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + 下载 + HornetQ项目的官方地址是 http://hornetq.org/ +
+ 软件下载 + HornetQ的下载地址是http://hornetq.org/downloads.html +
+
+ 项目信息 + + + + HornetQ的 wiki + + + 如果在使用HornetQ中发生任何问题,可以去我们的 用户论坛 + + + + 如果你有开发方面的问题与想法,请访问我们的 开发论坛 + + + 请加入我们的IRC频道与我们的核心开发工程师交流。 + + + 我们项目有自己的 博客 + + + 还可以跟踪我们的twitter + + + HornetQ的Git代码库地址 https://github.com/hornetq/hornetq + + + 每次发布的版本标签都在https://github.com/hornetq/hornetq/tags下能找到。 + + + +
+
diff --git a/docs/quickstart-guide/zh/examples.xml b/docs/quickstart-guide/zh/examples.xml new file mode 100644 index 0000000000..dab594a1b6 --- /dev/null +++ b/docs/quickstart-guide/zh/examples.xml @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + 运行HornetQ例子 + 在HornetQ的examples目录下有两组例子,它们是: + + + JMS例子 - 这些例子展示的是使用JMS发送与接收消息的功能。 + + + Java EE 例子 - 这些例子展示的是与应用服务器的集成,例如MDB,EJB,Servlet等。 + + +
+ JMS例子 + 所有JMS都有统一的格式。每个例子都有自己的目录,它的内容包括: + + + build.xml + ant的build文件,用来运行例子。 + + + src 目录 + 例子的代码。 + + + server0配置目录 + 它包含了运行服务器所需要的配置文件。有的集群的例子可能有多个这样的目录,如server0, + server1等。 + + + 在运行每个例子时,都要先启动一个或多个单独的服务器。当例子运行完毕,再将它们停止。 + 做为演示我们这里运行queue例子。其它的例子可以参见用户手册。 + 首先打开一个命令行窗口(shell),进入到HornetQ的 examples/jms/queue目录。 + 敲入命令./build.sh (或者在Windows上build.bat),你 + 将看到如下的输出: + Buildfile: build.xml + +run: + +init: + +compile: + [echo] src.example.dir=/home/andy/projects/hornetq/trunk/examples/jms/queue/src + [javac] Compiling 5 source files to /home/andy/projects/hornetq/trunk/examples/jms/queue +/build/classes + +runExample: + [java] 10:41:04,149 INFO @main [JMSExample] hornetq.example.runServer is true + [java] 10:41:04,149 INFO @main [JMSExample] starting server with config 'server0' + logServerOutput true + [java] 10:41:04,149 INFO @main [JMSExample] and vm args: -Xms512M,-Xmx512M,-XX:+U +seParallelGC,-XX:+AggressiveOpts,-XX:+UseFastAccessorMethods,-Djava.util.logging.config. +file=/home/andy/projects/hornetq/trunk/examples/jms/common/../../../src/config/stand-alone/no +n-clustered/logging.properties + [java] org.hornetq.jms.example.SpawnedJMSServer out:10:41:08,437 INFO @main [Journal +StorageManager] AIO journal selected + [java] org.hornetq.jms.example.SpawnedJMSServer out:10:41:08,437 WARN @main [Journal +StorageManager] AIO wasn't located on this platform, it will fall back to using pure Jav +a NIO. If your platform is Linux, install LibAIO to enable the AIO journal + [java] org.hornetq.jms.example.SpawnedJMSServer out:10:41:08,437 WARN @main [Securit +yStoreImpl] It has been detected that the cluster admin password which is used to replic +ate management operation from one node to the other has not had its password changed fro +m the installation default. Please see the HornetQ user guide for instructions o +n how to do this. + [java] org.hornetq.jms.example.SpawnedJMSServer out:10:41:10,941 INFO @main [HornetQCo +nnectionFactory] read only is false + [java] org.hornetq.jms.example.SpawnedJMSServer out:10:41:10,941 INFO @main [HornetQCo +nnectionFactory] read only is false + [java] org.hornetq.jms.example.SpawnedJMSServer out:10:41:10,941 INFO @main [HornetQCo +nnectionFactory] read only is false + [java] org.hornetq.jms.example.SpawnedJMSServer out:10:41:10,991 WARN @main [JMSServ +erManagerImpl] Binding for java:/ConnectionFactory already exists + [java] org.hornetq.jms.example.SpawnedJMSServer out:10:41:10,991 WARN @main [JMSServ +erManagerImpl] Binding for java:/XAConnectionFactory already exists + [java] org.hornetq.jms.example.SpawnedJMSServer out:10:41:11,241 INFO @main [Messagi +ngServerImpl] HornetQ Server version 2.0.0.BETA5 (buzz-buzz, 107) started + [java] org.hornetq.jms.example.SpawnedJMSServer out:10:41:11,241 INFO @main [HornetQBoot +strapServer] HornetQ server started + [java] org.hornetq.jms.example.SpawnedJMSServer out:STARTED:: + [java] 10:41:11,276 INFO @main [JMSExample] using server0/client-jndi.properties f +or jndi + [java] Sent message: This is a text message + [java] Received message: This is a text message + [java] + [java] ##################### + [java] ### SUCCESS! ### + [java] ##################### + +BUILD SUCCESSFUL +Total time: 13 seconds + + 恭喜!你已经成功地运行了你的第一个HornetQ例子。试着运行其它的例子。 +
+
+ Java EE例子 + Java EE的例子需要首先运行一个JEE应用服务器。这些例子包括MDB,Servlet,EJB等等。你首先要安装JBoss应用服务 + 器。参见前面的章节进行安装。 + 这里我们将用MDB例子来说明。有关其它例子的详细信息参见用户手册。首先确认JBoss应用服务器已经启动。 + 如同其它Java EE例子一样,MDB需要部署到应用服务器。第一,将JBOSS_HOME环境变量 + 指向你的应用服务器安装目录。如在Linux下: + export JBOSS_HOME=/home/jbossas5.1/build/output/jboss-5.1.0.GA + 然后就可以进行部署了。在examples/javaee/mdb目录下运行: + ./build.sh deploy + 它将创建一个“messaging"的AS配置,并用它来启动AS服务器。 + 在命令行窗口你会看到如下的输出: + Buildfile: build.xml + +validate-jboss: + +deploy: + +deploy-resources: + [copy] Copying 1 file to /home/andy/projects/jbossas5.1/build/output/jboss-5.1.0.GA + /server/default-with-hornetq/deploy/hornetq.sar + [copy] Copying 1 file to /home/andy/projects/jbossas5.1/build/output/jboss-5.1.0.GA + /server/default-with-hornetq/deploy/hornetq.sar + +init: + +compile: + +jar: + [jar] Building jar: /home/andy/projects/hornetq/trunk/examples/javaee/mdb/build/mdb-exa + mple.jar + +ear: + [jar] Building jar: /home/andy/projects/hornetq/trunk/examples/javaee/mdb/build/mdb-exa + mple.ear + +deploy-ear: + [copy] Copying 1 file to /home/andy/projects/jbossas5.1/build/output/jboss-5.1.0.GA + + ....... + + + [exec] 16:01:04,607 INFO [JBossASKernel] Class:javax.jms.MessageListener + [exec] 16:01:04,607 INFO [JBossASKernel] Added bean(jboss.j2ee:ear=mdb-example.ear, + jar=mdb-example.jar,name=MessageMDBExample,service=EJB3) to KernelDeployment of: + mdb-example.jar + [exec] 16:01:04,702 INFO [EJBContainer] STARTED EJB: org.hornetq.javaee.example.server + .MDBExample ejbName: MessageMDBExample + [exec] 16:01:09,496 INFO [TomcatDeployment] deploy, ctxPath=/mdb-example + [exec] 16:01:09,812 WARNING [config] Unable to process deployment descriptor for cont + ext '/mdb-example' + [exec] 16:01:09,812 INFO [config] Initializing Mojarra (1.2_12-b01-FCS) for context + '/mdb-example' + [exec] 16:01:09,958 INFO [Http11Protocol] Starting Coyote HTTP/1.1 on http-127.0.0.1- + 8080 + [exec] 16:01:09,990 INFO [AjpProtocol] Starting Coyote AJP/1.3 on ajp-127.0.0.1-8009 + [exec] 16:01:10,001 INFO [ServerImpl] JBoss (Microcontainer) [5.1.0.GA (build: SVNTag + =JBoss_5_1_0_GA date=200905151005)] Started in 6m:21s:797ms + + + 现在我们可以运行例子了。在mdb目录下运行下列命令: + ./build.sh + 你将看到如下输出: + Buildfile: build.xml + +run: + +init: + +compile: + +runExample: + [java] Sent message: This is a text message + +BUILD SUCCESSFUL +Total time: 7 seconds + 在JBoss应用服务器端你还会看到如下的输出: + 16:27:54,703 INFO [STDOUT] message This is a text message received + 然后在mdb目录下运行下面的命令可以将这个例子卸载。 + ./build.sh undeploy + 你将会看到如下的输出: + Buildfile: build.xml + +validate-jboss: + +undeploy: + +undeploy-misc: + [delete] Deleting: /home/andy/projects/jbossas5.1/build/output/jboss-5.1.0.GA + /server/default-with-hornetq/deploy/mdb-example.ear + [delete] Deleting: /home/andy/projects/jbossas5.1/build/output/jboss-5.1.0.GA + /server/default-with-hornetq/deploy/hornetq.sar/hornetq-queues.xml + [delete] Deleting: /home/andy/projects/jbossas5.1/build/output/jboss-5.1.0.GA + /server/default-with-hornetq/deploy/hornetq.sar/hornetq-jms.xml + +BUILD SUCCESSFUL +Total time: 1 second + + 你还会在窗口输出中看到MDB的应用最終被删除了,如: + 16:36:45,277 INFO [EJBContainer] STOPPED EJB: org.jboss.javaee.example.server.MDBExample + ejbName: MessageMDBExample + + 恭喜!你已经成功地部署并运行了一个Java EE的例子。 +
+
diff --git a/docs/quickstart-guide/zh/images/hornetQ_logo_600px.png b/docs/quickstart-guide/zh/images/hornetQ_logo_600px.png new file mode 100644 index 0000000000..b71f4ba130 Binary files /dev/null and b/docs/quickstart-guide/zh/images/hornetQ_logo_600px.png differ diff --git a/docs/quickstart-guide/zh/installation.xml b/docs/quickstart-guide/zh/installation.xml new file mode 100644 index 0000000000..dc89fd427d --- /dev/null +++ b/docs/quickstart-guide/zh/installation.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + 安装 + 本章讲述如何安装HornetQ。 +
+ 准备 + + HornetQ只能在Java 6或以上版本中运行 + + 默认情况下HornetQ运行的内存是1GiB。如果你的电脑内存少于1GiB,或者你希望更多的内存给HornetQ,你 + 可以修改 bin/run.sh脚本文件。 + HornetQ有自己的快速日志系统,它能够使用libaio(在Linux上它是默认的)或Java的NIO。 + 如果要使用libaio,你需要首先在你的Linux上安装它。 + 如果你不在使用Linux,则不需要考虑这个问题。 + 要安装libaio,你可以使用root用户完成以下步骤: + 使用yum(例如在Fedora 或 Red Hat Enterprise Linux上): + yum install libaio + 使用aptitude, (例如在Ubuntu或Debian系统上): + apt-get install libaio +
+
+ 单独的HornetQ服务器 + 将软件包下载后,将其解压到你选定的目录下。这里你就可以直接运行了。 + 下面给出了它的目录结构: + + |___ bin + | + |___ config + | |___ jboss-as-4 + | |___ jboss-as-5 + | |___ stand-alone + | + |___ docs + | |___ api + | |___ quickstart-guide + | |___ user-manual + | + |___ examples + | |___ core + | |___ javaee + | |___ jms + | + |___ lib + | + |___ licenses + | + |___ schemas + + + + bin -- 运行HornetQ的二进制文件和脚本文件。 + + + config -- HornetQ的配置文件。它包括了单独模式或者运行在 + JBoss AS 4 或 5中的配置。请参考配置索引来了解配置有详细信息。 + + + docs -- HornetQ的文档及Javadoc。 + + + examples -- JMS and Java EE例子。有关详细信息请参见 + 'running examples'一章。 + + + lib -- 运行HornetQ所需要的jar文件和库文件 + + + licenses -- HornetQ的软件协议 + + + schemas -- HornetQ配置文件的XML Schema + + +
+
+ HornetQ运行于JBoss应用服务器5.x + HornetQ可以部署在JBoss AS + 5中。目前默认的应用服务器没有安装HornetQ(HornetQ将是JBoss 6的默认JMS提供者),因此 + 你需要为HornetQ创建新的AS 5的配置(profile)。 + 创建AS 5新配置的步骤: + + + 下载并安装JBoss AS 5 + + + 设置环境变量JBOSS_HOME指向JBoss AS 5的安装目录。 + + + 运行HornetQ的config/jboss-as-5下的./build.sh (或 + 者如果在Windows下运行build.bat)。 + + + 这将会在$JBOSS_HOME/server创建两个服务器配置: + + + default-with-hornetq -- 这个相当于AS 5的default配置但其JMS提供者替换成为HornetQ。在这个配置中的HornetQ + 是非集群的。 + + + all-with-hornetq -- 这个相当于AS 5的all配置但其JMS提供者替换成为HornetQ。这个配置中的HornetQ + 是集群的。 + + + 这时,你就可以启动上面其中任何一个配置的JBoss AS 5服务器了,例如: + $JBOSS_HOME/bin/run.sh -c default-with-hornetq +
+
+ HornetQ运行于JBoss应用服务器4.x + 为了在AS 4中安装HornetQ,你需要创建新的配置(profile)。 + 步骤如下: + + + 下载并安装JBoss AS 4 + + + 设置环境变量JBOSS_HOME指向JBoss AS 4的安装目录。 + + + 运行HornetQ的config/jboss-as-4下的./build.sh (或 + 者如果在Windows下运行build.bat)。 + + + 这将会在$JBOSS_HOME/server创建两个服务器配置: + + + default-with-hornetq -- 这个相当于AS 4的default配置但其JMS提供者替换成为HornetQ。在这个配置中的HornetQ + 是非集群的。 + + + all-with-hornetq -- 这个相当于AS 4的all配置但其JMS提供者替换成为HornetQ。这个配置中的HornetQ + 是集群的。 + + + 这时,你就可以启动上面其中任何一个配置的JBoss AS 4服务器了,例如: + $JBOSS_HOME/bin/run.sh -c default-with-hornetq +
+
diff --git a/docs/quickstart-guide/zh/introduction.xml b/docs/quickstart-guide/zh/introduction.xml new file mode 100644 index 0000000000..e29f4fc3de --- /dev/null +++ b/docs/quickstart-guide/zh/introduction.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + 快速入手 + 本简短的指南给出了如何下载、安装HornetQ,以及尽快开始使用HornetQ。 + 我们强烈建议当下载安装完成后,运行HornetQ的例子来了解HornetQ。我们有70多个例子来展示几乎 + 所有HornetQ的功能。 + 本指南不能代替用户手册。用户手册包括更加完整和深入的信息,供用户进一步全面掌握HornetQ。 + diff --git a/docs/quickstart-guide/zh/master.xml b/docs/quickstart-guide/zh/master.xml new file mode 100644 index 0000000000..3971baf1c5 --- /dev/null +++ b/docs/quickstart-guide/zh/master.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]> + + + HornetQ快速指南 + Putting the buzz in messaging + + + + + ¬ice; + &about; + &introduction; + &download; + &installation; + &running; + &examples; + diff --git a/docs/quickstart-guide/zh/notice.xml b/docs/quickstart-guide/zh/notice.xml new file mode 100644 index 0000000000..a9db5e5fab --- /dev/null +++ b/docs/quickstart-guide/zh/notice.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + 法律声明 + + Red Hat, Inc. 以及其他公司2010年版权所有。 + Red Hat公司依照 CC-BY-SA 3.0 Unported(Creative Commons + Attribution-Share Alike)条款之规定授权用戶是用本手册中的文字和插图。 + 有关 CC-BY-SA 的解释请访问http://creativecommons.org/licenses/by-sa/3.0/。根据CC-BY-SA的规定,如果要发布本文档或任何本文档的修改版本,都必须给出原始版本文档的URL。 + Red Hat 作为本文档的授权方声明在相关法律允许的最大范围内放弃CC-BY-SA第4d节所规定的权利。 + + diff --git a/docs/quickstart-guide/zh/running.xml b/docs/quickstart-guide/zh/running.xml new file mode 100644 index 0000000000..7833af850a --- /dev/null +++ b/docs/quickstart-guide/zh/running.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + Starting The Server +
+ 单独HornetQ + 要运行单独的HornetQ服务,打开一个命令行窗口,进入到HornetQ的bin + 目录下,执行./run.sh (或者在Windows下 run.bat)。你将看到如下的输出: + + bin$ ./run.sh + + 15:05:54,108 INFO @main [HornetQBootstrapServer] Starting HornetQ server + ... + 15:06:02,566 INFO @main [HornetQServerImpl] HornetQ Server version + 2.0.0.CR3 (yellowjacket, 111) started + + 这表明HornetQ已经启动并运行了。 + 默认情况下,不论是启动还是停止脚本都使用config/stand-alone/non-clustered + 下的配置文件。要使用不同的配置目录,可运行./run.sh ../config/stand-alone/clustered + 或者其它选定的目录。同样方法适用于停止脚本。 +
+
+ HornetQ在JBoss AS 5.x中运行 + 要在JBoss AS 5运行HornetQ,你需要创建安装有HornetQ的AS 5的配置。然后用这个配置启动AS 5。 + 例如,要运行一个带有非集群的HornetQ服务的AS 5,进入$JBOSS_HOME/bin目录,然后键入: + + bin$ ./run.sh -c default-with-hornetq + + 15:18:35,460 INFO [ServerImpl] Starting JBoss (Microcontainer)... + 15:18:35,462 INFO [ServerImpl] Release ID: JBoss (Microcontainer) [5.1.0.GA (build: SVNTag= + JBoss_5_1_0_GA date=200905221053) + ... + 15:19:30,305 INFO [HornetQServerImpl] HornetQ Server version + 2.0.0.CR3 (yellowjacket, 111) started + ... + 15:19:43,601 INFO [ServerImpl] JBoss (Microcontainer) [5.1.0.GA (build: SVNTag= + JBoss_5_1_0_GA date=200905221053)]Started in 1m:14s:556ms + +
+
+ HornetQ在JBoss AS 4中运行 + 首先按照与JBoss AS 5相同的步骤创建安装有HornetQ的AS 4配置 + 然后以相同的方式启动AS。 +
+
+ HornetQ在JBoss AS 6.0中运行 + 从JBoss AS 6.0 M3开始,HornetQ已经是默认的(内建)JMS提供者。所以无需安装即可运行。 +
+
diff --git a/docs/user-manual/en/Author_Group.xml b/docs/user-manual/en/Author_Group.xml new file mode 100644 index 0000000000..42b4ffc37f --- /dev/null +++ b/docs/user-manual/en/Author_Group.xml @@ -0,0 +1,82 @@ + + + + +%BOOK_ENTITIES; +]> + + + Clebert + Suconic + + Red Hat, Inc. + Project Lead + JBoss + + csuconic@redhat.com + + + Andy + Taylor + + Red Hat, Inc. + Core Developer + JBoss + + ataylor@redhat.com + + + Tim + Fox + + Red Hat, Inc. + Core Developer + JBoss + + + + Jeff + Mesnil + + Red Hat, Inc. + Core Developer + JBoss + + + + Howard + Gao + + Red Hat, Inc. + Core Developer + JBoss + + ghoward@redhat.com + + + Francisco + Borges + + + Justin + Bertram + + Red Hat, Inc. + Core Developer + JBoss + + jbertram@redhat.com + + diff --git a/docs/user-manual/en/Book_Info.xml b/docs/user-manual/en/Book_Info.xml new file mode 100644 index 0000000000..f646ef63b1 --- /dev/null +++ b/docs/user-manual/en/Book_Info.xml @@ -0,0 +1,44 @@ + + + + +%BOOK_ENTITIES; +]> + + HornetQ User Manual + Putting the buzz in messaging + HornetQ + 2 + 2.1.0 + 1 + + The User manual is an in depth manual on all aspects of HornetQ + + + + + + + + HornetQ Logo + + + + + &YEAR; + &HOLDER; + + + diff --git a/docs/user-manual/en/HornetQ_User_Manual.ent b/docs/user-manual/en/HornetQ_User_Manual.ent new file mode 100644 index 0000000000..dd225e3e9e --- /dev/null +++ b/docs/user-manual/en/HornetQ_User_Manual.ent @@ -0,0 +1,18 @@ + + + + + + + diff --git a/docs/user-manual/en/HornetQ_User_Manual.xml b/docs/user-manual/en/HornetQ_User_Manual.xml new file mode 100644 index 0000000000..3ddf95485d --- /dev/null +++ b/docs/user-manual/en/HornetQ_User_Manual.xml @@ -0,0 +1,74 @@ + + + + +%BOOK_ENTITIES; + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/user-manual/en/aerogear-integration.xml b/docs/user-manual/en/aerogear-integration.xml new file mode 100644 index 0000000000..44e3e230ff --- /dev/null +++ b/docs/user-manual/en/aerogear-integration.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + %BOOK_ENTITIES; + ]> + + AeroGear Integration + AeroGears push technology provides support for different push notification technologies like Google Cloud Messaging, + Apple's APNs or Mozilla's SimplePush. HornetQ allows you to configure a Connector Service that will consume messages + from a queue and forward them to an AeroGear push server and subsequently sent as notifications to mobile devices. +
+ Configuring an AeroGear Connector Service + AeroGear Connector services are configured in the connector-services configuration: + + <connector-service name="aerogear-connector"> + <factory-class>org.hornetq.integration.aerogear.AeroGearConnectorServiceFactory</factory-class> + <param key="endpoint" value="endpoint"/> + <param key="queue" value="jms.queue.aerogearQueue"/> + <param key="application-id" value="an applicationid"/> + <param key="master-secret" value="a mastersecret"/> + </connector-service> + <address-setting match="jms.queue.lastValueQueue"> + <last-value-queue>true</last-value-queue> + </address-setting> + + Shown are the required params for the connector service and are: + + + + endpoint. The endpoint or URL of you AeroGear application. + + + queue. The name of the queue to consume from. + + + application-id. The application id of your mobile application in AeroGear. + + + master-secret. The secret of your mobile application in AeroGear. + + + As well as these required paramaters there are the following optional parameters + + + ttl. The time to live for the message once AeroGear receives it. + + + badge. The badge the mobile app should use for the notification. + + + sound. The sound the mobile app should use for the notification. + + + filter. A message filter(selector) to use on the connector. + + + retry-interval. If an error occurs on send, how long before we try again to connect. + + + retry-attempts. How many times we should try to reconnect after an error. + + + variants. A comma separated list of variants that should get the message. + + + aliases. A list of aliases that should get the message. + + + device-types. A list of device types that should get the messag. + + + More in depth explanations of the AeroGear related parameters can be found in the AeroGear Push docs +
+
+ How to send a message for AeroGear + To send a message intended for AeroGear simply send a JMS Message and set the appropriate headers, like so + + Message message = session.createMessage(); + + message.setStringProperty("AEROGEAR_ALERT", "Hello this is a notification from HornetQ"); + + producer.send(message); + + The 'AEROGEAR_ALERT' property will be the alert sent to the mobile device. + If the message does not contain this property then it will be simply ignored and left on the queue + Its also possible to override any of the other AeroGear parameters by simply setting them on the message, + for instance if you wanted to set ttl of a message you would: + + message.setIntProperty("AEROGEAR_TTL", 1234); + + or if you wanted to set the list of variants you would use: + + message.setStringProperty("AEROGEAR_VARIANTS", "variant1,variant2,variant3"); + + Again refer to the AeroGear documentation for a more in depth view on how to use these settings +
+
\ No newline at end of file diff --git a/docs/user-manual/en/appserver-integration.xml b/docs/user-manual/en/appserver-integration.xml new file mode 100644 index 0000000000..6335411449 --- /dev/null +++ b/docs/user-manual/en/appserver-integration.xml @@ -0,0 +1,1342 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Application Server Integration and Java EE + HornetQ can be easily installed in JBoss Application Server 4 or later. For details on + installing HornetQ in the JBoss Application Server please refer to quick-start guide. + Since HornetQ also provides a JCA adapter, it is also possible to integrate HornetQ + as a JMS provider in other JEE compliant app servers. For instructions on how to integrate a + remote JCA adaptor into another application sever, please consult the other application server's + instructions. + A JCA Adapter basically controls the inflow of messages to Message-Driven Beans (MDBs) and the + outflow of messages sent from other JEE components, e.g. EJBs and Servlets. + This section explains the basics behind configuring the different JEE components in the + AS. +
+ Configuring Message-Driven Beans + The delivery of messages to an MDB using HornetQ is configured on the JCA Adapter via + a configuration file ra.xml which can be found under the jms-ra.rar directory. By default this is configured to consume + messages using an InVM connector from the instance of HornetQ running within the + application server. The configuration properties are listed later in this chapter. + All MDBs however need to have the destination type and the destination configured. + The following example shows how this can be done using annotations: + +@MessageDriven(name = "MDBExample", activationConfig = +{ + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue") +}) +@ResourceAdapter("hornetq-ra.rar") +public class MDBExample implements MessageListener +{ + public void onMessage(Message message)... +} + In this example you can see that the MDB will consume messages from a queue that is + mapped into JNDI with the binding queue/testQueue. This queue must be + preconfigured in the usual way using the HornetQ configuration files. + The ResourceAdapter annotation is used to specify which adaptor + should be used. To use this you will need to import org.jboss.ejb3.annotation.ResourceAdapter for JBoss AS 5.X and later version which can be found in the + jboss-ejb3-ext-api.jar which can be found in the JBoss + repository. For JBoss AS 4.X, the annotation to use is org.jboss.annotation.ejb.ResourceAdaptor. + + Alternatively you can add use a deployment descriptor and add something like + the following to jboss.xml<message-driven> + <ejb-name>ExampleMDB</ejb-name> + <resource-adapter-name>hornetq-ra.rar</resource-adapter-name> +</message-driven> +You + can also rename the hornetq-ra.rar directory to jms-ra.rar and neither the annotation or + the extra descriptor information will be needed. If you do this you will need to edit + the jms-ds.xml datasource file and change rar-name + element. + + HornetQ is the default JMS provider for JBoss AS 6. Starting with this AS version, HornetQ resource + adapter is named jms-ra.rar and you no longer need to annotate the MDB for the resource adapter name. + + All the examples shipped with the HornetQ distribution use the annotation. +
+ Using Container-Managed Transactions + When an MDB is using Container-Managed Transactions (CMT), the delivery of the + message is done within the scope of a JTA transaction. The commit or rollback of + this transaction is controlled by the container itself. If the transaction is rolled + back then the message delivery semantics will kick in (by default, it will try to + redeliver the message up to 10 times before sending to a DLQ). Using annotations + this would be configured as follows: + +@MessageDriven(name = "MDB_CMP_TxRequiredExample", activationConfig = +{ + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue") +}) +@TransactionManagement(value= TransactionManagementType.CONTAINER) +@TransactionAttribute(value= TransactionAttributeType.REQUIRED) +@ResourceAdapter("hornetq-ra.rar") +public class MDB_CMP_TxRequiredExample implements MessageListener +{ + public void onMessage(Message message)... +} + The TransactionManagement annotation tells the container to manage the + transaction. The TransactionAttribute annotation tells the container that a JTA + transaction is required for this MDB. Note that the only other valid value for this + is TransactionAttributeType.NOT_SUPPORTED which tells the + container that this MDB does not support JTA transactions and one should not be + created. + It is also possible to inform the container that it must rollback the transaction + by calling setRollbackOnly on the MessageDrivenContext. The code for this would look something + like: + +@Resource +MessageDrivenContextContext ctx; + +public void onMessage(Message message) +{ + try + { + //something here fails + } + catch (Exception e) + { + ctx.setRollbackOnly(); + } +} + If you do not want the overhead of an XA transaction being created every time but + you would still like the message delivered within a transaction (i.e. you are only + using a JMS resource) then you can configure the MDB to use a local transaction. + This would be configured as such: + +@MessageDriven(name = "MDB_CMP_TxLocalExample", activationConfig = +{ + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"), + @ActivationConfigProperty(propertyName = "useLocalTx", propertyValue = "true") +}) +@TransactionManagement(value = TransactionManagementType.CONTAINER) +@TransactionAttribute(value = TransactionAttributeType.NOT_SUPPORTED) +@ResourceAdapter("hornetq-ra.rar") +public class MDB_CMP_TxLocalExample implements MessageListener +{ + public void onMessage(Message message)... +} +
+
+ Using Bean-Managed Transactions + Message-driven beans can also be configured to use Bean-Managed Transactions + (BMT). In this case a User Transaction is created. This would be configured as + follows: + +@MessageDriven(name = "MDB_BMPExample", activationConfig = +{ + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"), + @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Dups-ok-acknowledge") +}) +@TransactionManagement(value= TransactionManagementType.BEAN) +@ResourceAdapter("hornetq-ra.rar") +public class MDB_BMPExample implements MessageListener +{ + public void onMessage(Message message) +} + When using Bean-Managed Transactions the message delivery to the MDB will occur + outside the scope of the user transaction and use the acknowledge mode specified by + the user with the acknowledgeMode property. There are only 2 + acceptable values for this Auto-acknowledge and Dups-ok-acknowledge. Please note that because the message delivery is outside + the scope of the transaction a failure within the MDB will not cause the message to + be redelivered. + A user would control the life-cycle of the transaction something like the + following: + +@Resource +MessageDrivenContext ctx; + +public void onMessage(Message message) +{ + UserTransaction tx; + try + { + TextMessage textMessage = (TextMessage)message; + + String text = textMessage.getText(); + + UserTransaction tx = ctx.getUserTransaction(); + + tx.begin(); + + //do some stuff within the transaction + + tx.commit(); + + } + catch (Exception e) + { + tx.rollback(); + } +} +
+
+ Using Message Selectors with Message-Driven Beans + It is also possible to use MDBs with message selectors. To do this simple define + your message selector as follows: + +@MessageDriven(name = "MDBMessageSelectorExample", activationConfig = +{ + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"), + @ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "color = 'RED'") +}) +@TransactionManagement(value= TransactionManagementType.CONTAINER) +@TransactionAttribute(value= TransactionAttributeType.REQUIRED) +@ResourceAdapter("hornetq-ra.rar") +public class MDBMessageSelectorExample implements MessageListener +{ + public void onMessage(Message message).... +} +
+
+
+ Sending Messages from within JEE components + The JCA adapter can also be used for sending messages. The Connection Factory to use + is configured by default in the jms-ds.xml file and is mapped to + java:/JmsXA. Using this from within a JEE component will mean + that the sending of the message will be done as part of the JTA transaction being used + by the component. + This means that if the sending of the message fails the overall transaction would + rollback and the message be re-sent. Heres an example of this from within an + MDB: + +@MessageDriven(name = "MDBMessageSendTxExample", activationConfig = +{ + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue") +}) +@TransactionManagement(value= TransactionManagementType.CONTAINER) +@TransactionAttribute(value= TransactionAttributeType.REQUIRED) +@ResourceAdapter("hornetq-ra.rar") +public class MDBMessageSendTxExample implements MessageListener +{ + @Resource(mappedName = "java:/JmsXA") + ConnectionFactory connectionFactory; + + @Resource(mappedName = "queue/replyQueue") + Queue replyQueue; + + public void onMessage(Message message) + { + Connection conn = null; + try + { + //Step 9. We know the client is sending a text message so we cast + TextMessage textMessage = (TextMessage)message; + + //Step 10. get the text from the message. + String text = textMessage.getText(); + + System.out.println("message " + text); + + conn = connectionFactory.createConnection(); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + MessageProducer producer = sess.createProducer(replyQueue); + + producer.send(sess.createTextMessage("this is a reply")); + + } + catch (Exception e) + { + e.printStackTrace(); + } + finally + { + if(conn != null) + { + try + { + conn.close(); + } + catch (JMSException e) + { + } + } + } + } + } + In JBoss Application Server you can use the JMS JCA adapter for sending messages from + EJBs (including Session, Entity and Message-Driven Beans), Servlets (including jsps) and + custom MBeans. +
+
+ MDB and Consumer pool size + Most application servers, including JBoss, allow you to configure how many MDB's there are in a pool. In + JBoss this is configured via the MaxPoolSize parameter in the ejb3-interceptors-aop.xml file. Configuring + this has no actual effect on how many sessions/consumers there actually are created. This is because the Resource + Adaptor implementation knows nothing about the application servers MDB implementation. So even if you set the MDB + pool size to 1, 15 sessions/consumers will be created (this is the default). If you want to limit how many + sessions/consumers are created then you need to set the maxSession parameter either on the + resource adapter itself or via an an Activation Config Property on the MDB itself + +@MessageDriven(name = "MDBMessageSendTxExample", activationConfig = +{ + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"), + @ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1") +}) +@TransactionManagement(value= TransactionManagementType.CONTAINER) +@TransactionAttribute(value= TransactionAttributeType.REQUIRED) +@ResourceAdapter("hornetq-ra.rar") +public class MyMDB implements MessageListener +{ ....} + +
+
+ Configuring the JCA Adaptor + The Java Connector Architecture (JCA) Adapter is what allows HornetQ to be integrated + with JEE components such as MDBs and EJBs. It configures how components such as MDBs + consume messages from the HornetQ server and also how components such as EJBs or + Servlets can send messages. + The HornetQ JCA adapter is deployed via the jms-ra.rar archive. The + configuration of the adapter is found in this archive under META-INF/ra.xml. + The configuration will look something like the following: + +<resourceadapter> + <resourceadapter-class>org.hornetq.ra.HornetQResourceAdapter</resourceadapter-class> + <config-property> + <description>The transport type. Multiple connectors can be configured by using a comma separated list, + i.e. org.hornetq.core.remoting.impl.invm.InVMConnectorFactory,org.hornetq.core.remoting.impl.invm.InVMConnectorFactory.</description> + <config-property-name>ConnectorClassName</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>org.hornetq.core.remoting.impl.invm.InVMConnectorFactory</config-property-value> + </config-property> + <config-property> + <description>The transport configuration. These values must be in the form of key=val;key=val;, + if multiple connectors are used then each set must be separated by a comma i.e. host=host1;port=5445,host=host2;port=5446. + Each set of parameters maps to the connector classname specified.</description> + <config-property-name>ConnectionParameters</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>server-id=0</config-property-value> + </config-property> + + <outbound-resourceadapter> + <connection-definition> + <managedconnectionfactory-class>org.hornetq.ra.HornetQRAManagedConnection + Factory</managedconnectionfactory-class> + + <config-property> + <description>The default session type</description> + <config-property-name>SessionDefaultType</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>javax.jms.Queue</config-property-value> + </config-property> + <config-property> + <description>Try to obtain a lock within specified number of seconds; less + than or equal to 0 disable this functionality</description> + <config-property-name>UseTryLock</config-property-name> + <config-property-type>java.lang.Integer</config-property-type> + <config-property-value>0</config-property-value> + </config-property> + + <connectionfactory-interface>org.hornetq.ra.HornetQRAConnectionFactory + </connectionfactory-interface> + <connectionfactororg.hornetq.ra.HornetQConnectionFactoryImplonFactoryImpl + </connectionfactory-impl-class> + <connection-interface>javax.jms.Session</connection-interface> + <connection-impl-class>org.hornetq.ra.HornetQRASession + </connection-impl-class> + </connection-definition> + <transaction-support>XATransaction</transaction-support> + <authentication-mechanism> + <authentication-mechanism-type>BasicPassword + </authentication-mechanism-type> + <credential-interface>javax.resource.spi.security.PasswordCredential + </credential-interface> + </authentication-mechanism> + <reauthentication-support>false</reauthentication-support> + </outbound-resourceadapter> + + <inbound-resourceadapter> + <messageadapter> + <messagelistener> + <messagelistener-type>javax.jms.MessageListener</messagelistener-type> + <activationspec> + <activationspec-class>org.hornetq.ra.inflow.HornetQActivationSpec + </activationspec-class> + <required-config-property> + <config-property-name>destination</config-property-name> + </required-config-property> + </activationspec> + </messagelistener> + </messageadapter> + </inbound-resourceadapter> +</resourceadapter> + There are three main parts to this configuration. + + + A set of global properties for the adapter + + + The configuration for the outbound part of the adapter. This is used for + creating JMS resources within EE components. + + + The configuration of the inbound part of the adapter. This is used for + controlling the consumption of messages via MDBs. + + +
+ Global Properties + The first element you see is resourceadapter-class which should + be left unchanged. This is the HornetQ resource adapter class. + After that there is a list of configuration properties. This will be where most of + the configuration is done. The first two properties configure the transport used by the adapter + and the rest configure the connection factory itself. + + + All connection factory properties will use the defaults if they are not provided, except + for the reconnectAttempts which will default to -1. This + signifies that the connection should attempt to reconnect on connection + failure indefinitely. This is only used when the adapter is configured to + connect to a remote server as an InVM connector can never fail. + + + The following table explains what each property is for. + + Global Configuration Properties + + + + + + + Property Name + Property Type + Property Description + + + + + ConnectorClassName + String + The Connector class name (see for more information). If multiple connectors are + needed this should be provided as a comma separated list. + + + ConnectionParameters + String + The transport configuration. These parameters must be in the form of + key1=val1;key2=val2; and will be specific to the connector used. If + multiple connectors are configured then parameters should be supplied for each connector + separated by a comma. + + + + ha + boolean + True if high availability is needed. + + + useLocalTx + boolean + True will enable local transaction optimisation. + + + UserName + String + The user name to use when making a connection + + + Password + String + The password to use when making a connection + + + + DiscoveryAddress + String + The discovery group address to use to auto-detect a server + + + + DiscoveryPort + Integer + The port to use for discovery + + + + DiscoveryRefreshTimeout + Long + The timeout, in milliseconds, to refresh. + + + + + DiscoveryInitialWaitTimeout + + + Long + The initial time to wait for discovery. + + + + + ConnectionLoadBalancingPolicyClassName + + String + The load balancing policy class to use. + + + + ConnectionTTL + + Long + The time to live (in milliseconds) for the connection. + + + + CallTimeout + + Long + the call timeout (in milliseconds) for each packet sent. + + + + DupsOKBatchSize + + Integer + the batch size (in bytes) between acknowledgements when using + DUPS_OK_ACKNOWLEDGE mode + + + + TransactionBatchSize + + Integer + the batch size (in bytes) between acknowledgements when using a + transactional session + + + + ConsumerWindowSize + + Integer + the window size (in bytes) for consumer flow control + + + + ConsumerMaxRate + + Integer + the fastest rate a consumer may consume messages per second + + + + ConfirmationWindowSize + + Integer + the window size (in bytes) for reattachment confirmations + + + + ProducerMaxRate + + Integer + the maximum rate of messages per second that can be sent + + + + MinLargeMessageSize + + Integer + the size (in bytes) before a message is treated as large + + + + BlockOnAcknowledge + + Boolean + whether or not messages are acknowledged synchronously + + + + BlockOnNonDurableSend + + Boolean + whether or not non-durable messages are sent synchronously + + + + BlockOnDurableSend + + Boolean + whether or not durable messages are sent synchronously + + + + AutoGroup + + Boolean + whether or not message grouping is automatically used + + + + PreAcknowledge + + Boolean + whether messages are pre acknowledged by the server before + sending + + + + ReconnectAttempts + + Integer + maximum number of retry attempts, default for the resource adapter is -1 (infinite attempts) + + + + RetryInterval + + Long + the time (in milliseconds) to retry a connection after failing + + + + RetryIntervalMultiplier + + Double + multiplier to apply to successive retry intervals + + + + FailoverOnServerShutdown + + Boolean + If true client will reconnect to another server if + available + + + + ClientID + + String + the pre-configured client ID for the connection factory + + + + ClientFailureCheckPeriod + + Long + the period (in ms) after which the client will consider the + connection failed after not receiving packets from the + server + + + + UseGlobalPools + + Boolean + whether or not to use a global thread pool for threads + + + + ScheduledThreadPoolMaxSize + + Integer + the size of the scheduled thread pool + + + + ThreadPoolMaxSize + + Integer + the size of the thread pool + + + SetupAttempts + Integer + Number of attempts to setup a JMS connection (default is 10, -1 means to attempt infinitely). It is possible + that the MDB is deployed before the JMS resources are available. In that case, the resource + adapter will try to setup several times until the resources are available. This applies only for inbound connections + + + SetupInterval + Long + Interval in milliseconds between consecutive attempts to setup a JMS connection (default is 2000m). This applies only for inbound connections + + + +
+
+
+ Adapter Outbound Configuration + The outbound configuration should remain unchanged as they define connection + factories that are used by Java EE components. These Connection Factories can be + defined inside a configuration file that matches the name *-ds.xml. You'll find a default jms-ds.xml + configuration under the hornetq directory in the JBoss AS + deployment. The connection factories defined in this file inherit their + properties from the main ra.xml configuration but can also be + overridden. The following example shows how to override them. + + Please note that this configuration only applies when HornetQ resource adapter is installed in + JBoss Application Server. If you are using another JEE application + server please refer to your application servers documentation for how to do + this. + + +<tx-connection-factory> + <jndi-name>RemoteJmsXA</jndi-name> + <xa-transaction/> + <rar-name>jms-ra.rar</rar-name> + <connection-definition>org.hornetq.ra.HornetQRAConnectionFactory +</connection-definition> +<config-property name="SessionDefaultType" type="String">javax.jms.Topic</config-property> + <config-property name="ConnectorClassName" type="String"> + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + </config-property> + <config-property name="ConnectionParameters" type="String"> + port=5445</config-property> + <max-pool-size>20</max-pool-size> +</tx-connection-factory> + + overriding connectors + If the connector class name is overridden the all parameters must also be supplied. + + In this example the connection factory will be bound to JNDI with the name + RemoteJmsXA and can be looked up in the usual way using JNDI + or defined within the EJB or MDB as such: + +@Resource(mappedName="java:/RemoteJmsXA") +private ConnectionFactory connectionFactory; + The config-property elements are what overrides those in the + ra.xml configuration file. Any of the elements pertaining to the + connection factory can be overridden here. + The outbound configuration also defines additional properties in addition to the global configuration properties. + + + Outbound Configuration Properties + + + + + + + Property Name + Property Type + Property Description + + + + + SessionDefaultType + String + the default session type + + + UseTryLock + Integer + try to obtain a lock within specified number of seconds. less + than or equal to 0 disable this functionality + + + +
+
+
+ Adapter Inbound Configuration + The inbound configuration should again remain unchanged. This controls what + forwards messages onto MDBs. It is possible to override properties on the MDB by + adding an activation configuration to the MDB itself. This could be used to + configure the MDB to consume from a different server. + The inbound configuration also defines additional properties in addition to the global configuration properties. + + + Inbound Configuration Properties + + + + + + + Property Name + Property Type + Property Description + + + + + Destination + String + JNDI name of the destination + + + DestinationType + String + type of the destination, either javax.jms.Queue or javax.jms.Topic + (default is javax.jms.Queue) + + + AcknowledgeMode + String + The Acknowledgment mode, either Auto-acknowledge or Dups-ok-acknowledge + (default is Auto-acknowledge). AUTO_ACKNOWLEDGE and DUPS_OK_ACKNOWLEDGE are acceptable values. + + + JndiParams + String + A semicolon (';') delimited string of name=value pairs which represent the properties to be used for the destination JNDI + look up. The properties depends on the JNDI implementation of the server hosting HornetQ. Typically only be used when the MDB is + configured to consume from a remote destination and needs to look up a JNDI reference rather than the HornetQ name of the + destination. Only relevant when useJNDI is true (default is an empty string). + + + MaxSession + Integer + Maximum number of session created by this inbound configuration (default is 15) + + + MessageSelector + String + the message selector of the consumer + + + SubscriptionDurability + String + Type of the subscription, either Durable or NonDurable + + + ShareSubscriptions + Boolean + When true, multiple MDBs can share the same Durable subscription + + + SubscriptionName + String + Name of the subscription + + + TransactionTimeout + Long + The transaction timeout in milliseconds (default is 0, the transaction does not timeout) + + + UseJNDI + Boolean + Whether or not use JNDI to look up the destination (default is true) + + + +
+ +
+
+ Configuring the adapter to use a standalone HornetQ Server + Sometime you may want your messaging server on a different machine or separate from the application server. + If this is the case you will only need the hornetq client libs installed. This section explains what config to create + and what jar dependencies are needed. +
+ There are two configuration files needed to do this, one for the incoming adapter used for MDB's + and one for outgoing connections managed by the JCA managed connection pool used by outgoing JEE components + wanting outgoing connections. +
+ Configuring the Incoming Adaptor + Firstly you will need to create directory under the + deploy + directory ending in + .rar. + For this example we will name the directory hornetq-ra.rar. This detail is + important as + the name of directory is referred to by the MDB's and the outgoing configuration. + + + + The jboss default for this is jms-ra.rar, If you don't want to have to + configure your + MDB's you can use this but you may need to remove the generic adaptor that uses this. + + + Under the + hornetq-ra.rar + directory you will need to create a + META-INF + directory into which you should create an + ra.xml + configuration file. You can find a template + for the + ra.xml + under the config directory of the HornetQ distribution. + + To configure MDB's to consume messages from a remote HornetQ server you need to edit the + ra.xml + file under + deploy/hornet-ra.rar/META-INF + and change the transport type to + use a netty connector (instead of the invm connector that is defined) and configure its transport + parameters. + Heres an example of what this would look like: + + +<resourceadapter-class>org.hornetq.ra.HornetQResourceAdapter</resourceadapter-class> + <config-property> + <description>The transport type</description> + <config-property-name>ConnectorClassName</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property-value> + </config-property> + <config-property> + <description>The transport configuration. These values must be in the form of key=val;key=val;</description> + <config-property-name>ConnectionParameters</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>host=127.0.0.1;port=5446</config-property-value> +</config-property> + + If you want to provide a list of servers that the adapter can connect to you can provide a list of + connectors, each separated by a comma. + + + +<resourceadapter-class>org.hornetq.ra.HornetQResourceAdapter</resourceadapter-class> + <config-property> + <description>The transport type</description> + <config-property-name>ConnectorClassName</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory,org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property-value> + </config-property> + <config-property> + <description>The transport configuration. These values must be in the form of key=val;key=val;</description> + <config-property-name>ConnectionParameters</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>host=127.0.0.1;port=5446,host=127.0.0.2;port=5447</config-property-value> +</config-property> + + provide all parameters + + Make sure you provide parameters for each connector configured. The position of the parameters in the + list maps to each connector provided. + + + This configures the resource adapter to connect to a server running on localhost listening on port + 5446 + +
+ +
+ Configuring the outgoing adaptor + You will also need to configure the outbound connection by creating a hornetq-ds.xml + and placing it under any directory that will be deployed under the deploy directory. + In a standard HornetQ jboss configuration this would be under hornetq or hornetq.sar + but you can place it where ever you like. Actually as long as it ends in -ds.xml you can + call it anything you like. You can again find a template for this file under the config directory of the + HornetQ distribution but called jms-ds.xml which is the jboss default. + + The following example shows a sample configuration + +<tx-connection-factory> + <jndi-name>RemoteJmsXA</jndi-name> + <xa-transaction/> + <rar-name>hornetq-ra.rar</rar-name> + <connection-definition>org.hornetq.ra.HornetQRAConnectionFactory</connection-definition> + <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property> + <config-property name="ConnectorClassName" type="java.lang.String">org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property> + <config-property name="ConnectionParameters" type="java.lang.String">host=127.0.0.1;port=5446</config-property> + <max-pool-size>20</max-pool-size> +</tx-connection-factory> + Again you will see that this uses the netty connector type and will connect to the HornetQ server + running on localhost and listening on port 5446. JEE components can access this by using JNDI and looking + up the connection factory using JNDI using java:/RemoteJmsXA, you can see that this + is defined under thejndi-name attribute. You will also note that the outgoing connection + will be created by the resource adaptor configured under the directory hornetq-ra.rar + as explained in the last section. + + + Also if you want to configure multiple connectors do this as a comma separated list as in the ra configuration. + +
+ +
+ Jar dependencies + This is a list of the HornetQ and third party jars needed + + Jar Dependencies + + + + + + + Jar Name + Description + Location + + + + + hornetq-ra.jar + The HornetQ resource adaptor classes + deploy/hornetq-ra.rar or equivalent + + + hornetq-core-client.jar + The HornetQ core client classes + either in the config lib, i.e. default/lib or the common lib dir, i.e. $JBOSS_HOME/common lib + + + hornetq-jms-client.jar + The HornetQ JMS classes + as above + + + netty.jar + The Netty transport classes + as above + + + +
+
+ +
+
+
+
+ Configuring the JBoss Application Server to connect to Remote HornetQ Server + This is a step by step guide on how to configure a JBoss application server that doesn't have HornetQ installed + to use a remote instance of HornetQ +
+ Configuring JBoss 5 + Firstly download and install JBoss AS 5 as per the JBoss installation guide and HornetQ as per the + HornetQ installation guide. After that the following steps are required + + + Copy the following jars from the HornetQ distribution to the lib directory of + which ever JBossAs configuration you have chosen, i.e. default. + + + hornetq-core-client.jar + + + hornetq-jms-client.jar + + + hornetq-ra.jar (this can be found inside the hornetq-ra.rar archive) + + + netty.jar + + + + + create the directories hornetq-ra.rar and hornetq-ra.rar/META-INF + under the deploy directory in your JBoss config directory + + + under the hornetq-ra.rar/META-INF create a ra.xml file or + copy it from the HornetQ distribution (again it can be found in the hornetq-ra.rar archive) + and configure it as follows + +<?xml version="1.0" encoding="UTF-8"?> + +<connector xmlns="http://java.sun.com/xml/ns/j2ee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee + http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd" + version="1.5"> + + <description>HornetQ 2.0 Resource Adapter Alternate Configuration</description> + <display-name>HornetQ 2.0 Resource Adapter Alternate Configuration</display-name> + + <vendor-name>Red Hat Middleware LLC</vendor-name> + <eis-type>JMS 1.1 Server</eis-type> + <resourceadapter-version>1.0</resourceadapter-version> + + <license> + <description> +Copyright 2009 Red Hat, Inc. + Red Hat licenses this file to you under the Apache License, version + 2.0 (the "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + </description> + <license-required>true</license-required> + </license> + + <resourceadapter> + <resourceadapter-class>org.hornetq.ra.HornetQResourceAdapter</resourceadapter-class> + <config-property> + <description>The transport type</description> + <config-property-name>ConnectorClassName</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property-value> + </config-property> + <config-property> + <description>The transport configuration. These values must be in the form of key=val;key=val;</description> + <config-property-name>ConnectionParameters</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>host=127.0.0.1;port=5445</config-property-value> + </config-property> + + <outbound-resourceadapter> + <connection-definition> + <managedconnectionfactory-class>org.hornetq.ra.HornetQRAManagedConnectionFactory</managedconnectionfactory-class> + + <config-property> + <description>The default session type</description> + <config-property-name>SessionDefaultType</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>javax.jms.Queue</config-property-value> + </config-property> + <config-property> + <description>Try to obtain a lock within specified number of seconds; less than or equal to 0 disable this functionality</description> + <config-property-name>UseTryLock</config-property-name> + <config-property-type>java.lang.Integer</config-property-type> + <config-property-value>0</config-property-value> + </config-property> + + <connectionfactory-interface>org.hornetq.ra.HornetQRAConnectionFactory</connectionfactory-interface> + <connectionfactory-impl-class>org.hornetq.ra.HornetQRAConnectionFactoryImpl</connectionfactory-impl-class> + <connection-interface>javax.jms.Session</connection-interface> + <connection-impl-class>org.hornetq.ra.HornetQRASession</connection-impl-class> + </connection-definition> + <transaction-support>XATransaction</transaction-support> + <authentication-mechanism> + <authentication-mechanism-type>BasicPassword</authentication-mechanism-type> + <credential-interface>javax.resource.spi.security.PasswordCredential</credential-interface> + </authentication-mechanism> + <reauthentication-support>false</reauthentication-support> + </outbound-resourceadapter> + + <inbound-resourceadapter> + <messageadapter> + <messagelistener> + <messagelistener-type>javax.jms.MessageListener</messagelistener-type> + <activationspec> + <activationspec-class>org.hornetq.ra.inflow.HornetQActivationSpec</activationspec-class> + <required-config-property> + <config-property-name>destination</config-property-name> + </required-config-property> + </activationspec> + </messagelistener> + </messageadapter> + </inbound-resourceadapter> + + </resourceadapter> +</connector> + The important part of this configuration is the part in bold, i.e. <config-property-value>host=127.0.0.1;port=5445</config-property-value>. + This should be configured to the host and port of the remote HornetQ server. + + + At this point you should be able to now deploy MDB's that consume from the remote server. You will however, + have to make sure that your MDB's have the annotation @ResourceAdapter("hornetq-ra.rar") + added, this is illustrated in the Configuring Message-Driven Beans section. + If you don't want to add this annotation then you can delete the generic resource adapter jms-ra.rar + and rename the hornetq-ra.rar to this. + If you also want to use the remote HornetQ server for outgoing connections, i.e. sending messages, then + do the following: + + + Create a file called hornetq-ds.xml in the deploy directory + (in fact you can call this anything you want as long as it ends in -ds.xml). Then + add the following: + +<connection-factories> + <!-- + JMS XA Resource adapter, use this for outbound JMS connections. + Inbound connections are defined at the @MDB activation or at the resource-adapter properties. + --> + <tx-connection-factory> + <jndi-name>RemoteJmsXA</jndi-name> + <xa-transaction/> + <rar-name>hornetq-ra.rar</rar-name> + <connection-definition>org.hornetq.ra.HornetQRAConnectionFactory</connection-definition> + <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property> + <config-property name="ConnectorClassName" type="java.lang.String">org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property> + <config-property name="ConnectionParameters" type="java.lang.String">host=127.0.0.1;port=5445</config-property> + <max-pool-size>20</max-pool-size> + </tx-connection-factory> + + +</connection-factories> + Again you will see that the host and port are configured here to match the remote HornetQ servers + configuration. The other important attributes are: + + + jndi-name - This is the name used to look up the JMS connection factory from within your JEE client + + + rar-name - This should match the directory that you created to hold the Resource Adapter + configuration + + + + + Now you should be able to send messages using the JCA JMS connection pooling within an XA transaction. +
+
+ Configuring JBoss 5 + The steps to do this are exactly the same as for JBoss 4, you will have to create a jboss.xml definition + file for your MDB with the following entry + +<message-driven> + <ejb-name>MyMDB</ejb-name> + <resource-adapter-name>jms-ra.rar</resource-adapter-name> + </message-driven> + Also you will need to edit the standardjboss.xml and uncomment the section with the + following 'Uncomment to use JMS message inflow from jmsra.rar' and then comment out the invoker-proxy-binding + called 'message-driven-bean' +
+
+
+ High Availability JNDI (HA-JNDI) + If you are using JNDI to look-up JMS queues, topics and connection factories from a + cluster of servers, it is likely you will want to use HA-JNDI so that your JNDI look-ups + will continue to work if one or more of the servers in the cluster fail. + HA-JNDI is a JBoss Application Server service which allows you to use JNDI from + clients without them having to know the exact JNDI connection details of every server in + the cluster. This service is only available if using a cluster of JBoss Application + Server instances. + To use it use the following properties when connecting to JNDI. + +Hashtable<String, String> jndiParameters = new Hashtable<String, String>(); +jndiParameters.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); +jndiParameters.put("java.naming.factory.url.pkgs=", "org.jboss.naming:org.jnp.interfaces"); + +initialContext = new InitialContext(jndiParameters); + For more information on using HA-JNDI see the JBoss Application Server clustering documentation +
+
+ XA Recovery + XA recovery deals with system or application failures to ensure + that of a transaction are applied consistently to all resources affected by the + transaction, even if any of the application processes or the machine hosting them crash + or lose network connectivity. For more information on XA Recovery,please refer to JBoss + Transactions. + When HornetQ is integrated with JBoss AS, it can take advantage of JBoss Transactions + to provide recovery of messaging resources. If messages are involved in a XA + transaction, in the event of a server crash, the recovery manager will ensure that the + transactions are recovered and the messages will either be committed or rolled back + (depending on the transaction outcome) when the server is restarted. +
+ XA Recovery Configuration + To enable HornetQ's XA Recovery, the Recovery Manager must be configured to connect + to HornetQ to recover its resources. The following property must be added to the + jta section of conf/jbossts-properties.xml + of JBoss AS profiles: + +<properties depends="arjuna" name="jta"> + ... + + <property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HornetQ1" + value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;[connection configuration]"/> + <property name="com.arjuna.ats.jta.xaRecoveryNode" value="1"/> +</properties> + The [connection configuration] contains all the information + required to connect to HornetQ node under the form [connector factory class + name],[user name], [password], [connector parameters]. + + + [connector factory class name] corresponds to the name + of the ConnectorFactory used to connect to HornetQ. + Values can be org.hornetq.core.remoting.impl.invm.InVMConnectorFactory or + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + [user name] is the user name to create a client + session. It is optional + + + [password] is the password to create a client session. + It is mandatory only if the user name is specified + + + [connector parameters] is a list of comma-separated + key=value pair which are passed to the connector factory (see for a list of the transport + parameters). + + + Also note the com.arjuna.ats.jta.xaRecoveryNode parameter. If you want recovery + enabled then this must be configured to what ever the tx node id is set to, this is configured in the + same file by the com.arjuna.ats.arjuna.xa.nodeIdentifier property. + + HornetQ must have a valid acceptor which corresponds to the connector + specified in conf/jbossts-properties.xml. + +
+ Configuration Settings + If HornetQ is configured with a default in-vm acceptor: + +<acceptor name="in-vm"> + <factory-class>org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory</factory-class> +</acceptor> + the corresponding configuration in conf/jbossts-properties.xml is: + +<property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HORNETQ1" + value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;org.hornetq.core.remoting.impl.invm.InVMConnectorFactory"/> + If it is now configured with a netty acceptor on a non-default port: + +<acceptor name="netty"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + <param key="port" value="8888"/> +</acceptor> + the corresponding configuration in conf/jbossts-properties.xml is: + +<property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HORNETQ1" + value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;org.hornetq.core.remoting.impl.netty.NettyConnectorFactory, , , port=8888"/> + + Note the additional commas to skip the user and password before connector + parameters + + If the recovery must use admin, adminpass, the + configuration would have been: + +<property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HORNETQ1" + value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;org.hornetq.core.remoting.impl.netty.NettyConnectorFactory, admin, adminpass, port=8888"/> + Configuring HornetQ with an invm acceptor and configuring the Recovery Manager + with an invm connector is the recommended way to enable XA Recovery. +
+
+
+ Example + See which shows how to configure XA Recovery + and recover messages after a server crash. +
+
+
diff --git a/docs/user-manual/en/architecture.xml b/docs/user-manual/en/architecture.xml new file mode 100644 index 0000000000..8b7085cba7 --- /dev/null +++ b/docs/user-manual/en/architecture.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Architecture + In this section we will give an overview of the HornetQ high level architecture. +
+ Core Architecture + HornetQ core is designed simply as set of Plain Old Java Objects (POJOs) - we hope you + like its clean-cut design. + We've also designed it to have as few dependencies on external jars as possible. In + fact, HornetQ core has only one jar dependency, netty.jar, + other than the standard JDK classes! This is because we use some of the netty buffer classes + internally. + This allows HornetQ to be easily embedded in your own project, or instantiated in any + dependency injection framework such as JBoss Microcontainer, Spring or Google + Guice. + Each HornetQ server has its own ultra high performance persistent journal, which it + uses for message and other persistence. + Using a high performance journal allows outrageous persistence message performance, + something not achievable when using a relational database for persistence. + HornetQ clients, potentially on different physical machines interact with the HornetQ + server. HornetQ currently provides two APIs for messaging at the client side: + + + + Core client API. This is a simple intuitive Java API that allows the full + set of messaging functionality without some of the complexities of + JMS. + + + JMS client API. The standard JMS API is available at the client + side. + + + + JMS semantics are implemented by a thin JMS facade layer on the client side. + The HornetQ server does not speak JMS and in fact does not know anything about JMS, + it is a protocol agnostic messaging server designed to be used with multiple different + protocols. + When a user uses the JMS API on the client side, all JMS interactions are translated + into operations on the HornetQ core client API before being transferred over the wire + using the HornetQ wire format. + The server always just deals with core API interactions. + A schematic illustrating this relationship is shown in figure 3.1 below: + + + + Figure 3.1 shows two user applications interacting with a HornetQ server. User + Application 1 is using the JMS API, while User Application 2 is using the core client + API directly. + You can see from the diagram that the JMS API is implemented by a thin facade layer on + the client side. +
+
+ HornetQ embedded in your own application + HornetQ core is designed as a set of simple POJOs so if you have an application that + requires messaging functionality internally but you don't want to expose that as a + HornetQ server you can directly instantiate and embed HornetQ servers in your own + application. + For more information on embedding HornetQ, see . +
+
+ HornetQ integrated with a JEE application server + HornetQ provides its own fully functional Java Connector Architecture (JCA) adaptor + which enables it to be integrated easily into any JEE compliant application server or + servlet engine. + JEE application servers provide Message Driven Beans (MDBs), which are a special type + of Enterprise Java Beans (EJBs) that can process messages from sources such as JMS + systems or mail systems. + Probably the most common use of an MDB is to consume messages from a JMS messaging + system. + According to the JEE specification, a JEE application server uses a JCA adapter to + integrate with a JMS messaging system so it can consume messages for MDBs. + However, the JCA adapter is not only used by the JEE application server for consuming messages via MDBs, it is also used when sending + message to the JMS messaging system e.g. from inside an EJB or servlet. + When integrating with a JMS messaging system from inside a JEE application server it + is always recommended that this is done via a JCA adaptor. In fact, communicating with a + JMS messaging system directly, without using JCA would be illegal according to the JEE + specification. + The application server's JCA service provides extra functionality such as connection + pooling and automatic transaction enlistment, which are desirable when using messaging, + say, from inside an EJB. It is possible to talk to a JMS messaging system directly from + an EJB, MDB or servlet without going through a JCA adapter, but this is not recommended + since you will not be able to take advantage of the JCA features, such as caching of JMS + sessions, which can result in poor performance. + Figure 3.2 below shows a JEE application server integrating with a HornetQ server via + the HornetQ JCA adaptor. Note that all communication between EJB sessions or entity + beans and Message Driven beans go through the adaptor and not directly to + HornetQ. + The large arrow with the prohibited sign shows an EJB session bean talking directly to + the HornetQ server. This is not recommended as you'll most likely end up creating a new + connection and session every time you want to interact from the EJB, which is an + anti-pattern. + + + + For more information on using the JCA adaptor, please see . +
+
+ HornetQ stand-alone server + HornetQ can also be deployed as a stand-alone server. This means a fully independent + messaging server not dependent on a JEE application server. + The standard stand-alone messaging server configuration comprises a core messaging + server, a JMS service and a JNDI service. + The role of the JMS Service is to deploy any JMS Queue, Topic and ConnectionFactory + instances from any server side hornetq-jms.xml configuration files. + It also provides a simple management API for creating and destroying Queues, Topics and + ConnectionFactory instances which can be accessed via JMX or the connection. It is a + separate service to the HornetQ core server, since the core server is JMS agnostic. If + you don't want to deploy any JMS Queue, Topic or ConnectionFactory instances via server + side XML configuration and don't require a JMS management API on the server side then + you can disable this service. + We also include a JNDI server since JNDI is a common requirement when using JMS to + lookup Queues, Topics and ConnectionFactory instances. If you do not require JNDI then + this service can also be disabled. HornetQ allows you to programmatically create JMS and + core objects directly on the client side as opposed to looking them up from JNDI, so a + JNDI server is not always a requirement. + The stand-alone server configuration uses JBoss Microcontainer to instantiate and + enforce dependencies between the components. JBoss Microcontainer is a very lightweight + POJO bootstrapper. + The stand-alone server architecture is shown in figure 3.3 below: + + + + For more information on server configuration files see . $ +
+
diff --git a/docs/user-manual/en/client-classpath.xml b/docs/user-manual/en/client-classpath.xml new file mode 100644 index 0000000000..be94909c57 --- /dev/null +++ b/docs/user-manual/en/client-classpath.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + The Client Classpath + HornetQ requires several jars on the Client Classpath depending on + whether the client uses HornetQ Core API, JMS, and JNDI. + + All the jars mentioned here can be found in the lib directory of + the HornetQ distribution. Be sure you only use the jars from the correct version of the + release, you must not mix and match versions of jars from different + HornetQ versions. Mixing and matching different jar versions may cause subtle errors and + failures to occur. + +
+ HornetQ Core Client + If you are using just a pure HornetQ Core client (i.e. no JMS) then you need hornetq-core-client.jar, hornetq-commons.jar, and + netty.jar on your client classpath. +
+
+ JMS Client + If you are using JMS on the client side, then you will also need to include hornetq-jms-client.jar and jboss-jms-api.jar. + + + jboss-jms-api.jar just contains Java EE API interface classes + needed for the javax.jms.* classes. If you already have a jar + with these interface classes on your classpath, you will not need it. + + +
+
+ JMS Client with JNDI + If you are looking up JMS resources from the JNDI server co-located with the HornetQ + standalone server, you will also need the jar jnp-client.jar jar on + your client classpath as well as any other jars mentioned previously. +
+
diff --git a/docs/user-manual/en/client-reconnection.xml b/docs/user-manual/en/client-reconnection.xml new file mode 100644 index 0000000000..d647011672 --- /dev/null +++ b/docs/user-manual/en/client-reconnection.xml @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Client Reconnection and Session Reattachment + HornetQ clients can be configured to automatically reconnect or re-attach to the server in + the event that a failure is detected in the connection between the client and the server. +
+ 100% Transparent session re-attachment + If the failure was due to some transient failure such as a temporary network failure, + and the target server was not restarted, then the sessions will still be existent on the + server, assuming the client hasn't been disconnected for more than connection-ttl . + In this scenario, HornetQ will automatically re-attach the client sessions to the + server sessions when the connection reconnects. This is done 100% transparently and the + client can continue exactly as if nothing had happened. + The way this works is as follows: + As HornetQ clients send commands to their servers they store each sent command in an + in-memory buffer. In the case that connection failure occurs and the client subsequently + reattaches to the same server, as part of the reattachment protocol the server informs + the client during reattachment with the id of the last command it successfully received + from that client. + If the client has sent more commands than were received before failover it can replay + any sent commands from its buffer so that the client and server can reconcile their + states. + The size of this buffer is configured by the ConfirmationWindowSize + parameter, when the server has received ConfirmationWindowSize bytes + of commands and processed them it will send back a command confirmation to the client, + and the client can then free up space in the buffer. + If you are using JMS and you're using the JMS service on the server to load your JMS + connection factory instances into JNDI then this parameter can be configured in hornetq-jms.xml using the element confirmation-window-size a. If you're using JMS but not using JNDI then + you can set these values directly on the HornetQConnectionFactory + instance using the appropriate setter method. + If you're using the core API you can set these values directly on the ServerLocator instance using the appropriate setter method. + The window is specified in bytes. + Setting this parameter to -1 disables any buffering and prevents + any re-attachment from occurring, forcing reconnect instead. The default value for this + parameter is -1. (Which means by default no auto re-attachment will occur) +
+
+ Session reconnection + Alternatively, the server might have actually been restarted after crashing or being + stopped. In this case any sessions will no longer be existent on the server and it won't + be possible to 100% transparently re-attach to them. + In this case, HornetQ will automatically reconnect the connection and recreate any sessions and consumers on the server + corresponding to the sessions and consumers on the client. This process is exactly the + same as what happens during failover onto a backup server. + Client reconnection is also used internally by components such as core bridges to + allow them to reconnect to their target servers. + Please see the section on failover to get a + full understanding of how transacted and non-transacted sessions are reconnected during + failover/reconnect and what you need to do to maintain once and + only once delivery guarantees. +
+
+ Configuring reconnection/reattachment attributes + Client reconnection is configured using the following parameters: + + + retry-interval. This optional parameter determines the + period in milliseconds between subsequent reconnection attempts, if the + connection to the target server has failed. The default value is 2000 milliseconds. + + + retry-interval-multiplier. This optional parameter + determines determines a multiplier to apply to the time since the last retry to + compute the time to the next retry. + This allows you to implement an exponential backoff + between retry attempts. + Let's take an example: + If we set retry-interval to 1000 ms and + we set retry-interval-multiplier to 2.0, + then, if the first reconnect attempt fails, we will wait 1000 + ms then 2000 ms then 4000 ms between + subsequent reconnection attempts. + The default value is 1.0 meaning each reconnect attempt is + spaced at equal intervals. + + + max-retry-interval. This optional parameter determines the + maximum retry interval that will be used. When setting retry-interval-multiplier it would otherwise be possible that + subsequent retries exponentially increase to ridiculously large values. By + setting this parameter you can set an upper limit on that value. The default + value is 2000 milliseconds. + + + reconnect-attempts. This optional parameter determines the + total number of reconnect attempts to make before giving up and shutting down. A + value of -1 signifies an unlimited number of attempts. The + default value is 0. + + + If you're using JMS, and you're using the JMS Service on the server to load your JMS + connection factory instances directly into JNDI, then you can specify these parameters + in the xml configuration in hornetq-jms.xml, for example: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + <entry name="XAConnectionFactory"/> + </entries> + <retry-interval>1000</retry-interval> + <retry-interval-multiplier>1.5</retry-interval-multiplier> + <max-retry-interval>60000</max-retry-interval> + <reconnect-attempts>1000</reconnect-attempts> +</connection-factory> + If you're using JMS, but instantiating your JMS connection factory directly, you can + specify the parameters using the appropriate setter methods on the HornetQConnectionFactory immediately after creating it. + If you're using the core API and instantiating the ServerLocator instance directly you can also specify the + parameters using the appropriate setter methods on the ServerLocator immediately after creating it. + If your client does manage to reconnect but the session is no longer available on the + server, for instance if the server has been restarted or it has timed out, then the + client won't be able to re-attach, and any ExceptionListener or + FailureListener instances registered on the connection or session + will be called. +
+
+ ExceptionListeners and SessionFailureListeners + Please note, that when a client reconnects or re-attaches, any registered JMS ExceptionListener or core API SessionFailureListener + will be called. +
+
diff --git a/docs/user-manual/en/clusters.xml b/docs/user-manual/en/clusters.xml new file mode 100644 index 0000000000..25e79b211f --- /dev/null +++ b/docs/user-manual/en/clusters.xml @@ -0,0 +1,998 @@ + + + + + + + + + + + + + + + + + + + + + %BOOK_ENTITIES; + ]> + + Clusters +
+ Clusters Overview + HornetQ clusters allow groups of HornetQ servers to be grouped together in order to + share message processing load. Each active node in the cluster is an active HornetQ + server which manages its own messages and handles its own connections. + + The clustered parameter is deprecated and no longer needed for + setting up a cluster. If your configuration contains this parameter it will be ignored and + a message with the ID HQ221038 will be logged. + + The cluster is formed by each node declaring cluster connections + to other nodes in the core configuration file hornetq-configuration.xml. When a node forms a cluster connection to + another node, internally it creates a core bridge (as described in + ) connection between it and the other node, this is + done transparently behind the scenes - you don't have to declare an explicit bridge for + each node. These cluster connections allow messages to flow between the nodes of the + cluster to balance load. + Nodes can be connected together to form a cluster in many different topologies, we + will discuss a couple of the more common topologies later in this chapter. + We'll also discuss client side load balancing, where we can balance client connections + across the nodes of the cluster, and we'll consider message redistribution where HornetQ + will redistribute messages between nodes to avoid starvation. + Another important part of clustering is server discovery where + servers can broadcast their connection details so clients or other servers can connect + to them with the minimum of configuration. + + Once a cluster node has been configured it is common to simply copy that configuration + to other nodes to produce a symmetric cluster. However, care must be taken when copying the + HornetQ files. Do not copy the HornetQ data (i.e. the + bindings, journal, and large-messages + directories) from one node to another. When a node is started for the first time and initializes + its journal files it also persists a special identifier to the journal + directory. This id must be unique among nodes in the cluster or the + cluster will not form properly. + +
+
+ Server discovery + Server discovery is a mechanism by which servers can propagate their connection details to: + + + + Messaging clients. A messaging client wants to be able to connect + to the servers of the cluster without having specific knowledge of which servers + in the cluster are up at any one time. + + + + Other servers. Servers in a cluster want to be able to create + cluster connections to each other without having prior knowledge of all the + other servers in the cluster. + + + + This information, let's call it the Cluster Topology, is actually sent around normal HornetQ + connections to clients and to other servers over cluster connections. This being the case we need a + way of establishing the initial first connection. This can be done using + dynamic discovery techniques like UDP + and JGroups, or by + providing a list of initial connectors. + +
+ Dynamic Discovery + + Server discovery uses UDP + multicast or JGroups to broadcast server connection settings. + +
+ Broadcast Groups + A broadcast group is the means by which a server broadcasts connectors over the + network. A connector defines a way in which a client (or other server) can make + connections to the server. For more information on what a connector is, please see + . + The broadcast group takes a set of connector pairs, each connector pair contains + connection settings for a live and backup server (if one exists) and broadcasts them on + the network. Depending on which broadcasting technique you configure the cluster, it + uses either UDP or JGroups to broadcast connector pairs information. + Broadcast groups are defined in the server configuration file hornetq-configuration.xml. There can be many broadcast groups per + HornetQ server. All broadcast groups must be defined in a broadcast-groups element. + Let's take a look at an example broadcast group from hornetq-configuration.xml that defines a UDP broadcast group: + +<broadcast-groups> + <broadcast-group name="my-broadcast-group"> + <local-bind-address>172.16.9.3</local-bind-address> + <local-bind-port>5432</local-bind-port> + <group-address>231.7.7.7</group-address> + <group-port>9876</group-port> + <broadcast-period>2000</broadcast-period> + <connector-ref connector-name="netty-connector"/> + </broadcast-group> +</broadcast-groups> + Some of the broadcast group parameters are optional and you'll normally use the + defaults, but we specify them all in the above example for clarity. Let's discuss + each one in turn: + + + name attribute. Each broadcast group in the server must + have a unique name. + + + local-bind-address. This is the local bind address that + the datagram socket is bound to. If you have multiple network interfaces on + your server, you would specify which one you wish to use for broadcasts by + setting this property. If this property is not specified then the socket + will be bound to the wildcard address, an IP address chosen by the + kernel. This is a UDP specific attribute. + + + local-bind-port. If you want to specify a local port to + which the datagram socket is bound you can specify it here. Normally you + would just use the default value of -1 which signifies + that an anonymous port should be used. This parameter is always specified in conjunction with + local-bind-address. This is a UDP specific attribute. + + + group-address. This is the multicast address to which + the data will be broadcast. It is a class D IP address in the range 224.0.0.0 to 239.255.255.255, inclusive. + The address 224.0.0.0 is reserved and is not available + for use. This parameter is mandatory. This is a UDP specific attribute. + + + group-port. This is the UDP port number used for + broadcasting. This parameter is mandatory. This is a UDP specific attribute. + + + broadcast-period. This is the period in milliseconds + between consecutive broadcasts. This parameter is optional, the default + value is 2000 milliseconds. + + + connector-ref. This specifies the connector and + optional backup connector that will be broadcasted (see for more information on connectors). + The connector to be broadcasted is specified by the connector-name attribute. + + + + Here is another example broadcast group that defines a JGroups broadcast group: + +<broadcast-groups> + <broadcast-group name="my-broadcast-group"> + <jgroups-file>test-jgroups-file_ping.xml</jgroups-file> + <jgroups-channel>hornetq_broadcast_channel</jgroups-channel> + <broadcast-period>2000</broadcast-period> + <connector-ref connector-name="netty-connector"/> + </broadcast-group> +</broadcast-groups> + To be able to use JGroups to broadcast, one must specify two attributes, i.e. + jgroups-file and jgroups-channel, as discussed + in details as following: + + + jgroups-file attribute. This is the name of JGroups configuration + file. It will be used to initialize JGroups channels. Make sure the file is in the + java resource path so that HornetQ can load it. + + + jgroups-channel attribute. The name that JGroups channels connect + to for broadcasting. + + + + The JGroups attributes (jgroups-file and jgroups-channel) + and UDP specific attributes described above are exclusive of each other. Only one set can be + specified in a broadcast group configuration. Don't mix them! + + + The following is an example of a JGroups file + +<config xmlns="urn:org:jgroups" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/JGroups-3.0.xsd"> + <TCP loopback="true" + recv_buf_size="20000000" + send_buf_size="640000" + discard_incompatible_packets="true" + max_bundle_size="64000" + max_bundle_timeout="30" + enable_bundling="true" + use_send_queues="false" + sock_conn_timeout="300" + + thread_pool.enabled="true" + thread_pool.min_threads="1" + thread_pool.max_threads="10" + thread_pool.keep_alive_time="5000" + thread_pool.queue_enabled="false" + thread_pool.queue_max_size="100" + thread_pool.rejection_policy="run" + + oob_thread_pool.enabled="true" + oob_thread_pool.min_threads="1" + oob_thread_pool.max_threads="8" + oob_thread_pool.keep_alive_time="5000" + oob_thread_pool.queue_enabled="false" + oob_thread_pool.queue_max_size="100" + oob_thread_pool.rejection_policy="run"/> + + <FILE_PING location="../file.ping.dir"/> + <MERGE2 max_interval="30000" + min_interval="10000"/> + <FD_SOCK/> + <FD timeout="10000" max_tries="5" /> + <VERIFY_SUSPECT timeout="1500" /> + <BARRIER /> + <pbcast.NAKACK + use_mcast_xmit="false" + retransmit_timeout="300,600,1200,2400,4800" + discard_delivered_msgs="true"/> + <UNICAST timeout="300,600,1200" /> + <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000" + max_bytes="400000"/> + <pbcast.GMS print_local_addr="true" join_timeout="3000" + view_bundling="true"/> + <FC max_credits="2000000" + min_threshold="0.10"/> + <FRAG2 frag_size="60000" /> + <pbcast.STATE_TRANSFER/> + <pbcast.FLUSH timeout="0"/> +</config> + + + As it shows, the file content defines a jgroups protocol stacks. If you want hornetq + to use this stacks for channel creation, you have to make sure the value of + jgroups-file in your broadcast-group/discovery-group configuration + to be the name of this jgroups configuration file. For example if the above stacks + configuration is stored in a file named "jgroups-stacks.xml" then your + jgroups-file should be like + +<jgroups-file>jgroups-stacks.xml</jgroups-file> + +
+
+ Discovery Groups + While the broadcast group defines how connector information is broadcasted from a + server, a discovery group defines how connector information is received from a + broadcast endpoint (a UDP multicast address or JGroup channel). + A discovery group maintains a list of connector pairs - one for each broadcast by + a different server. As it receives broadcasts on the broadcast endpoint from a + particular server it updates its entry in the list for that server. + If it has not received a broadcast from a particular server for a length of time + it will remove that server's entry from its list. + Discovery groups are used in two places in HornetQ: + + + By cluster connections so they know how to obtain an initial connection to download the topology + + + By messaging clients so they know how to obtain an initial connection to download the topology + + + + Although a discovery group will always accept broadcasts, its current list of available live and + backup servers is only ever used when an initial connection is made, from then server discovery is + done over the normal HornetQ connections. + + + + Each discovery group must be configured with broadcast endpoint (UDP or JGroups) that matches its broadcast + group counterpart. For example, if broadcast is configured using UDP, the discovery group must also use UDP, and the same + multicast address. + + +
+
+ Defining Discovery Groups on the Server + For cluster connections, discovery groups are defined in the server side + configuration file hornetq-configuration.xml. All discovery + groups must be defined inside a discovery-groups element. There + can be many discovery groups defined by HornetQ server. Let's look at an + example: + +<discovery-groups> + <discovery-group name="my-discovery-group"> + <local-bind-address>172.16.9.7</local-bind-address> + <group-address>231.7.7.7</group-address> + <group-port>9876</group-port> + <refresh-timeout>10000</refresh-timeout> + </discovery-group> +</discovery-groups> + We'll consider each parameter of the discovery group: + + + name attribute. Each discovery group must have a unique + name per server. + + + local-bind-address. If you are running with multiple network interfaces on the same machine, you + may want to specify that the discovery group listens only only a specific interface. To do this you can specify the interface + address with this parameter. This parameter is optional. This is a UDP specific attribute. + + + group-address. This is the multicast IP address of the + group to listen on. It should match the group-address in + the broadcast group that you wish to listen from. This parameter is + mandatory. This is a UDP specific attribute. + + + group-port. This is the UDP port of the multicast + group. It should match the group-port in the broadcast + group that you wish to listen from. This parameter is mandatory. This is a UDP specific attribute. + + + refresh-timeout. This is the period the discovery group + waits after receiving the last broadcast from a particular server before + removing that servers connector pair entry from its list. You would normally + set this to a value significantly higher than the broadcast-period on the broadcast group otherwise servers + might intermittently disappear from the list even though they are still + broadcasting due to slight differences in timing. This parameter is + optional, the default value is 10000 milliseconds (10 + seconds). + + + Here is another example that defines a JGroups discovery group: + +<discovery-groups> + <discovery-group name="my-broadcast-group"> + <jgroups-file>test-jgroups-file_ping.xml</jgroups-file> + <jgroups-channel>hornetq_broadcast_channel</jgroups-channel> + <refresh-timeout>10000</refresh-timeout> + </discovery-group> +</discovery-groups> + To receive broadcast from JGroups channels, one must specify two attributes, + jgroups-file and jgroups-channel, as discussed + in details as following: + + + jgroups-file attribute. This is the name of JGroups configuration + file. It will be used to initialize JGroups channels. Make sure the file is in the + java resource path so that HornetQ can load it. + + + jgroups-channel attribute. The name that JGroups channels connect + to for receiving broadcasts. + + + + The JGroups attributes (jgroups-file and jgroups-channel) + and UDP specific attributes described above are exclusive of each other. Only one set can be + specified in a discovery group configuration. Don't mix them! + +
+
+ Discovery Groups on the Client Side + Let's discuss how to configure a HornetQ client to use discovery to discover a + list of servers to which it can connect. The way to do this differs depending on + whether you're using JMS or the core API. +
+ Configuring client discovery using JMS + If you're using JMS and you're also using the JMS Service on the server to + load your JMS connection factory instances into JNDI, then you can specify which + discovery group to use for your JMS connection factory in the server side xml + configuration hornetq-jms.xml. Let's take a look at an + example: + +<connection-factory name="ConnectionFactory"> + <discovery-group-ref discovery-group-name="my-discovery-group"/> + <entries> + <entry name="ConnectionFactory"/> + </entries> +</connection-factory> + The element discovery-group-ref specifies the name of a + discovery group defined in hornetq-configuration.xml. + When this connection factory is downloaded from JNDI by a client application + and JMS connections are created from it, those connections will be load-balanced + across the list of servers that the discovery group maintains by listening on + the multicast address specified in the discovery group configuration. + If you're using JMS, but you're not using JNDI to lookup a connection factory + - you're instantiating the JMS connection factory directly then you can specify + the discovery group parameters directly when creating the JMS connection + factory. Here's an + example: + +final String groupAddress = "231.7.7.7"; + +final int groupPort = 9876; + +ConnectionFactory jmsConnectionFactory = +HornetQJMSClient.createConnectionFactory(new DiscoveryGroupConfiguration(groupAddress, groupPort, + new UDPBroadcastGroupConfiguration(groupAddress, groupPort, null, -1)), JMSFactoryType.CF); + +Connection jmsConnection1 = jmsConnectionFactory.createConnection(); + +Connection jmsConnection2 = jmsConnectionFactory.createConnection(); + The refresh-timeout can be set directly on the DiscoveryGroupConfiguration + by using the setter method setDiscoveryRefreshTimeout() if you + want to change the default value. + There is also a further parameter settable on the DiscoveryGroupConfiguration using the + setter method setDiscoveryInitialWaitTimeout(). If the connection + factory is used immediately after creation then it may not have had enough time + to received broadcasts from all the nodes in the cluster. On first usage, the + connection factory will make sure it waits this long since creation before + creating the first connection. The default value for this parameter is 10000 milliseconds. +
+
+ Configuring client discovery using Core + If you're using the core API to directly instantiate + ClientSessionFactory instances, then you can specify the + discovery group parameters directly when creating the session factory. Here's an + example: + +final String groupAddress = "231.7.7.7"; +final int groupPort = 9876; +ServerLocator factory = HornetQClient.createServerLocatorWithHA(new DiscoveryGroupConfiguration(groupAddress, groupPort, + new UDPBroadcastGroupConfiguration(groupAddress, groupPort, null, -1)))); +ClientSessionFactory factory = locator.createSessionFactory(); +ClientSession session1 = factory.createSession(); +ClientSession session2 = factory.createSession(); + The refresh-timeout can be set directly on the DiscoveryGroupConfiguration + by using the setter method setDiscoveryRefreshTimeout() if you + want to change the default value. + There is also a further parameter settable on the DiscoveryGroupConfiguration using the + setter method setDiscoveryInitialWaitTimeout(). If the session factory + is used immediately after creation then it may not have had enough time to + received broadcasts from all the nodes in the cluster. On first usage, the + session factory will make sure it waits this long since creation before creating + the first session. The default value for this parameter is 10000 milliseconds. +
+
+
+
+ Discovery using static Connectors + Sometimes it may be impossible to use UDP on the network you are using. In this case its + possible to configure a connection with an initial list if possible servers. This could be just + one server that you know will always be available or a list of servers where at least one will + be available. + This doesn't mean that you have to know where all your servers are going to be hosted, you + can configure these servers to use the reliable servers to connect to. Once they are connected + there connection details will be propagated via the server it connects to +
+ Configuring a Cluster Connection + For cluster connections there is no extra configuration needed, you just need to make sure that any + connectors are defined in the usual manner, (see for more + information on connectors). These are then referenced by the cluster connection configuration. +
+
+ Configuring a Client Connection + A static list of possible servers can also be used by a normal client. +
+ Configuring client discovery using JMS + If you're using JMS and you're also using the JMS Service on the server to + load your JMS connection factory instances into JNDI, then you can specify which + connectors to use for your JMS connection factory in the server side xml + configuration hornetq-jms.xml. Let's take a look at an + example: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + <connector-ref connector-name="netty-connector2"/> + <connector-ref connector-name="netty-connector3"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> +</connection-factory> + + The element connectors contains a list of pre defined connectors in the + hornetq-configuration.xml file. When this connection factory is downloaded + from JNDI by a client application and JMS connections are created from it, those connections will + be load-balanced across the list of servers defined by these connectors. + + + If you're using JMS, but you're not using JNDI to lookup a connection factory - you're instantiating + the JMS connection factory directly then you can specify the connector list directly when creating + the JMS connection factory. Here's an example: + + +HashMap<String, Object> map = new HashMap<String, Object>(); +map.put("host", "myhost"); +map.put("port", "5445"); +TransportConfiguration server1 = new TransportConfiguration(NettyConnectorFactory.class.getName(), map); +HashMap<String, Object> map2 = new HashMap<String, Object>(); +map2.put("host", "myhost2"); +map2.put("port", "5446"); +TransportConfiguration server2 = new TransportConfiguration(NettyConnectorFactory.class.getName(), map2); + +HornetQConnectionFactory cf = HornetQJMSClient.createConnectionFactoryWithHA(JMSFactoryType.CF, server1, server2); +
+
+ Configuring client discovery using Core + If you are using the core API then the same can be done as follows: + +HashMap<String, Object> map = new HashMap<String, Object>(); +map.put("host", "myhost"); +map.put("port", "5445"); +TransportConfiguration server1 = new TransportConfiguration(NettyConnectorFactory.class.getName(), map); +HashMap<String, Object> map2 = new HashMap<String, Object>(); +map2.put("host", "myhost2"); +map2.put("port", "5446"); +TransportConfiguration server2 = new TransportConfiguration(NettyConnectorFactory.class.getName(), map2); + +ServerLocator locator = HornetQClient.createServerLocatorWithHA(server1, server2); +ClientSessionFactory factory = locator.createSessionFactory(); +ClientSession session = factory.createSession(); +
+
+
+
+
+ Server-Side Message Load Balancing + If cluster connections are defined between nodes of a cluster, then HornetQ will load + balance messages arriving at a particular node from a client. + Let's take a simple example of a cluster of four nodes A, B, C, and D arranged in a + symmetric cluster (described in + ). We have a queue called OrderQueue + deployed on each node of the cluster. + We have client Ca connected to node A, sending orders to the server. We have also have + order processor clients Pa, Pb, Pc, and Pd connected to each of the nodes A, B, C, D. If + no cluster connection was defined on node A, then as order messages arrive on node A + they will all end up in the OrderQueue on node A, so will only get + consumed by the order processor client attached to node A, Pa. + If we define a cluster connection on node A, then as ordered messages arrive on node A + instead of all of them going into the local OrderQueue instance, they + are distributed in a round-robin fashion between all the nodes of the cluster. The + messages are forwarded from the receiving node to other nodes of the cluster. This is + all done on the server side, the client maintains a single connection to node A. + For example, messages arriving on node A might be distributed in the following order + between the nodes: B, D, C, A, B, D, C, A, B, D. The exact order depends on the order + the nodes started up, but the algorithm used is round robin. + HornetQ cluster connections can be configured to always blindly load balance messages + in a round robin fashion irrespective of whether there are any matching consumers on + other nodes, but they can be a bit cleverer than that and also be configured to only + distribute to other nodes if they have matching consumers. We'll look at both these + cases in turn with some examples, but first we'll discuss configuring cluster + connections in general. +
+ Configuring Cluster Connections + Cluster connections group servers into clusters so that messages can be load + balanced between the nodes of the cluster. Let's take a look at a typical cluster + connection. Cluster connections are always defined in hornetq-configuration.xml inside a cluster-connection element. There can be zero or more cluster + connections defined per HornetQ server. + +<cluster-connections> + <cluster-connection name="my-cluster"> + <address>jms</address> + <connector-ref>netty-connector</connector-ref> + <check-period>1000</check-period> + <connection-ttl>5000</connection-ttl> + <min-large-message-size>50000</min-large-message-size> + <call-timeout>5000</call-timeout> + <retry-interval>500</retry-interval> + <retry-interval-multiplier>1.0</retry-interval-multiplier> + <max-retry-interval>5000</max-retry-interval> + <initial-connect-attempts>-1</initial-connect-attempts> + <reconnect-attempts>-1</reconnect-attempts> + <use-duplicate-detection>true</use-duplicate-detection> + <forward-when-no-consumers>false</forward-when-no-consumers> + <max-hops>1</max-hops> + <confirmation-window-size>32000</confirmation-window-size> + <call-failover-timeout>30000</call-failover-timeout> + <notification-interval>1000</notification-interval> + <notification-attempts>2</notification-attempts> + <discovery-group-ref discovery-group-name="my-discovery-group"/> + </cluster-connection> +</cluster-connections> + In the above cluster connection all parameters have been explicitly specified. The following + shows all the available configuration options + + + address. Each cluster connection only applies to + messages sent to an address that starts with this value. Note: this does + not use wild-card matching. + In this case, this cluster connection will load balance messages sent to + address that start with jms. This cluster connection, + will, in effect apply to all JMS queues and topics since they map to core + queues that start with the substring "jms". + The address can be any value and you can have many cluster connections + with different values of address, simultaneously + balancing messages for those addresses, potentially to different clusters of + servers. By having multiple cluster connections on different addresses a + single HornetQ Server can effectively take part in multiple clusters + simultaneously. + Be careful not to have multiple cluster connections with overlapping + values of address, e.g. "europe" and "europe.news" since + this could result in the same messages being distributed between more than + one cluster connection, possibly resulting in duplicate deliveries. + This parameter is mandatory. + + + connector-ref. This is the connector which will be sent to other nodes in + the cluster so they have the correct cluster topology. + This parameter is mandatory. + + + check-period. The period (in milliseconds) used to check if the cluster connection + has failed to receive pings from another server. Default is 30000. + + + connection-ttl. This is how long a cluster connection should stay alive if it + stops receiving messages from a specific node in the cluster. Default is 60000. + + + min-large-message-size. If the message size (in bytes) is larger than this + value then it will be split into multiple segments when sent over the network to other cluster + members. Default is 102400. + + + call-timeout. When a packet is sent via a cluster connection and is a blocking + call, i.e. for acknowledgements, this is how long it will wait (in milliseconds) for the reply before + throwing an exception. Default is 30000. + + + retry-interval. We mentioned before that, internally, + cluster connections cause bridges to be created between the nodes of the + cluster. If the cluster connection is created and the target node has not + been started, or say, is being rebooted, then the cluster connections from + other nodes will retry connecting to the target until it comes back up, in + the same way as a bridge does. + This parameter determines the interval in milliseconds between retry + attempts. It has the same meaning as the retry-interval + on a bridge (as described in ). + This parameter is optional and its default value is 500 + milliseconds. + + + retry-interval-multiplier. This is a multiplier used to increase the + retry-interval after each reconnect attempt, default is 1. + + + max-retry-interval. The maximum delay (in milliseconds) for retries. + Default is 2000. + + + initial-connect-attempts. The number of times the system will + try to connect a node in the cluster initially. If the max-retry is achieved this + node will be considered permanently down and the system will not route messages + to this node. Default is -1 (infinite retries). + + + reconnect-attempts. The number of times the system will + try to reconnect to a node in the cluster. If the max-retry is achieved this node will + be considered permanently down and the system will stop routing messages to this + node. Default is -1 (infinite retries). + + + use-duplicate-detection. Internally cluster connections + use bridges to link the nodes, and bridges can be configured to add a + duplicate id property in each message that is forwarded. If the target node + of the bridge crashes and then recovers, messages might be resent from the + source node. By enabling duplicate detection any duplicate messages will be + filtered out and ignored on receipt at the target node. + This parameter has the same meaning as use-duplicate-detection + on a bridge. For more information on duplicate detection, please see + . Default is true. + + + forward-when-no-consumers. This parameter determines + whether messages will be distributed round robin between other nodes of the + cluster regardless of whether or not there are matching or + indeed any consumers on other nodes. + If this is set to true then each incoming message will + be round robin'd even though the same queues on the other nodes of the + cluster may have no consumers at all, or they may have consumers that have + non matching message filters (selectors). Note that HornetQ will + not forward messages to other nodes if there are no + queues of the same name on the other nodes, even if + this parameter is set to true. + If this is set to false then HornetQ will only forward + messages to other nodes of the cluster if the address to which they are + being forwarded has queues which have consumers, and if those consumers have + message filters (selectors) at least one of those selectors must match the + message. + Default is false. + + + max-hops. When a cluster connection decides the set of + nodes to which it might load balance a message, those nodes do not have to + be directly connected to it via a cluster connection. HornetQ can be + configured to also load balance messages to nodes which might be connected + to it only indirectly with other HornetQ servers as intermediates in a + chain. + This allows HornetQ to be configured in more complex topologies and still + provide message load balancing. We'll discuss this more later in this + chapter. + The default value for this parameter is 1, which means + messages are only load balanced to other HornetQ serves which are directly + connected to this server. This parameter is optional. + + + confirmation-window-size. The size (in bytes) of the window + used for sending confirmations from the server connected to. So once the server has + received confirmation-window-size bytes it notifies its client, + default is 1048576. A value of -1 means no window. + + + call-failover-timeout. Similar to call-timeout but used + when a call is made during a failover attempt. Default is -1 (no timeout). + + + notification-interval. How often (in milliseconds) the cluster connection + should broadcast itself when attaching to the cluster. Default is 1000. + + + notification-attempts. How many times the cluster connection should + broadcast itself when connecting to the cluster. Default is 2. + + + discovery-group-ref. This parameter determines which + discovery group is used to obtain the list of other servers in the cluster + that this cluster connection will make connections to. + + + + Alternatively if you would like your cluster connections to use a static list of + servers for discovery then you can do it like this. + + +<cluster-connection name="my-cluster"> + ... + <static-connectors> + <connector-ref>server0-connector</connector-ref> + <connector-ref>server1-connector</connector-ref> + </static-connectors> +</cluster-connection> + + Here we have defined 2 servers that we know for sure will that at least one will be available. There may + be many more servers in the cluster but these will; be discovered via one of these connectors once an + initial connection has been made. +
+
+ Cluster User Credentials + When creating connections between nodes of a cluster to form a cluster connection, + HornetQ uses a cluster user and cluster password which is defined in hornetq-configuration.xml: + +<cluster-user>HORNETQ.CLUSTER.ADMIN.USER</cluster-user> +<cluster-password>CHANGE ME!!</cluster-password> + + It is imperative that these values are changed from their default, or remote + clients will be able to make connections to the server using the default values. + If they are not changed from the default, HornetQ will detect this and pester + you with a warning on every start-up. + +
+
+
+ Client-Side Load balancing + With HornetQ client-side load balancing, subsequent sessions created using a single + session factory can be connected to different nodes of the cluster. This allows sessions + to spread smoothly across the nodes of a cluster and not be "clumped" on any particular + node. + The load balancing policy to be used by the client factory is configurable. HornetQ + provides four out-of-the-box load balancing policies, and you can also implement your own + and use that. + The out-of-the-box policies are + + + Round Robin. With this policy the first node is chosen randomly then each + subsequent node is chosen sequentially in the same order. + For example nodes might be chosen in the order B, C, D, A, B, C, D, A, B or D, + A, B, C, D, A, B, C, D or C, D, A, B, C, D, A, B, C. + Use org.hornetq.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy + as the <connection-load-balancing-policy-class-name>. + + + Random. With this policy each node is chosen randomly. + Use org.hornetq.api.core.client.loadbalance.RandomConnectionLoadBalancingPolicy + as the <connection-load-balancing-policy-class-name>. + + + Random Sticky. With this policy the first node is chosen randomly and then re-used for subsequent + connections. + Use org.hornetq.api.core.client.loadbalance.RandomStickyConnectionLoadBalancingPolicy + as the <connection-load-balancing-policy-class-name>. + + + First Element. With this policy the "first" (i.e. 0th) node is always returned. + Use org.hornetq.api.core.client.loadbalance.FirstElementConnectionLoadBalancingPolicy + as the <connection-load-balancing-policy-class-name>. + + + You can also implement your own policy by implementing the interface org.hornetq.api.core.client.loadbalance.ConnectionLoadBalancingPolicy + Specifying which load balancing policy to use differs whether you are using JMS or the + core API. If you don't specify a policy then the default will be used which is org.hornetq.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy. + If you're using JMS, and you're using JNDI on the server to put your JMS connection + factories into JNDI, then you can specify the load balancing policy directly in the + hornetq-jms.xml configuration file on the server as follows: + +<connection-factory name="ConnectionFactory"> + <discovery-group-ref discovery-group-name="my-discovery-group"/> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <connection-load-balancing-policy-class-name> + org.hornetq.api.core.client.loadbalance.RandomConnectionLoadBalancingPolicy + </connection-load-balancing-policy-class-name> +</connection-factory> + The above example would deploy a JMS connection factory that uses the random connection load + balancing policy. + If you're using JMS but you're instantiating your connection factory directly on the + client side then you can set the load balancing policy using the setter on the + HornetQConnectionFactory before using it: + +ConnectionFactory jmsConnectionFactory = HornetQJMSClient.createConnectionFactory(...); +jmsConnectionFactory.setLoadBalancingPolicyClassName("com.acme.MyLoadBalancingPolicy"); + If you're using the core API, you can set the load balancing policy directly on the + ServerLocator instance you are using: + +ServerLocator locator = HornetQClient.createServerLocatorWithHA(server1, server2); +locator.setLoadBalancingPolicyClassName("com.acme.MyLoadBalancingPolicy"); + The set of servers over which the factory load balances can be determined in one of + two ways: + + + Specifying servers explicitly + + + Using discovery. + + +
+
+ Specifying Members of a Cluster Explicitly + + Sometimes you want to explicitly define a cluster more explicitly, that is control which + server connect to each other in the cluster. This is typically used to form non symmetrical clusters + such as chain cluster or ring clusters. This can only be done using a static list of connectors and is + configured as follows: + + +<cluster-connection name="my-cluster"> + <address>jms</address> + <connector-ref>netty-connector</connector-ref> + <retry-interval>500</retry-interval> + <use-duplicate-detection>true</use-duplicate-detection> + <forward-when-no-consumers>true</forward-when-no-consumers> + <max-hops>1</max-hops> + <static-connectors allow-direct-connections-only="true"> + <connector-ref>server1-connector</connector-ref> + </static-connectors> +</cluster-connection> + + In this example we have set the attribute allow-direct-connections-only which means that + the only server that this server can create a cluster connection to is server1-connector. This means you can + explicitly create any cluster topology you want. + +
+
+ Message Redistribution + Another important part of clustering is message redistribution. Earlier we learned how + server side message load balancing round robins messages across the cluster. If forward-when-no-consumers is false, then messages won't be forwarded to + nodes which don't have matching consumers, this is great and ensures that messages don't + arrive on a queue which has no consumers to consume them, however there is a situation + it doesn't solve: What happens if the consumers on a queue close after the messages have + been sent to the node? If there are no consumers on the queue the message won't get + consumed and we have a starvation situation. + This is where message redistribution comes in. With message redistribution HornetQ can + be configured to automatically redistribute messages from queues + which have no consumers back to other nodes in the cluster which do have matching + consumers. + Message redistribution can be configured to kick in immediately after the last + consumer on a queue is closed, or to wait a configurable delay after the last consumer + on a queue is closed before redistributing. By default message redistribution is + disabled. + Message redistribution can be configured on a per address basis, by specifying the + redistribution delay in the address settings, for more information on configuring + address settings, please see . + Here's an address settings snippet from hornetq-configuration.xml + showing how message redistribution is enabled for a set of queues: + +<address-settings> + <address-setting match="jms.#"> + <redistribution-delay>0</redistribution-delay> + </address-setting> +</address-settings> + The above address-settings block would set a redistribution-delay of 0 for any queue which is bound + to an address that starts with "jms.". All JMS queues and topic subscriptions are bound + to addresses that start with "jms.", so the above would enable instant (no delay) + redistribution for all JMS queues and topic subscriptions. + The attribute match can be an exact match or it can be a string + that conforms to the HornetQ wildcard syntax (described in ). + The element redistribution-delay defines the delay in milliseconds + after the last consumer is closed on a queue before redistributing messages from that + queue to other nodes of the cluster which do have matching consumers. A delay of zero + means the messages will be immediately redistributed. A value of -1 + signifies that messages will never be redistributed. The default value is -1. + It often makes sense to introduce a delay before redistributing as it's a common case + that a consumer closes but another one quickly is created on the same queue, in such a + case you probably don't want to redistribute immediately since the new consumer will + arrive shortly. +
+
+ Cluster topologies + HornetQ clusters can be connected together in many different topologies, let's + consider the two most common ones here +
+ Symmetric cluster + A symmetric cluster is probably the most common cluster topology, and you'll be + familiar with if you've had experience of JBoss Application Server + clustering. + With a symmetric cluster every node in the cluster is connected to every other + node in the cluster. In other words every node in the cluster is no more than one + hop away from every other node. + To form a symmetric cluster every node in the cluster defines a cluster connection + with the attribute max-hops set to 1. + Typically the cluster connection will use server discovery in order to know what + other servers in the cluster it should connect to, although it is possible to + explicitly define each target server too in the cluster connection if, for example, + UDP is not available on your network. + With a symmetric cluster each node knows about all the queues that exist on all + the other nodes and what consumers they have. With this knowledge it can determine + how to load balance and redistribute messages around the nodes. + Don't forget this warning when creating a + symmetric cluster. +
+
+ Chain cluster + With a chain cluster, each node in the cluster is not connected to every node in + the cluster directly, instead the nodes form a chain with a node on each end of the + chain and all other nodes just connecting to the previous and next nodes in the + chain. + An example of this would be a three node chain consisting of nodes A, B and C. + Node A is hosted in one network and has many producer clients connected to it + sending order messages. Due to corporate policy, the order consumer clients need to + be hosted in a different network, and that network is only accessible via a third + network. In this setup node B acts as a mediator with no producers or consumers on + it. Any messages arriving on node A will be forwarded to node B, which will in turn + forward them to node C where they can get consumed. Node A does not need to directly + connect to C, but all the nodes can still act as a part of the cluster. + To set up a cluster in this way, node A would define a cluster connection that + connects to node B, and node B would define a cluster connection that connects to + node C. In this case we only want cluster connections in one direction since we're + only moving messages from node A->B->C and never from C->B->A. + For this topology we would set max-hops to 2. With a value of 2 the knowledge of what queues and + consumers that exist on node C would be propagated from node C to node B to node A. + Node A would then know to distribute messages to node B when they arrive, even + though node B has no consumers itself, it would know that a further hop away is node + C which does have consumers. +
+
+
+ Scaling Down + HornetQ supports scaling down a cluster with no message loss (even for non-durable messages). This is especially + useful in certain environments (e.g. the cloud) where the size of a cluster may change relatively frequently. + When scaling up a cluster (i.e. adding nodes) there is no risk of message loss, but when scaling down a cluster + (i.e. removing nodes) the messages on those nodes would be lost unless the broker sent them to another node in + the cluster. HornetQ can be configured to do just that. + The simplest way to enable this behavior is to set scale-down to + true. If the server is clustered and scale-down is + true then when the server is shutdown gracefully (i.e. stopped without crashing) it will find + another node in the cluster and send all of its messages (both durable and non-durable) + to that node. The messages are processed in order and go to the back of the respective + queues on the other node (just as if the messages were sent from an external client for the first time). + If more control over where the messages go is required then specify scale-down-group-name. + Messages will only be sent to another node in the cluster that uses the same scale-down-group-name + as the server being shutdown. + + If cluster nodes are grouped together with different scale-down-group-name values beware. + If all the nodes in a single group are shut down then the messages from that node/group will be lost. + + If the server is using multiple cluster-connection then use scale-down-clustername + to identify the name of the cluster-connection which should be used for scaling down. +
+
diff --git a/docs/user-manual/en/configuration-index.xml b/docs/user-manual/en/configuration-index.xml new file mode 100644 index 0000000000..b3cc162105 --- /dev/null +++ b/docs/user-manual/en/configuration-index.xml @@ -0,0 +1,705 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Configuration Reference + This section is a quick index for looking up configuration. Click on the element name to + go to the specific chapter. +
+ Server Configuration +
+ hornetq-configuration.xml + This is the main core server configuration file. + + Server Configuration + + + + + + + + Element Name + Element Type + Description + Default + + + + + +
+
+
+ hornetq-jms.xml + This is the configuration file used by the server side JMS service to load JMS + Queues, Topics and Connection Factories. + + JMS Server Configuration + + + + + + + + Element Name + Element Type + Description + Default + + + + + + connection-factory + + ConnectionFactory + a list of connection factories to create and add to JNDI + + + + +
+ + + Continued.. + + + + + + + + + + connection-factory.signature (attribute) + + String + Type of connection factory + generic + + + + connection-factory.xa + + Boolean + If it is a XA connection factory + false + + + + connection-factory.auto-group + + Boolean + whether or not message grouping is automatically used + false + + + connection-factory.connectors + + String + A list of connectors used by the connection factory + + + + connection-factory.connectors.connector-ref.connector-name (attribute) + + String + Name of the connector to connect to the live server + + + + connection-factory.discovery-group-ref.discovery-group-name (attribute) + + String + Name of discovery group used by this connection factory + + + + + + connection-factory.discovery-initial-wait-timeout + + Long + the initial time to wait (in ms) for discovery groups to wait for + broadcasts + 10000 + + + + connection-factory.block-on-acknowledge + + Boolean + whether or not messages are acknowledged synchronously + false + + + + connection-factory.block-on-non-durable-send + + Boolean + whether or not non-durable messages are sent synchronously + false + + + + connection-factory.block-on-durable-send + + Boolean + whether or not durable messages are sent synchronously + true + + + connection-factory.call-timeout + Long + the timeout (in ms) for remote calls + 30000 + + + + connection-factory.client-failure-check-period + + Long + the period (in ms) after which the client will consider the + connection failed after not receiving packets from the + server + 30000 + + + + connection-factory.client-id + + String + the pre-configured client ID for the connection factory + null + + + + + connection-factory.connection-load-balancing-policy-class-name + + String + the name of the load balancing class + org.hornetq.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy + + + + connection-factory.connection-ttl + + Long + the time to live (in ms) for connections + 1 * 60000 + + + + connection-factory.consumer-max-rate + Integer + the fastest rate a consumer may consume messages per + second + -1 + + + + connection-factory.consumer-window-size + Integer + the window size (in bytes) for consumer flow control + 1024 * 1024 + + + + connection-factory.dups-ok-batch-size + Integer + the batch size (in bytes) between acknowledgements when using + DUPS_OK_ACKNOWLEDGE mode + 1024 * 1024 + + + connection-factory.failover-on-initial-connection + Boolean + whether or not to failover to backup on event that initial connection to live server fails + false + + + + connection-factory.failover-on-server-shutdown + Boolean + whether or not to failover on server shutdown + false + + + + connection-factory.min-large-message-size + Integer + the size (in bytes) before a message is treated as large + 100 * 1024 + + + + connection-factory.avoid-large-messages + Boolean + If compress large messages and send them as regular messages if possible + false + + + connection-factory.cache-large-message-client + Boolean + If true clients using this connection factory will hold the large + message body on temporary files. + false + + + + connection-factory.pre-acknowledge + Boolean + whether messages are pre acknowledged by the server before + sending + false + + + + connection-factory.producer-max-rate + Integer + the maximum rate of messages per second that can be sent + -1 + + + connection-factory.producer-window-size + Integer + the window size in bytes for producers sending messages + 1024 * 1024 + + + + connection-factory.confirmation-window-size + + Integer + the window size (in bytes) for reattachment confirmations + 1024 * 1024 + + + + connection-factory.reconnect-attempts + + Integer + maximum number of retry attempts, -1 signifies infinite + 0 + + + + connection-factory.retry-interval + + Long + the time (in ms) to retry a connection after failing + 2000 + + + + connection-factory.retry-interval-multiplier + + Double + multiplier to apply to successive retry intervals + 1.0 + + + connection-factory.max-retry-interval + Integer + The maximum retry interval in the case a retry-interval-multiplier has been specified + 2000 + + + + connection-factory.scheduled-thread-pool-max-size + + Integer + the size of the scheduled thread pool + 5 + + + + connection-factory.thread-pool-max-size + + Integer + the size of the thread pool + -1 + + + + + connection-factory.transaction-batch-size + + Integer + the batch size (in bytes) between acknowledgements when using a + transactional session + 1024 * 1024 + + + + connection-factory.use-global-pools + + Boolean + whether or not to use a global thread pool for threads + true + + + queue + Queue + a queue to create and add to JNDI + + + + queue.name + (attribute) + String + unique name of the queue + + + + queue.entry + String + context where the queue will be bound in JNDI (there can be + many) + + + + queue.durable + Boolean + is the queue durable? + true + + + queue.filter + String + optional filter expression for the queue + + + + topic + Topic + a topic to create and add to JNDI + + + + topic.name + (attribute) + String + unique name of the topic + + + + topic.entry + String + context where the topic will be bound in JNDI (there can be + many) + + + + + +
+ +
+ Using Masked Passwords in Configuration Files + By default all passwords in HornetQ server's configuration files are in plain text form. This usually poses no security issues as those + files should be well protected from unauthorized accessing. However, in some circumstances a user doesn't want to expose its passwords to more + eyes than necessary. + + HornetQ can be configured to use 'masked' passwords in its configuration files. A masked password is an obscure string representation + of a real password. To mask a password a user will use an 'encoder'. The encoder takes in the real password and outputs the masked version. + A user can then replace the real password in the configuration files with the new masked password. + When HornetQ loads a masked password, it uses a suitable 'decoder' to decode it into real password. + + HornetQ provides a default password encoder and decoder. Optionally users can use or implement their own encoder and decoder for + masking the passwords. + +
Password Masking in Server Configuration File + +
The password masking property + + The server configuration file has a property that defines the default masking behaviors over the entire file scope. + + mask-password: this boolean type property indicates if a password should be masked or not. Set it to "true" + if you want your passwords masked. The default value is "false". +
+ +
Specific masking behaviors + +
cluster-password + + The nature of the value of cluster-password is subject to the value of property 'mask-password'. If it is true + the cluster-password is masked. +
+ +
Passwords in connectors and acceptors + + In the server configuration, Connectors and Acceptors sometimes needs to specify passwords. For example + if a users wants to use an SSL-enabled NettyAcceptor, it can specify a key-store-password and a trust-store-password. Because + Acceptors and Connectors are pluggable implementations, each transport will have different password masking needs. + + When a Connector or Acceptor configuration is initialised, HornetQ will add the "mask-password" and + "password-codec" values to the Connector or Acceptors params using the keys hornetq.usemaskedpassword + and hornetq.passwordcodec respectively. The Netty and InVM implementations will use these + as needed and any other implementations will have access to these to use if they so wish. +
+ +
Passwords in Core Bridge configurations + + Core Bridges are configured in the server configuration file and so the masking of its 'password' properties + follows the same rules as that of 'cluster-password'. +
+
+ +
Examples + + The following table summarizes the relations among the above-mentioned properties + + + + + + + + + + mask-password + cluster-password + acceptor/connector passwords + bridge password + + + + + absent + plain text + plain text + plain text + + + false + plain text + plain text + plain text + + + true + masked + masked + masked + + + +
+ +Examples + +Note: In the following examples if related attributed or properties are absent, it means they are not specified in the configure file. + +example 1 + + +<cluster-password>bbc</cluster-password> + +This indicates the cluster password is a plain text value ("bbc"). + +example 2 + + +<mask-password>true</mask-password> +<cluster-password>80cf731af62c290</cluster-password> + + This indicates the cluster password is a masked value and HornetQ will use its built-in decoder to decode it. All other + passwords in the configuration file, Connectors, Acceptors and Bridges, will also use masked passwords. +
+
+ +
JMS Bridge password masking + + The JMS Bridges are configured and deployed as separate beans so they need separate configuration to control the password masking. + A JMS Bridge has two password parameters in its constructor, SourcePassword and TargetPassword. It uses the following two optional + properties to control their masking: + + useMaskedPassword -- If set to "true" the passwords are masked. Default is false. + passwordCodec -- Class name and its parameters for the Decoder used to decode the masked password. Ignored if + useMaskedPassword is false. The format of this property is a full qualified class name optionally followed by key/value pairs, + separated by semi-colons. For example: + + +<property name="useMaskedPassword">true</property> + + +<property name="passwordCodec">com.foo.FooDecoder;key=value</property> + + HornetQ will load this property and initialize the class with a parameter map containing the "key"->"value" pair. + If passwordCodec is not specified, the built-in decoder is used. + +
+ +
Masking passwords in HornetQ ResourceAdapters and MDB activation configurations + + Both ra.xml and MDB activation configuration have a 'password' property that can be masked. They are controlled by the following two + optional Resource Adapter properties in ra.xml: + + UseMaskedPassword -- If setting to "true" the passwords are masked. Default is false. + PasswordCodec -- Class name and its parameters for the Decoder used to decode the masked password. + Ignored if UseMaskedPassword is false. The format of this property is a full qualified class name optionally followed by key/value pairs. + It is the same format as that for JMS Bridges. Example: + + +<config-property> + <config-property-name>UseMaskedPassword</config-property-name> + <config-property-type>boolean</config-property-type> + <config-property-value>true</config-property-value> +</config-property> +<config-property> + <config-property-name>PasswordCodec</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>com.foo.ADecoder;key=helloworld</config-property-value> +</config-property> + + With this configuration, both passwords in ra.xml and all of its MDBs will have to be in masked form. + +
+ +
Masking passwords in hornetq-users.xml + + HornetQ's built-in security manager uses plain configuration files where the user passwords are specified in plaintext + forms by default. To mask those parameters the following two properties are needed: + + mask-password -- If set to "true" all the passwords are masked. Default is false. + password-codec -- Class name and its parameters for the Decoder used to decode the masked password. + Ignored if mask-password is false. The format of this property is a full qualified class name optionally + followed by key/value pairs. It is the same format as that for JMS Bridges. Example: + + +<mask-password>true</mask-password> +<password-codec>org.hornetq.utils.DefaultSensitiveStringCodec;key=hello world</password-codec> + + When so configured, the HornetQ security manager will initialize a DefaultSensitiveStringCodec with the parameters + "key"->"hello world", then use it to decode all the masked passwords in this configuration file. + +
+ +
Choosing a decoder for password masking + + As described in the previous sections, all password masking requires a decoder. A decoder uses an algorithm to + convert a masked password into its original clear text form in order to be used in various security operations. The algorithm + used for decoding must match that for encoding. Otherwise the decoding may not be successful. + + For user's convenience HornetQ provides a default built-in Decoder. However a user can if they so wish implement their own. + +
The built-in Decoder + + Whenever no decoder is specified in the configuration file, the built-in decoder is used. The class name for the built-in + decoder is org.hornetq.utils.DefaultSensitiveStringCodec. It has both encoding and decoding capabilities. It uses java.crypto.Cipher + utilities to encrypt (encode) a plaintext password and decrypt a mask string using same algorithm. Using this decoder/encoder is + pretty straightforward. To get a mask for a password, just run the following in command line: + + +java org.hornetq.utils.DefaultSensitiveStringCodec "your plaintext password" + + Make sure the classpath is correct. You'll get something like + + +Encoded password: 80cf731af62c290 + + Just copy "80cf731af62c290" and replace your plaintext password with it. +
+ +
Using a different decoder + + It is possible to use a different decoder rather than the built-in one. Simply make sure the decoder + is in HornetQ's classpath and configure the server to use it as follows: + + +<password-codec>com.foo.SomeDecoder;key1=value1;key2=value2</password-codec> + + If your decoder needs params passed to it you can do this via key/value pairs when configuring. + For instance if your decoder needs say a "key-location" parameter, you can define like so: + + +<password-codec>com.foo.NewDecoder;key-location=/some/url/to/keyfile</password-codec> + + Then configure your cluster-password like this: + + +<mask-password>true</mask-password> +<cluster-password>masked_password</cluster-password> + + When HornetQ reads the cluster-password it will initialize the NewDecoder and use it to decode "mask_password". + It also process all passwords using the new defined decoder. +
+ +
Implementing your own codecs + + To use a different decoder than the built-in one, you either pick one from existing libraries or you implement it yourself. + All decoders must implement the org.hornetq.utils.SensitiveDataCodec<T> interface: + + +public interface SensitiveDataCodec<T> +{ + T decode(Object mask) throws Exception; + + void init(Map<String, String> params); +} + + This is a generic type interface but normally for a password you just need String type. + So a new decoder would be defined like + + +public class MyNewDecoder implements SensitiveDataCodec<String> +{ + public String decode(Object mask) throws Exception + { + //decode the mask into clear text password + return "the password"; + } + + public void init(Map<String, String> params) + { + //initialization done here. It is called right after the decoder has been created. + } +} + + Last but not least, once you get your own decoder, please add it to the classpath. Otherwise HornetQ will + fail to load it! +
+
+
+
+
diff --git a/docs/user-manual/en/configuring-transports.xml b/docs/user-manual/en/configuring-transports.xml new file mode 100644 index 0000000000..066e783834 --- /dev/null +++ b/docs/user-manual/en/configuring-transports.xml @@ -0,0 +1,453 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Configuring the Transport + HornetQ has a fully pluggable and highly flexible transport layer and defines its own + Service Provider Interface (SPI) to make plugging in a new transport provider relatively + straightforward. + In this chapter we'll describe the concepts required for understanding HornetQ transports + and where and how they're configured. +
+ Understanding Acceptors + One of the most important concepts in HornetQ transports is the + acceptor. Let's dive straight in and take a look at an acceptor + defined in xml in the configuration file hornetq-configuration.xml. + +<acceptors> + <acceptor name="netty"> + <factory-class> + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + </factory-class> + <param key="port" value="5446"/> + </acceptor> +</acceptors> + Acceptors are always defined inside an acceptors element. There can + be one or more acceptors defined in the acceptors element. There's no + upper limit to the number of acceptors per server. + Each acceptor defines a way in which connections can be made to the HornetQ + server. + In the above example we're defining an acceptor that uses Netty to listen for connections at port + 5446. + The acceptor element contains a sub-element factory-class, this element defines the factory used to create acceptor + instances. In this case we're using Netty to listen for connections so we use the Netty + implementation of an AcceptorFactory to do this. Basically, the + factory-class element determines which pluggable transport we're + going to use to do the actual listening. + The acceptor element can also be configured with zero or more + param sub-elements. Each param element defines + a key-value pair. These key-value pairs are used to configure the specific transport, + the set of valid key-value pairs depends on the specific transport be used and are + passed straight through to the underlying transport. + Examples of key-value pairs for a particular transport would be, say, to configure the + IP address to bind to, or the port to listen at. + Note that unlike versions before 2.4 an Acceptor can now support multiple protocols. By default this will + be all available protocols but can be limited by either the now deprecated protocol param or + by setting a comma seperated list to the newly added protocols parameter. +
+
+ Understanding Connectors + Whereas acceptors are used on the server to define how we accept connections, + connectors are used by a client to define how it connects to a server. + Let's look at a connector defined in our hornetq-configuration.xml + file: + +<connectors> + <connector name="netty"> + <factory-class> + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + </factory-class> + <param key="port" value="5446"/> + </connector> +</connectors> + Connectors can be defined inside a connectors element. There can be + one or more connectors defined in the connectors element. There's no + upper limit to the number of connectors per server. + You make ask yourself, if connectors are used by the client to + make connections then why are they defined on the server? There are + a couple of reasons for this: + + + Sometimes the server acts as a client itself when it connects to another + server, for example when one server is bridged to another, or when a server + takes part in a cluster. In this cases the server needs to know how to connect + to other servers. That's defined by connectors. + + + If you're using JMS and the server side JMS service to instantiate JMS + ConnectionFactory instances and bind them in JNDI, then when creating the + HornetQConnectionFactory it needs to know what server + that connection factory will create connections to. + That's defined by the connector-ref element in the hornetq-jms.xml file on the server side. Let's take a look at a + snipped from a hornetq-jms.xml file that shows a JMS + connection factory that references our netty connector defined in our hornetq-configuration.xml file: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + <entry name="XAConnectionFactory"/> + </entries> +</connection-factory> + + +
+
+ Configuring the transport directly from the client side. + How do we configure a core ClientSessionFactory with the + information that it needs to connect with a server? + Connectors are also used indirectly when directly configuring a core ClientSessionFactory to directly talk to a server. Although in this case + there's no need to define such a connector in the server side configuration, instead we + just create the parameters and tell the ClientSessionFactory which + connector factory to use. + Here's an example of creating a ClientSessionFactory which will + connect directly to the acceptor we defined earlier in this chapter, it uses the + standard Netty TCP transport and will try and connect on port 5446 to localhost + (default): + +Map<String, Object> connectionParams = new HashMap<String, Object>(); + +connectionParams.put(org.hornetq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, + 5446); + +TransportConfiguration transportConfiguration = + new TransportConfiguration( + "org.hornetq.core.remoting.impl.netty.NettyConnectorFactory", + connectionParams); + +ServerLocator locator = HornetQClient.createServerLocatorWithoutHA(transportConfiguration); + +ClientSessionFactory sessionFactory = locator.createClientSessionFactory(); + +ClientSession session = sessionFactory.createSession(...); + +etc + Similarly, if you're using JMS, you can configure the JMS connection factory directly + on the client side without having to define a connector on the server side or define a + connection factory in hornetq-jms.xml: + +Map<String, Object> connectionParams = new HashMap<String, Object>(); + +connectionParams.put(org.hornetq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, 5446); + +TransportConfiguration transportConfiguration = + new TransportConfiguration( + "org.hornetq.core.remoting.impl.netty.NettyConnectorFactory", + connectionParams); + +ConnectionFactory connectionFactory = HornetQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration); + +Connection jmsConnection = connectionFactory.createConnection(); + +etc +
+
+ Configuring the Netty transport + Out of the box, HornetQ currently uses Netty, a high performance low level network library. + Our Netty transport can be configured in several different ways; to use old (blocking) + Java IO, or NIO (non-blocking), also to use straightforward TCP sockets, SSL, or to + tunnel over HTTP or HTTPS.. + We believe this caters for the vast majority of transport requirements. +
+ Single Port Support + As of version 2.4 HornetQ now supports using a single port for all protocols, HornetQ will automatically + detect which protocol is being used CORE, AMQP or STOMP and use the appropriate HornetQ handler. It will also detect + whether protocols such as HTTP or Web Sockets are being used and also use the appropriate decoders + It is possible to limit which protocols are supported by using the protocols parameter + on the Acceptor like so: + + <param key="protocols" value="CORE,AMQP"/> + + The protocol parameter is now deprecated +
+
+ Configuring Netty TCP + Netty TCP is a simple unencrypted TCP sockets based transport. Netty TCP can be + configured to use old blocking Java IO or non blocking Java NIO. We recommend you + use the Java NIO on the server side for better scalability with many concurrent + connections. However using Java old IO can sometimes give you better latency than + NIO when you're not so worried about supporting many thousands of concurrent + connections. + If you're running connections across an untrusted network please bear in mind this + transport is unencrypted. You may want to look at the SSL or HTTPS + configurations. + With the Netty TCP transport all connections are initiated from the client side. + I.e. the server does not initiate any connections to the client. This works well + with firewall policies that typically only allow connections to be initiated in one + direction. + All the valid Netty transport keys are defined in the class org.hornetq.core.remoting.impl.netty.TransportConstants. Most + parameters can be used either with acceptors or connectors, some only work with + acceptors. The following parameters can be used to configure Netty for simple + TCP: + + + use-nio. If this is true then Java + non blocking NIO will be used. If set to false then old + blocking Java IO will be used. + If you require the server to handle many concurrent connections, we highly + recommend that you use non blocking Java NIO. Java NIO does not maintain a + thread per connection so can scale to many more concurrent connections than + with old blocking IO. If you don't require the server to handle many + concurrent connections, you might get slightly better performance by using + old (blocking) IO. The default value for this property is false on the server side and false on the + client side. + + + host. This specifies the host name or IP address to + connect to (when configuring a connector) or to listen on (when configuring + an acceptor). The default value for this property is localhost. When configuring acceptors, multiple hosts or IP + addresses can be specified by separating them with commas. It is also + possible to specify 0.0.0.0 to accept connection from all the + host's network interfaces. It's not valid to specify multiple addresses when + specifying the host for a connector; a connector makes a connection to one + specific address. + + Don't forget to specify a host name or IP address! If you want your + server able to accept connections from other nodes you must specify a + hostname or IP address at which the acceptor will bind and listen for + incoming connections. The default is localhost which of course is not + accessible from remote nodes! + + + + port. This specified the port to connect to (when + configuring a connector) or to listen on (when configuring an acceptor). The + default value for this property is 5445. + + + tcp-no-delay. If this is true then + Nagle's + algorithm will be disabled. This is a + Java (client) socket option. The default value for this property is true. + + + tcp-send-buffer-size. This parameter determines the + size of the TCP send buffer in bytes. The default value for this property is + 32768 bytes (32KiB). + TCP buffer sizes should be tuned according to the bandwidth and latency of + your network. Here's a good link that explains the theory behind this. + In summary TCP send/receive buffer sizes should be calculated as: + +buffer_size = bandwidth * RTT. + Where bandwidth is in bytes per second and network + round trip time (RTT) is in seconds. RTT can be easily measured using the + ping utility. + For fast networks you may want to increase the buffer sizes from the + defaults. + + + tcp-receive-buffer-size. This parameter determines the + size of the TCP receive buffer in bytes. The default value for this property + is 32768 bytes (32KiB). + + + batch-delay. Before writing packets to the transport, + HornetQ can be configured to batch up writes for a maximum of batch-delay milliseconds. This can increase overall + throughput for very small messages. It does so at the expense of an increase + in average latency for message transfer. The default value for this property + is 0 ms. + + + direct-deliver. When a message arrives on the server + and is delivered to waiting consumers, by default, the delivery is done on + the same thread as that on which the message arrived. This gives good latency + in environments with relatively small messages and a small number of consumers, + but at the cost of overall throughput and scalability - especially on multi-core + machines. If you want the lowest latency and a possible reduction in throughput + then you can use the default value for direct-deliver (i.e. + true). If you are willing to take some small extra hit on latency but want the + highest throughput set direct-deliver to false + . + + + nio-remoting-threads. When configured to use NIO, + HornetQ will, by default, use a number of threads equal to three times the + number of cores (or hyper-threads) as reported by Runtime.getRuntime().availableProcessors() for processing + incoming packets. If you want to override this value, you can set the number + of threads by specifying this parameter. The default value for this + parameter is -1 which means use the value from Runtime.getRuntime().availableProcessors() * 3. + + + local-address. When configured a Netty Connector it is possible to specify + which local address the client will use when connecting to the remote address. This is typically used + in the Application Server or when running Embedded to control which address is used for outbound + connections. If the local-address is not set then the connector will use any local address available + + + local-port. When configured a Netty Connector it is possible to specify + which local port the client will use when connecting to the remote address. This is typically used + in the Application Server or when running Embedded to control which port is used for outbound + connections. If the local-port default is used, which is 0, then the connector will let the + system pick up an ephemeral port. valid ports are 0 to 65535 + + +
+
+ Configuring Netty SSL + Netty SSL is similar to the Netty TCP transport but it provides additional + security by encrypting TCP connections using the Secure Sockets Layer SSL + Please see the examples for a full working example of using Netty SSL. + Netty SSL uses all the same properties as Netty TCP but adds the following + additional properties: + + + ssl-enabled + Must be true to enable SSL. Default is false. + + + key-store-path + When used on an acceptor this is the path to the SSL key + store on the server which holds the server's certificates (whether self-signed + or signed by an authority). + When used on a connector this is the path to the client-side + SSL key store which holds the client certificates. This is only relevant + for a connector if you are using 2-way SSL (i.e. mutual + authentication). Although this value is configured on the server, it is + downloaded and used by the client. If the client needs to use a different path + from that set on the server then it can override the server-side setting by either + using the customary "javax.net.ssl.keyStore" system property or the HornetQ-specific + "org.hornetq.ssl.keyStore" system property. The HornetQ-specific system property + is useful if another component on client is already making use of the standard, Java + system property. + + + key-store-password + When used on an acceptor this is the password for the + server-side keystore. + When used on a connector this is the password for the + client-side keystore. This is only relevant for a connector + if you are using 2-way SSL (i.e. mutual authentication). Although this value can + be configured on the server, it is downloaded and used by the client. If the client + needs to use a different password from that set on the server then it can override + the server-side setting by either using the customary "javax.net.ssl.keyStorePassword" + system property or the HornetQ-specific "org.hornetq.ssl.keyStorePassword" system + property. The HornetQ-specific system property is useful if another component on client + is already making use of the standard, Java system property. + + + trust-store-path + When used on an acceptor this is the path to the server-side + SSL key store that holds the keys of all the clients that the server trusts. This + is only relevant for an acceptor if you are using 2-way SSL + (i.e. mutual authentication). + When used on a connector this is the path to the client-side + SSL key store which holds the public keys of all the servers that the client + trusts. Although this value can be configured on the server, it is downloaded and + used by the client. If the client needs to use a different path + from that set on the server then it can override the server-side setting by either + using the customary "javax.net.ssl.trustStore" system property or the HornetQ-specific + "org.hornetq.ssl.trustStore" system property. The HornetQ-specific system property + is useful if another component on client is already making use of the standard, Java + system property. + + + trust-store-password + When used on an acceptor this is the password for the + server-side trust store. This is only relevant for an acceptor + if you are using 2-way SSL (i.e. mutual authentication). + When used on a connector this is the password for the + client-side truststore. Although this value can be configured on the server, it is + downloaded and used by the client. If the client + needs to use a different password from that set on the server then it can override + the server-side setting by either using the customary "javax.net.ssl.trustStorePassword" + system property or the HornetQ-specific "org.hornetq.ssl.trustStorePassword" system + property. The HornetQ-specific system property is useful if another component on client + is already making use of the standard, Java system property. + + + enabled-cipher-suites + Whether used on an acceptor or connector this is a + comma separated list of cipher suites used for SSL communication. The default value is + null which means the JVM's default will be used. + + + enabled-protocols + Whether used on an acceptor or connector this is a + comma separated list of protocols used for SSL communication. The default value is + null which means the JVM's default will be used. + + + need-client-auth + This property is only for an acceptor. It tells a client connecting to this + acceptor that 2-way SSL is required. Valid values are true or + false. Default is false. + + +
+
+ Configuring Netty HTTP + Netty HTTP tunnels packets over the HTTP protocol. It can be useful in scenarios + where firewalls only allow HTTP traffic to pass. + Please see the examples for a full working example of using Netty HTTP. + Netty HTTP uses the same properties as Netty TCP but adds the following additional + properties: + + + http-enabled. This is now no longer needed as of version 2.4. With single + port support HornetQ will now automatically detect if http is being used and configure itself. + + + http-client-idle-time. How long a client can be idle + before sending an empty http request to keep the connection alive + + + http-client-idle-scan-period. How often, in + milliseconds, to scan for idle clients + + + http-response-time. How long the server can wait before + sending an empty http response to keep the connection alive + + + http-server-scan-period. How often, in milliseconds, to + scan for clients needing responses + + + http-requires-session-id. If true the client will wait + after the first call to receive a session id. Used the http connector is + connecting to servlet acceptor (not recommended) + + +
+
+ Configuring Netty Servlet + As of 2.4 HornetQ Servlet support will be provided via Undertow in Wildfly +
+
+
diff --git a/docs/user-manual/en/connection-ttl.xml b/docs/user-manual/en/connection-ttl.xml new file mode 100644 index 0000000000..b9b4182b98 --- /dev/null +++ b/docs/user-manual/en/connection-ttl.xml @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Detecting Dead Connections + In this section we will discuss connection time-to-live (TTL) and explain how HornetQ + deals with crashed clients and clients which have exited without cleanly closing their + resources. +
+ Cleaning up Dead Connection Resources on the Server + Before a HornetQ client application exits it is considered good practice that it + should close its resources in a controlled manner, using a finally + block. + Here's an example of a well behaved core client application closing its session and + session factory in a finally block: + +ServerLocator locator = null; +ClientSessionFactory sf = null; +ClientSession session = null; + +try +{ + locator = HornetQClient.createServerLocatorWithoutHA(..); + + sf = locator.createClientSessionFactory();; + + session = sf.createSession(...); + + ... do some stuff with the session... +} +finally +{ + if (session != null) + { + session.close(); + } + + if (sf != null) + { + sf.close(); + } + + if(locator != null) + { + locator.close(); + } +} + And here's an example of a well behaved JMS client application: + +Connection jmsConnection = null; + +try +{ + ConnectionFactory jmsConnectionFactory = HornetQJMSClient.createConnectionFactoryWithoutHA(...); + + jmsConnection = jmsConnectionFactory.createConnection(); + + ... do some stuff with the connection... +} +finally +{ + if (connection != null) + { + connection.close(); + } +} + Unfortunately users don't always write well behaved applications, and sometimes + clients just crash so they don't have a chance to clean up their resources! + If this occurs then it can leave server side resources, like sessions, hanging on the + server. If these were not removed they would cause a resource leak on the server and + over time this result in the server running out of memory or other resources. + We have to balance the requirement for cleaning up dead client resources with the fact + that sometimes the network between the client and the server can fail and then come + back, allowing the client to reconnect. HornetQ supports client reconnection, so we + don't want to clean up "dead" server side resources too soon or this will prevent any + client from reconnecting, as it won't be able to find its old sessions on the + server. + HornetQ makes all of this configurable. For each ClientSessionFactory we define a connection TTL. + Basically, the TTL determines how long the server will keep a connection alive in the + absence of any data arriving from the client. The client will automatically send "ping" + packets periodically to prevent the server from closing it down. If the server doesn't + receive any packets on a connection for the connection TTL time, then it will + automatically close all the sessions on the server that relate to that + connection. + If you're using JMS, the connection TTL is defined by the ConnectionTTL attribute on a HornetQConnectionFactory + instance, or if you're deploying JMS connection factory instances direct into JNDI on + the server side, you can specify it in the xml config, using the parameter connection-ttl. + The default value for connection ttl on an "unreliable" connection (e.g. a Netty + connection) is 60000ms, i.e. 1 minute. The default value for connection + ttl on a "reliable" connection (e.g. an in-vm connection) is -1. A + value of -1 for ConnectionTTL means the server + will never time out the connection on the server side. + If you do not wish clients to be able to specify their own connection TTL, you can + override all values used by a global value set on the server side. This can be done by + specifying the connection-ttl-override attribute in the server side + configuration. The default value for connection-ttl-override is + -1 which means "do not override" (i.e. let clients use their own + values). +
+ Closing core sessions or JMS connections that you have failed to close + As previously discussed, it's important that all core client sessions and JMS + connections are always closed explicitly in a finally block when + you are finished using them. + If you fail to do so, HornetQ will detect this at garbage collection time, and log + a warning similar to the following in the logs (If you are using JMS the warning + will involve a JMS connection not a client session): + +[Finalizer] 20:14:43,244 WARNING [org.hornetq.core.client.impl.DelegatingSession] I'm closing a ClientSession you left open. Please make sure you close all ClientSessions explicitly before let +ting them go out of scope! +[Finalizer] 20:14:43,244 WARNING [org.hornetq.core.client.impl.DelegatingSession] The session you didn't close was created here: +java.lang.Exception + at org.hornetq.core.client.impl.DelegatingSession.<init>(DelegatingSession.java:83) + at org.acme.yourproject.YourClass (YourClass.java:666) + HornetQ will then close the connection / client session for you. + Note that the log will also tell you the exact line of your user code where you + created the JMS connection / client session that you later did not close. This will + enable you to pinpoint the error in your code and correct it appropriately. +
+
+
+ Detecting failure from the client side. + In the previous section we discussed how the client sends pings to the server and how + "dead" connection resources are cleaned up by the server. There's also another reason + for pinging, and that's for the client to be able to detect that + the server or network has failed. + As long as the client is receiving data from the server it will consider the + connection to be still alive. + If the client does not receive any packets for client-failure-check-period milliseconds then it will consider the + connection failed and will either initiate failover, or call any FailureListener instances (or ExceptionListener + instances if you are using JMS) depending on how it has been configured. + If you're using JMS it's defined by the ClientFailureCheckPeriod + attribute on a HornetQConnectionFactory instance, or if you're + deploying JMS connection factory instances direct into JNDI on the server side, you can + specify it in the hornetq-jms.xml configuration file, using the + parameter client-failure-check-period. + The default value for client failure check period on an "unreliable" connection (e.g. + a Netty connection) is 30000ms, i.e. 30 seconds. The default value + for client failure check period on a "reliable" connection (e.g. an in-vm connection) + is -1. A value of -1 means the client will never fail the + connection on the client side if no data is received from the server. Typically this is + much lower than connection TTL to allow clients to reconnect in case of transitory + failure. +
+
+ Configuring Asynchronous Connection Execution + Most packets received on the server side are executed on the remoting thread. These packets + represent short-running operations and are always executed on the remoting thread for + performance reasons. + However, by default some kinds of packets are executed using a thread from a + thread pool so that the remoting thread is not tied up for too long. Please note that + processing operations asynchronously on another thread adds a little more latency. These packets + are: + + + org.hornetq.core.protocol.core.impl.wireformat.RollbackMessage + + + org.hornetq.core.protocol.core.impl.wireformat.SessionCloseMessage + + + org.hornetq.core.protocol.core.impl.wireformat.SessionCommitMessage + + + org.hornetq.core.protocol.core.impl.wireformat.SessionXACommitMessage + + + org.hornetq.core.protocol.core.impl.wireformat.SessionXAPrepareMessage + + + org.hornetq.core.protocol.core.impl.wireformat.SessionXARollbackMessage + + + To disable asynchronous connection execution, set the parameter + async-connection-execution-enabled in + hornetq-configuration.xml to false (default value is + true). +
+
diff --git a/docs/user-manual/en/core-bridges.xml b/docs/user-manual/en/core-bridges.xml new file mode 100644 index 0000000000..9004e7f755 --- /dev/null +++ b/docs/user-manual/en/core-bridges.xml @@ -0,0 +1,240 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Core Bridges + The function of a bridge is to consume messages from a source queue, and forward them to a + target address, typically on a different HornetQ server. + The source and target servers do not have to be in the same cluster which makes bridging + suitable for reliably sending messages from one cluster to another, for instance across a + WAN, or internet and where the connection may be unreliable. + The bridge has built in resilience to failure so if the target server connection is lost, + e.g. due to network failure, the bridge will retry connecting to the target until it comes + back online. When it comes back online it will resume operation as normal. + In summary, bridges are a way to reliably connect two separate HornetQ servers together. + With a core bridge both source and target servers must be HornetQ servers. + Bridges can be configured to provide once and only once delivery + guarantees even in the event of the failure of the source or the target server. They do this + by using duplicate detection (described in ). + + Although they have similar function, don't confuse core bridges with JMS + bridges! + Core bridges are for linking a HornetQ node with another HornetQ node and do not use + the JMS API. A JMS Bridge is used for linking any two JMS 1.1 compliant JMS providers. + So, a JMS Bridge could be used for bridging to or from different JMS compliant messaging + system. It's always preferable to use a core bridge if you can. Core bridges use + duplicate detection to provide once and only once guarantees. To + provide the same guarantee using a JMS bridge you would have to use XA which has a + higher overhead and is more complex to configure. + +
+ Configuring Bridges + Bridges are configured in hornetq-configuration.xml. Let's kick off + with an example (this is actually from the bridge example): + +<bridge name="my-bridge"> + <queue-name>jms.queue.sausage-factory</queue-name> + <forwarding-address>jms.queue.mincing-machine</forwarding-address> + <filter-string="name='aardvark'"/> + <transformer-class-name> + org.hornetq.jms.example.HatColourChangeTransformer + </transformer-class-name> + <retry-interval>1000</retry-interval> + <ha>true</ha> + <retry-interval-multiplier>1.0</retry-interval-multiplier> + <initial-connect-attempts>-1</initial-connect-attempts> + <reconnect-attempts>-1</reconnect-attempts> + <failover-on-server-shutdown>false</failover-on-server-shutdown> + <use-duplicate-detection>true</use-duplicate-detection> + <confirmation-window-size>10000000</confirmation-window-size> + <user>foouser</user> + <password>foopassword</password> + <static-connectors> + <connector-ref>remote-connector</connector-ref> + </static-connectors> + <!-- alternative to static-connectors + <discovery-group-ref discovery-group-name="bridge-discovery-group"/> + --> +</bridge> + In the above example we have shown all the parameters its possible to configure for a + bridge. In practice you might use many of the defaults so it won't be necessary to + specify them all explicitly. + Let's take a look at all the parameters in turn: + + + name attribute. All bridges must have a unique name in the + server. + + + queue-name. This is the unique name of the local queue that + the bridge consumes from, it's a mandatory parameter. + The queue must already exist by the time the bridge is instantiated at + start-up. + + If you're using JMS then normally the JMS configuration hornetq-jms.xml is loaded after the core configuration file + hornetq-configuration.xml is loaded. If your bridge + is consuming from a JMS queue then you'll need to make sure the JMS queue is + also deployed as a core queue in the core configuration. Take a look at the + bridge example for an example of how this is done. + + + + forwarding-address. This is the address on the target + server that the message will be forwarded to. If a forwarding address is not + specified, then the original address of the message will be retained. + + + filter-string. An optional filter string can be supplied. + If specified then only messages which match the filter expression specified in + the filter string will be forwarded. The filter string follows the HornetQ + filter expression syntax described in . + + + transformer-class-name. An optional transformer-class-name + can be specified. This is the name of a user-defined class which implements the + org.hornetq.core.server.cluster.Transformer + interface. + If this is specified then the transformer's transform() + method will be invoked with the message before it is forwarded. This gives you + the opportunity to transform the message's header or body before forwarding + it. + + + ha. This optional parameter determines whether or not this + bridge should support high availability. True means it will connect to any available + server in a cluster and support failover. The default value is false. + + + retry-interval. This optional parameter determines the + period in milliseconds between subsequent reconnection attempts, if the + connection to the target server has failed. The default value is 2000milliseconds. + + + retry-interval-multiplier. This optional parameter + determines determines a multiplier to apply to the time since the last retry to + compute the time to the next retry. + This allows you to implement an exponential backoff + between retry attempts. + Let's take an example: + If we set retry-intervalto 1000 ms and + we set retry-interval-multiplier to 2.0, + then, if the first reconnect attempt fails, we will wait 1000 + ms then 2000 ms then 4000 ms between + subsequent reconnection attempts. + The default value is 1.0 meaning each reconnect attempt is + spaced at equal intervals. + + + initial-connect-attempts. This optional parameter determines the + total number of initial connect attempts the bridge will make before giving up and + shutting down. A value of -1 signifies an unlimited number of + attempts. The default value is -1. + + + reconnect-attempts. This optional parameter determines the + total number of reconnect attempts the bridge will make before giving up and + shutting down. A value of -1 signifies an unlimited number of + attempts. The default value is -1. + + + failover-on-server-shutdown. This optional parameter + determines whether the bridge will attempt to failover onto a backup server (if + specified) when the target server is cleanly shutdown rather than + crashed. + The bridge connector can specify both a live and a backup server, if it + specifies a backup server and this parameter is set to true + then if the target server is cleanly shutdown the bridge + connection will attempt to failover onto its backup. If the bridge connector has + no backup server configured then this parameter has no effect. + Sometimes you want a bridge configured with a live and a backup target server, + but you don't want to failover to the backup if the live server is simply taken + down temporarily for maintenance, this is when this parameter comes in + handy. + The default value for this parameter is false. + + + use-duplicate-detection. This optional parameter determines + whether the bridge will automatically insert a duplicate id property into each + message that it forwards. + Doing so, allows the target server to perform duplicate detection on messages + it receives from the source server. If the connection fails or server crashes, + then, when the bridge resumes it will resend unacknowledged messages. This might + result in duplicate messages being sent to the target server. By enabling + duplicate detection allows these duplicates to be screened out and + ignored. + This allows the bridge to provide a once and only once + delivery guarantee without using heavyweight methods such as XA (see for more information). + The default value for this parameter is true. + + + confirmation-window-size. This optional parameter + determines the confirmation-window-size to use for the + connection used to forward messages to the target node. This attribute is + described in section + + When using the bridge to forward messages from a queue which has a + max-size-bytes set it's important that confirmation-window-size is less than + or equal to max-size-bytes to prevent the flow of + messages from ceasing. + + + + + user. This optional parameter determines the user name to + use when creating the bridge connection to the remote server. If it is not + specified the default cluster user specified by cluster-user + in hornetq-configuration.xml will be used. + + + password. This optional parameter determines the password + to use when creating the bridge connection to the remote server. If it is not + specified the default cluster password specified by cluster-password in hornetq-configuration.xml + will be used. + + + static-connectors or discovery-group-ref. + Pick either of these options to connect the bridge to the target server. + + The static-connectors is a list of connector-ref + elements pointing to connector elements defined elsewhere. + A connector encapsulates knowledge of what transport to + use (TCP, SSL, HTTP etc) as well as the server connection parameters (host, port + etc). For more information about what connectors are and how to configure them, + please see . + + The discovery-group-ref element has one attribute - + discovery-group-name. This attribute points to a + discovery-group defined elsewhere. For more information about + what discovery-groups are and how to configure them, please see + . + + + +
+
diff --git a/docs/user-manual/en/diagrams/architecture-diagrams.odg b/docs/user-manual/en/diagrams/architecture-diagrams.odg new file mode 100644 index 0000000000..33d99cf6bb Binary files /dev/null and b/docs/user-manual/en/diagrams/architecture-diagrams.odg differ diff --git a/docs/user-manual/en/diagrams/ha-replicated-store.odg b/docs/user-manual/en/diagrams/ha-replicated-store.odg new file mode 100644 index 0000000000..495c672ecf Binary files /dev/null and b/docs/user-manual/en/diagrams/ha-replicated-store.odg differ diff --git a/docs/user-manual/en/diagrams/ha-shared-store.odg b/docs/user-manual/en/diagrams/ha-shared-store.odg new file mode 100644 index 0000000000..3b976924f4 Binary files /dev/null and b/docs/user-manual/en/diagrams/ha-shared-store.odg differ diff --git a/docs/user-manual/en/diverts.xml b/docs/user-manual/en/diverts.xml new file mode 100644 index 0000000000..3cddf094bd --- /dev/null +++ b/docs/user-manual/en/diverts.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + + Diverting and Splitting Message Flows + HornetQ allows you to configure objects called diverts with + some simple server configuration. + Diverts allow you to transparently divert messages routed to one address to some other + address, without making any changes to any client application logic. + Diverts can be exclusive, meaning that the message is diverted + to the new address, and does not go to the old address at all, or they can be + non-exclusive which means the message continues to go the old + address, and a copy of it is also sent to the new address. + Non-exclusive diverts can therefore be used for splitting message + flows, e.g. there may be a requirement to monitor every order sent to an order queue. + Diverts can also be configured to have an optional message filter. If specified then only + messages that match the filter will be diverted. + Diverts can also be configured to apply a Transformer. If specified, + all diverted messages will have the opportunity of being transformed by the Transformer. + A divert will only divert a message to an address on the same server, + however, if you want to divert to an address on a different server, a common pattern would + be to divert to a local store-and-forward queue, then set up a bridge which consumes from + that queue and forwards to an address on a different server. + Diverts are therefore a very sophisticated concept, which when combined with bridges can + be used to create interesting and complex routings. The set of diverts on a server can be + thought of as a type of routing table for messages. Combining diverts with bridges allows + you to create a distributed network of reliable routing connections between multiple + geographically distributed servers, creating your global messaging mesh. + Diverts are defined as xml in the hornetq-configuration.xml file. There can + be zero or more diverts in the file. + Please see for a full working + example showing you how to configure and use diverts. + Let's take a look at some divert examples: +
+ Exclusive Divert + Let's take a look at an exclusive divert. An exclusive divert diverts all matching + messages that are routed to the old address to the new address. Matching messages do not + get routed to the old address. + Here's some example xml configuration for an exclusive divert, it's taken from the + divert example: + +<divert name="prices-divert"> + <address>jms.topic.priceUpdates</address> + <forwarding-address>jms.queue.priceForwarding</forwarding-address> + <filter string="office='New York'"/> + <transformer-class-name> + org.hornetq.jms.example.AddForwardingTimeTransformer + </transformer-class-name> + <exclusive>true</exclusive> +</divert> + We define a divert called 'prices-divert' that will divert any + messages sent to the address 'jms.topic.priceUpdates' (this + corresponds to any messages sent to a JMS Topic called 'priceUpdates') to another local address 'jms.queue.priceForwarding' (this corresponds to a local JMS queue called + 'priceForwarding' + We also specify a message filter string so only messages with the message property + office with value New York will get diverted, + all other messages will continue to be routed to the normal address. The filter string + is optional, if not specified then all messages will be considered matched. + In this example a transformer class is specified. Again this is optional, and if + specified the transformer will be executed for each matching message. This allows you to + change the messages body or properties before it is diverted. In this example the + transformer simply adds a header that records the time the divert happened. + This example is actually diverting messages to a local store and forward queue, which + is configured with a bridge which forwards the message to an address on another HornetQ + server. Please see the example for more details. +
+
+ Non-exclusive Divert + Now we'll take a look at a non-exclusive divert. Non exclusive diverts are the same as + exclusive diverts, but they only forward a copy of the message to + the new address. The original message continues to the old address + You can therefore think of non-exclusive diverts as splitting a + message flow. + Non exclusive diverts can be configured in the same way as exclusive diverts with an + optional filter and transformer, here's an example non-exclusive divert, again from the + divert example: + +<divert name="order-divert"> + <address>jms.queue.orders</address> + <forwarding-address>jms.topic.spyTopic</forwarding-address> + <exclusive>false</exclusive> +</divert> + The above divert example takes a copy of every message sent to the address 'jms.queue.orders' (Which corresponds to a JMS Queue called 'orders') and sends it to a local address called 'jms.topic.SpyTopic' (which corresponds to a JMS Topic called 'SpyTopic'). +
+
diff --git a/docs/user-manual/en/duplicate-detection.xml b/docs/user-manual/en/duplicate-detection.xml new file mode 100644 index 0000000000..c2577ff245 --- /dev/null +++ b/docs/user-manual/en/duplicate-detection.xml @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + + Duplicate Message Detection + HornetQ includes powerful automatic duplicate message detection, filtering out + duplicate messages without you having to code your own fiddly duplicate detection logic at + the application level. This chapter will explain what duplicate detection is, how HornetQ + uses it and how and where to configure it. + When sending messages from a client to a server, or indeed from a server to another + server, if the target server or connection fails sometime after sending the message, but + before the sender receives a response that the send (or commit) was processed successfully + then the sender cannot know for sure if the message was sent successfully to the + address. + If the target server or connection failed after the send was received and processed but + before the response was sent back then the message will have been sent to the address + successfully, but if the target server or connection failed before the send was received and + finished processing then it will not have been sent to the address successfully. From the + senders point of view it's not possible to distinguish these two cases. + When the server recovers this leaves the client in a difficult situation. It knows the + target server failed, but it does not know if the last message reached its destination ok. + If it decides to resend the last message, then that could result in a duplicate message + being sent to the address. If each message was an order or a trade then this could result in + the order being fulfilled twice or the trade being double booked. This is clearly not a + desirable situation. + Sending the message(s) in a transaction does not help out either. If the server or + connection fails while the transaction commit is being processed it is also indeterminate + whether the transaction was successfully committed or not! + To solve these issues HornetQ provides automatic duplicate messages detection for + messages sent to addresses. +
+ Using Duplicate Detection for Message Sending + Enabling duplicate message detection for sent messages is simple: you just need to set + a special property on the message to a unique value. You can create the value however + you like, as long as it is unique. When the target server receives the message it will + check if that property is set, if it is, then it will check in its in memory cache if it + has already received a message with that value of the header. If it has received a + message with the same value before then it will ignore the message. + + Using duplicate detection to move messages between nodes can give you the same + once and only once delivery guarantees as if you were using + an XA transaction to consume messages from source and send them to the target, but + with less overhead and much easier configuration than using XA. + + If you're sending messages in a transaction then you don't have to set the property + for every message you send in that transaction, you only need to + set it once in the transaction. If the server detects a duplicate message for any + message in the transaction, then it will ignore the entire transaction. + The name of the property that you set is given by the value of org.hornetq.api.core.Message.HDR_DUPLICATE_DETECTION_ID, which + is _HQ_DUPL_ID + The value of the property can be of type byte[] or SimpleString if you're using the core API. If you're using JMS it must be + a String, and its value should be unique. An easy way of generating + a unique id is by generating a UUID. + Here's an example of setting the property using the core API: + +... + +ClientMessage message = session.createMessage(true); + +SimpleString myUniqueID = "This is my unique id"; // Could use a UUID for this + +message.setStringProperty(HDR_DUPLICATE_DETECTION_ID, myUniqueID); + +... + And here's an example using the JMS API: + +... + +Message jmsMessage = session.createMessage(); + +String myUniqueID = "This is my unique id"; // Could use a UUID for this + +message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID); + +... +
+
+ Configuring the Duplicate ID Cache + The server maintains caches of received values of the org.hornetq.core.message.impl.HDR_DUPLICATE_DETECTION_ID property + sent to each address. Each address has its own distinct cache. + The cache is a circular fixed size cache. If the cache has a maximum size of n elements, then the n + 1th id stored will overwrite + the 0th element in the cache. + The maximum size of the cache is configured by the parameter id-cache-size in hornetq-configuration.xml, the default + value is 2000 elements. + The caches can also be configured to persist to disk or not. This is configured by the + parameter persist-id-cache, also in hornetq-configuration.xml. If this is set to true then + each id will be persisted to permanent storage as they are received. The default value + for this parameter is true. + + When choosing a size of the duplicate id cache be sure to set it to a larger + enough size so if you resend messages all the previously sent ones are in the cache + not having been overwritten. + +
+
+ Duplicate Detection and Bridges + Core bridges can be configured to automatically add a unique duplicate id value (if there + isn't already one in the message) before forwarding the message to it's target. This + ensures that if the target server crashes or the connection is interrupted and the + bridge resends the message, then if it has already been received by the target server, + it will be ignored. + To configure a core bridge to add the duplicate id header, simply set the use-duplicate-detection to true when configuring a + bridge in hornetq-configuration.xml. + The default value for this parameter is true. + For more information on core bridges and how to configure them, please see + . +
+
+ Duplicate Detection and Cluster Connections + Cluster connections internally use core bridges to move messages reliable between + nodes of the cluster. Consequently they can also be configured to insert the duplicate + id header for each message they move using their internal bridges. + To configure a cluster connection to add the duplicate id header, simply set the + use-duplicate-detection to true when + configuring a cluster connection in hornetq-configuration.xml. + The default value for this parameter is true. + For more information on cluster connections and how to configure them, please see . +
+
diff --git a/docs/user-manual/en/embedding-hornetq.xml b/docs/user-manual/en/embedding-hornetq.xml new file mode 100644 index 0000000000..e2bea3a8d8 --- /dev/null +++ b/docs/user-manual/en/embedding-hornetq.xml @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Embedding HornetQ + + HornetQ is designed as set of simple Plain Old Java Objects (POJOs). + This means HornetQ can be instantiated and run in any dependency injection + framework such as JBoss Microcontainer, Spring or Google Guice. It also + means that if you have an application that could use messaging functionality + internally, then it can directly instantiate HornetQ + clients and servers in its own application code to perform that + functionality. We call this embedding HornetQ. + + Examples of applications that might want to do this include any + application that needs very high performance, transactional, persistent + messaging but doesn't want the hassle of writing it all from scratch. + + Embedding HornetQ can be done in very few easy steps. Instantiate the + configuration object, instantiate the server, start it, and you have a + HornetQ running in your virtual machine. It's as simple and easy as + that. + +
+ Simple Config File Embedding + + The simplest way to embed HornetQ is to use the embedded wrapper + classes and configure HornetQ through its configuration files. There are + two different helper classes for this depending on whether your using the + HornetQ Core API or JMS. + +
+ Core API Only + For instantiating a core HornetQ Server only, the steps are pretty + simple. The example requires that you have defined a configuration file + hornetq-configuration.xml in your + classpath: + +import org.hornetq.core.server.embedded.EmbeddedHornetQ; + +... + +EmbeddedHornetQ embedded = new EmbeddedHornetQ(); +embedded.start(); + +ClientSessionFactory nettyFactory = HornetQClient.createClientSessionFactory( + new TransportConfiguration( + InVMConnectorFactory.class.getName())); + +ClientSession session = factory.createSession(); + +session.createQueue("example", "example", true); + +ClientProducer producer = session.createProducer("example"); + +ClientMessage message = session.createMessage(true); + +message.getBody().writeString("Hello"); + +producer.send(message); + +session.start(); + +ClientConsumer consumer = session.createConsumer("example"); + +ClientMessage msgReceived = consumer.receive(); + +System.out.println("message = " + msgReceived.getBody().readString()); + +session.close(); + +The EmbeddedHornetQ class has a + few additional setter methods that allow you to specify a different + config file name as well as other properties. See the javadocs for this + class for more details. +
+ +
+ JMS API + + JMS embedding is simple as well. This example requires that you + have defined the config files + hornetq-configuration.xml, + hornetq-jms.xml, and a + hornetq-users.xml if you have security enabled. Let's + also assume that a queue and connection factory has been defined in the + hornetq-jms.xml config file. + + +import org.hornetq.jms.server.embedded.EmbeddedJMS; + +... + +EmbeddedJMS jms = new EmbeddedJMS(); +jms.start(); + +// This assumes we have configured hornetq-jms.xml with the appropriate config information +ConnectionFactory connectionFactory = jms.lookup("ConnectionFactory"); +Destination destination = jms.lookup("/example/queue"); + +... regular JMS code ... + By default, the EmbeddedJMS + class will store component entries defined within your + hornetq-jms.xml file in an internal concurrent hash + map. The EmbeddedJMS.lookup() method returns + components stored in this map. If you want to use JNDI, call the + EmbeddedJMS.setContext() method with the root JNDI + context you want your components bound into. See the javadocs for this + class for more details on other config options. +
+
+ +
+ POJO instantiation - Embedding Programmatically + + You can follow this step-by-step guide to programmatically embed the + core, non-JMS HornetQ Server instance: + + Create the configuration object - this contains configuration + information for a HornetQ instance. The setter methods of this class allow + you to programmatically set configuration options as describe in the section. + + The acceptors are configured through + ConfigurationImpl. Just add the + NettyAcceptorFactory on the transports the same way you + would through the main configuration file. + + +import org.hornetq.core.config.Configuration; +import org.hornetq.core.config.impl.ConfigurationImpl; + +... + +Configuration config = new ConfigurationImpl(); +HashSet<TransportConfiguration> transports = new HashSet<TransportConfiguration>(); + +transports.add(new TransportConfiguration(NettyAcceptorFactory.class.getName())); +transports.add(new TransportConfiguration(InVMAcceptorFactory.class.getName())); + +config.setAcceptorConfigurations(transports); + + You need to instantiate an instance of + org.hornetq.api.core.server.embedded.EmbeddedHornetQ + and add the configuration object to it. + + +import org.hornetq.api.core.server.HornetQ; +import org.hornetq.core.server.embedded.EmbeddedHornetQ; + +... + +EmbeddedHornetQ server = new EmbeddedHornetQ(); +server.setConfiguration(config); + +server.start(); + + You also have the option of instantiating + HornetQServerImpl directly: + + +HornetQServer server = new HornetQServerImpl(config); +server.start(); + + For JMS POJO instantiation, you work with the EmbeddedJMS class + instead as described earlier. First you define the configuration + programmatically for your ConnectionFactory and Destination objects, then + set the JmsConfiguration property of the EmbeddedJMS class. Here is an + example of this: + + +// Step 1. Create HornetQ core configuration, and set the properties accordingly +Configuration configuration = new ConfigurationImpl(); +configuration.setPersistenceEnabled(false); +configuration.setSecurityEnabled(false); +configuration.getAcceptorConfigurations().add(new TransportConfiguration(NettyAcceptorFactory.class.getName())); + +// Step 2. Create the JMS configuration +JMSConfiguration jmsConfig = new JMSConfigurationImpl(); + +// Step 3. Configure the JMS ConnectionFactory +TransportConfiguration connectorConfig = new TransportConfiguration(NettyConnectorFactory.class.getName()); +ConnectionFactoryConfiguration cfConfig = new ConnectionFactoryConfigurationImpl("cf", connectorConfig, "/cf"); +jmsConfig.getConnectionFactoryConfigurations().add(cfConfig); + +// Step 4. Configure the JMS Queue +JMSQueueConfiguration queueConfig = new JMSQueueConfigurationImpl("queue1", null, false, "/queue/queue1"); +jmsConfig.getQueueConfigurations().add(queueConfig); + +// Step 5. Start the JMS Server using the HornetQ core server and the JMS configuration +EmbeddedJMS jmsServer = new EmbeddedJMS(); +jmsServer.setConfiguration(configuration); +jmsServer.setJmsConfiguration(jmsConfig); +jmsServer.start(); + + Please see for an example which + shows how to setup and run HornetQ embedded with JMS. +
+ +
+ Dependency Frameworks + + You may also choose to use a dependency injection framework such as + JBoss Micro Container or Spring + Framework. See for more + details on Spring and HornetQ, but here's how you would do things with the + JBoss Micro Container. + + HornetQ standalone uses JBoss Micro Container as the injection + framework. HornetQBootstrapServer and + hornetq-beans.xml which are part of the HornetQ + distribution provide a very complete implementation of what's needed to + bootstrap the server using JBoss Micro Container. + + When using JBoss Micro Container, you need to provide an XML file + declaring the HornetQServer and + Configuration object, you can also inject a security + manager and a MBean server if you want, but those are optional. + + A very basic XML Bean declaration for the JBoss Micro Container + would be: + + +<?xml version="1.0" encoding="UTF-8"?> +<deployment xmlns="urn:jboss:bean-deployer:2.0"> + <!-- The core configuration --> + <bean name="Configuration" + class="org.hornetq.core.config.impl.FileConfiguration"> + </bean> + + <!-- The core server --> + <bean name="HornetQServer" + class="org.hornetq.core.server.impl.HornetQServerImpl"> + <constructor> + <parameter> + <inject bean="Configuration"/> + </parameter> + </constructor> + </bean> +</deployment> + + HornetQBootstrapServer provides an easy + encapsulation of JBoss Micro Container. + + +HornetQBootstrapServer bootStrap = new HornetQBootstrapServer(new String[] {"hornetq-beans.xml"}); +bootStrap.run(); +
+
diff --git a/docs/user-manual/en/examples.xml b/docs/user-manual/en/examples.xml new file mode 100644 index 0000000000..cec40216f0 --- /dev/null +++ b/docs/user-manual/en/examples.xml @@ -0,0 +1,689 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Examples + The HornetQ distribution comes with over 70 run out-of-the-box examples demonstrating many + of the features. + The examples are available in the distribution, in the examples + directory. Examples are split into JMS and core examples. JMS examples show how a particular + feature can be used by a normal JMS client. Core examples show how the equivalent feature + can be used by a core messaging client. + A set of Java EE examples are also provided which need WildFly + installed to be able to run. +
+ JMS Examples + To run a JMS example, simply cd into the appropriate example + directory and type mvn verify (For details please read the readme.html + in each example directory). + Here's a listing of the examples with a brief description. +
+ JMS AeroGear + This example shows how you can send a message to a mobile device by leveraging + AeroGears push technology which provides support for different push notification technologies + like Google Cloud Messaging, Apple's APNs or Mozilla's SimplePush. +
+
+ Applet + This example shows you how to send and receive JMS messages from an Applet. +
+
+ Application-Layer Failover + HornetQ also supports Application-Layer failover, useful in the case that + replication is not enabled on the server side. + With Application-Layer failover, it's up to the application to register a JMS + ExceptionListener with HornetQ which will be called by + HornetQ in the event that connection failure is detected. + The code in the ExceptionListener then recreates the JMS + connection, session, etc on another node and the application can continue. + Application-layer failover is an alternative approach to High Availability (HA). + Application-layer failover differs from automatic failover in that some client side + coding is required in order to implement this. Also, with Application-layer + failover, since the old session object dies and a new one is created, any + uncommitted work in the old session will be lost, and any unacknowledged messages + might be redelivered. +
+
+ Core Bridge Example + The bridge example demonstrates a core bridge deployed on one + server, which consumes messages from a local queue and forwards them to an address + on a second server. + Core bridges are used to create message flows between any two HornetQ servers + which are remotely separated. Core bridges are resilient and will cope with + temporary connection failure allowing them to be an ideal choice for forwarding over + unreliable connections, e.g. a WAN. +
+
+ Browser + The browser example shows you how to use a JMS QueueBrowser with HornetQ. + Queues are a standard part of JMS, please consult the JMS 1.1 specification for + full details. + A QueueBrowser is used to look at messages on the queue + without removing them. It can scan the entire content of a queue or only messages + matching a message selector. +
+
+ Client Kickoff + The client-kickoff example shows how to terminate client + connections given an IP address using the JMX management API. +
+
+ Client side failover listener + The client-side-failoverlistener example shows how to register a listener to monitor + failover events +
+
+ Client-Side Load-Balancing + The client-side-load-balancing example demonstrates how + sessions created from a single JMS Connection can + be created to different nodes of the cluster. In other words it demonstrates how + HornetQ does client-side load-balancing of sessions across the cluster. +
+
+ Clustered Durable Subscription + This example demonstrates a clustered JMS durable subscription +
+
+ Clustered Grouping + This is similar to the message grouping example except that it demonstrates it + working over a cluster. Messages sent to different nodes with the same group id will + be sent to the same node and the same consumer. +
+
+ Clustered Queue + The clustered-queue example demonstrates a JMS queue deployed + on two different nodes. The two nodes are configured to form a cluster. We then + create a consumer for the queue on each node, and we create a producer on only one + of the nodes. We then send some messages via the producer, and we verify that both + consumers receive the sent messages in a round-robin fashion. +
+
+ Clustering with JGroups + The clustered-jgroups example demonstrates how to form a two + node cluster using JGroups as its underlying topology discovery technique, rather than + the default UDP broadcasting. We then create a consumer for the queue on each node, + and we create a producer on only one of the nodes. We then send some messages via the + producer, and we verify that both consumers receive the sent messages in a round-robin fashion. +
+
+ Clustered Standalone + The clustered-standalone example demonstrates how to configure + and starts 3 cluster nodes on the same machine to form a cluster. A subscriber for a + JMS topic is created on each node, and we create a producer on only one of the + nodes. We then send some messages via the producer, and we verify that the 3 + subscribers receive all the sent messages. +
+
+ Clustered Static Discovery + This example demonstrates how to configure a cluster using a list of connectors rather + than UDP for discovery +
+
+ Clustered Static Cluster One Way + This example demonstrates how to set up a cluster where cluster connections are one way, + i.e. server A -> Server B -> Server C +
+
+ Clustered Topic + The clustered-topic example demonstrates a JMS topic deployed + on two different nodes. The two nodes are configured to form a cluster. We then + create a subscriber on the topic on each node, and we create a producer on only one + of the nodes. We then send some messages via the producer, and we verify that both + subscribers receive all the sent messages. +
+
+ Message Consumer Rate Limiting + With HornetQ you can specify a maximum consume rate at which a JMS MessageConsumer + will consume messages. This can be specified when creating or deploying the + connection factory. + If this value is specified then HornetQ will ensure that messages are never + consumed at a rate higher than the specified rate. This is a form of consumer + throttling. +
+
+ Dead Letter + The dead-letter example shows you how to define and deal with + dead letter messages. Messages can be delivered unsuccessfully (e.g. if the + transacted session used to consume them is rolled back). + Such a message goes back to the JMS destination ready to be redelivered. However, + this means it is possible for a message to be delivered again and again without any + success and remain in the destination, clogging the system. + To prevent this, messaging systems define dead letter messages: after a specified + unsuccessful delivery attempts, the message is removed from the destination and put + instead in a dead letter destination where they can be consumed for further + investigation. +
+
+ Delayed Redelivery + The delayed-redelivery example demonstrates how HornetQ can be + configured to provide a delayed redelivery in the case a message needs to be + redelivered. + Delaying redelivery can often be useful in the case that clients regularly fail or + roll-back. Without a delayed redelivery, the system can get into a "thrashing" + state, with delivery being attempted, the client rolling back, and delivery being + re-attempted in quick succession, using up valuable CPU and network + resources. +
+
+ Divert + HornetQ diverts allow messages to be transparently "diverted" or copied from one + address to another with just some simple configuration defined on the server + side. +
+
+ Durable Subscription + The durable-subscription example shows you how to use a durable + subscription with HornetQ. Durable subscriptions are a standard part of JMS, please + consult the JMS 1.1 specification for full details. + Unlike non-durable subscriptions, the key function of durable subscriptions is + that the messages contained in them persist longer than the lifetime of the + subscriber - i.e. they will accumulate messages sent to the topic even if there is + no active subscriber on them. They will also survive server restarts or crashes. + Note that for the messages to be persisted, the messages sent to them must be marked + as durable messages. +
+
+ Embedded + The embedded example shows how to embed JMS + within your own code using POJO instantiation and no config files. +
+
+ Embedded Simple + The embedded example shows how to embed JMS within your own code using regular HornetQ XML files. +
+
+ Message Expiration + The expiry example shows you how to define and deal with + message expiration. Messages can be retained in the messaging system for a limited + period of time before being removed. JMS specification states that clients should + not receive messages that have been expired (but it does not guarantee this will not + happen). + HornetQ can assign an expiry address to a given queue so that when messages + are expired, they are removed from the queue and sent to the expiry address. + These "expired" messages can later be consumed from the expiry address for + further inspection. +
+
+ HornetQ Resource Adapter example + This examples shows how to build the hornetq resource adapters a rar for deployment in other Application + Server's +
+
+ HTTP Transport + The http-transport example shows you how to configure HornetQ + to use the HTTP protocol as its transport layer. +
+
+ Instantiate JMS Objects Directly + Usually, JMS Objects such as ConnectionFactory, Queue and Topic instances are looked up from JNDI + before being used by the client code. This objects are called "administered objects" + in JMS terminology. + However, in some cases a JNDI server may not be available or desired. To come to + the rescue HornetQ also supports the direct instantiation of these administered + objects on the client side so you don't have to use JNDI for JMS. +
+
+ Interceptor + HornetQ allows an application to use an interceptor to hook into the messaging + system. Interceptors allow you to handle various message events in HornetQ. +
+
+ JAAS + The jaas example shows you how to configure HornetQ to use JAAS + for security. HornetQ can leverage JAAS to delegate user authentication and + authorization to existing security infrastructure. +
+
+ JMS Auto Closable + The jms-auto-closeable example shows how JMS resources, such + as connections, sessions and consumers, in JMS 2 can be automatically closed on error. +
+
+ JMS Completion Listener + The jms-completion-listener example shows how to send a message + asynchronously to HornetQ and use a CompletionListener to be notified of the Broker + receiving it. +
+
+ JMS Bridge + The jms-brige example shows how to setup a bridge + between two standalone HornetQ servers. +
+
+ JMS Context + The jms-context example shows how to send and receive a message + to a JMS Queue using HornetQ by using a JMS Context. + A JMSContext is part of JMS 2.0 and combines the JMS Connection and Session Objects + into a simple Interface. +
+
+ JMS Shared Consumer + The jms-shared-consumer example shows you how can use shared + consumers to share a subscription on a topic. In JMS 1.1 this was not allowed and so caused + a scalability issue. In JMS 2 this restriction has been lifted so you can share the load + across different threads and connections. +
+
+ JMX Management + The jmx example shows how to manage HornetQ using JMX. +
+
+ Large Message + The large-message example shows you how to send and receive + very large messages with HornetQ. HornetQ supports the sending and receiving of huge + messages, much larger than can fit in available RAM on the client or server. + Effectively the only limit to message size is the amount of disk space you have on + the server. + Large messages are persisted on the server so they can survive a server restart. + In other words HornetQ doesn't just do a simple socket stream from the sender to the + consumer. +
+
+ Last-Value Queue + The last-value-queue example shows you how to define and deal + with last-value queues. Last-value queues are special queues which discard any + messages when a newer message with the same value for a well-defined last-value + property is put in the queue. In other words, a last-value queue only retains the + last value. + A typical example for last-value queue is for stock prices, where you are only + interested by the latest price for a particular stock. +
+
+ Management + The management example shows how to manage HornetQ using JMS + Messages to invoke management operations on the server. +
+
+ Management Notification + The management-notification example shows how to receive + management notifications from HornetQ using JMS messages. HornetQ servers emit + management notifications when events of interest occur (consumers are created or + closed, addresses are created or deleted, security authentication fails, + etc.). +
+
+ Message Counter + The message-counters example shows you how to use message + counters to obtain message information for a JMS queue. +
+
+ Message Group + The message-group example shows you how to configure and use + message groups with HornetQ. Message groups allow you to pin messages so they are + only consumed by a single consumer. Message groups are sets of messages that has the + following characteristics: + + + + Messages in a message group share the same group id, i.e. they have + same JMSXGroupID string property values + + + The consumer that receives the first message of a group will receive + all the messages that belongs to the group + + + +
+
+ Message Group + The message-group2 example shows you how to configure and use + message groups with HornetQ via a connection factory. +
+
+ Message Priority + Message Priority can be used to influence the delivery order for messages. + It can be retrieved by the message's standard header field 'JMSPriority' as + defined in JMS specification version 1.1. + The value is of type integer, ranging from 0 (the lowest) to 9 (the highest). When + messages are being delivered, their priorities will effect their order of delivery. + Messages of higher priorities will likely be delivered before those of lower + priorities. + Messages of equal priorities are delivered in the natural order of their arrival + at their destinations. Please consult the JMS 1.1 specification for full + details. +
+
+ Multiple Failover + This example demonstrates how to set up a live server with multiple backups +
+
+ Multiple Failover Failback + This example demonstrates how to set up a live server with multiple backups but + forcing failover back to the original live server +
+
+ No Consumer Buffering + By default, HornetQ consumers buffer messages from the server in a client side + buffer before you actually receive them on the client side. This improves + performance since otherwise every time you called receive() or had processed the + last message in a MessageListener onMessage() method, the HornetQ + client would have to go the server to request the next message, which would then get + sent to the client side, if one was available. + This would involve a network round trip for every message and reduce performance. + Therefore, by default, HornetQ pre-fetches messages into a buffer on each + consumer. + In some case buffering is not desirable, and HornetQ allows it to be switched off. + This example demonstrates that. +
+
+ Non-Transaction Failover With Server Data Replication + The non-transaction-failover example demonstrates two servers coupled + as a live-backup pair for high availability (HA), and a client using a non-transacted + JMS session failing over from live to backup when the live server is + crashed. + HornetQ implements failover of client connections between + live and backup servers. This is implemented by the replication of state between + live and backup nodes. When replication is configured and a live node crashes, the + client connections can carry and continue to send and consume messages. When non-transacted + sessions are used, once and only once message delivery is not guaranteed and it is possible + that some messages will be lost or delivered twice. +
+
+ Paging + The paging example shows how HornetQ can support huge queues + even when the server is running in limited RAM. It does this by transparently + paging messages to disk, and depaging + them when they are required. +
+
+ Pre-Acknowledge + Standard JMS supports three acknowledgement modes: + AUTO_ACKNOWLEDGE, CLIENT_ACKNOWLEDGE, and DUPS_OK_ACKNOWLEDGE. For a full description on these modes please + consult the JMS specification, or any JMS tutorial. + All of these standard modes involve sending acknowledgements from the client to + the server. However in some cases, you really don't mind losing messages in event of + failure, so it would make sense to acknowledge the message on the server before + delivering it to the client. This example demonstrates how HornetQ allows this with + an extra acknowledgement mode. +
+
+ Message Producer Rate Limiting + The producer-rte-limit example demonstrates how, with HornetQ, + you can specify a maximum send rate at which a JMS message producer will send + messages. +
+
+ Proton Qpid + HornetQ can be configured to accept requests from any AMQP client that supports the + 1.0 version of the protocol. This proton-j example shows a simply + qpid java 1.0 client example. +
+
+ Proton Ruby + HornetQ can be configured to accept requests from any AMQP client that supports the + 1.0 version of the protocol. This example shows a simply proton ruby client + that sends and receives messages +
+
+ Queue + A simple example demonstrating a JMS queue. +
+
+ Message Redistribution + The queue-message-redistribution example demonstrates message + redistribution between queues with the same name deployed in different nodes of a + cluster. +
+
+ Queue Requestor + A simple example demonstrating a JMS queue requestor. +
+
+ Queue with Message Selector + The queue-selector example shows you how to selectively consume + messages using message selectors with queue consumers. +
+
+ Reattach Node example + The Reattach Node example shows how a client can try to reconnect to + the same server instead of failing the connection immediately and + notifying any user ExceptionListener objects. HornetQ can be configured to automatically + retry the connection, and reattach to the server when it becomes available again across + the network. +
+
+ Replicated Failback example + An example showing how failback works when using replication, In this example a live server will replicate + all its Journal to a backup server as it updates it. When the live server crashes the backup takes over + from the live server and the client reconnects and carries on from where it left off. +
+
+ Replicated Failback static example + An example showing how failback works when using replication, but this time with static connectors +
+
+ Replicated multiple failover example + An example showing how to configure multiple backups when using replication +
+
+ Replicated Failover transaction example + An example showing how failover works with a transaction when using replication +
+
+ Request-Reply example + A simple example showing the JMS request-response pattern. +
+
+ Rest example + An example showing how to use the HornetQ Rest API +
+
+ Scheduled Message + The scheduled-message example shows you how to send a scheduled + message to a JMS Queue with HornetQ. Scheduled messages won't get delivered until a + specified time in the future. +
+
+ Security + The security example shows you how configure and use role based + queue security with HornetQ. +
+
+ Send Acknowledgements + The send-acknowledgements example shows you how to use + HornetQ's advanced asynchronous send acknowledgements feature + to obtain acknowledgement from the server that sends have been received and + processed in a separate stream to the sent messages. +
+
+ Spring Integration + This example shows how to use embedded JMS using HornetQ's Spring integration. +
+
+ SSL Transport + The ssl-enabled shows you how to configure SSL with HornetQ to + send and receive message. +
+
+ Static Message Selector + The static-selector example shows you how to configure a + HornetQ core queue with static message selectors (filters). +
+
+ Static Message Selector Using JMS + The static-selector-jms example shows you how to configure a + HornetQ queue with static message selectors (filters) using JMS. +
+
+ Stomp + The stomp example shows you how to configure a + HornetQ server to send and receive Stomp messages. +
+
+ Stomp1.1 + The stomp example shows you how to configure a + HornetQ server to send and receive Stomp messages via a Stomp 1.1 connection. +
+
+ Stomp1.2 + The stomp example shows you how to configure a + HornetQ server to send and receive Stomp messages via a Stomp 1.2 connection. +
+
+ Stomp Over Web Sockets + The stomp-websockets example shows you how to configure a + HornetQ server to send and receive Stomp messages directly from Web browsers (provided + they support Web Sockets). +
+
+ Symmetric Cluster + The symmetric-cluster example demonstrates a symmetric cluster + set-up with HornetQ. + HornetQ has extremely flexible clustering which allows you to set-up servers in + many different topologies. The most common topology that you'll perhaps be familiar + with if you are used to application server clustering is a symmetric cluster. + With a symmetric cluster, the cluster is homogeneous, i.e. each node is configured + the same as every other node, and every node is connected to every other node in the + cluster. +
+
+ Temporary Queue + A simple example demonstrating how to use a JMS temporary queue. +
+
+ Topic + A simple example demonstrating a JMS topic. +
+
+ Topic Hierarchy + HornetQ supports topic hierarchies. With a topic hierarchy you can register a + subscriber with a wild-card and that subscriber will receive any messages sent to an + address that matches the wild card. +
+
+ Topic Selector 1 + The topic-selector-example1 example shows you how to send + message to a JMS Topic, and subscribe them using selectors with HornetQ. +
+
+ Topic Selector 2 + The topic-selector-example2 example shows you how to + selectively consume messages using message selectors with topic consumers. +
+
+ Transaction Failover + The transaction-failover example demonstrates two servers coupled + as a live-backup pair for high availability (HA), and a client using a transacted JMS + session failing over from live to backup when the live server is + crashed. + HornetQ implements failover of client connections between + live and backup servers. This is implemented by the sharing of a journal between the + servers. When a live node crashes, the + client connections can carry and continue to send and consume messages. When transacted + sessions are used, once and only once message delivery is guaranteed. +
+
+ Failover Without Transactions + The stop-server-failover example demonstrates failover of the + JMS connection from one node to another when the live server crashes using a JMS + non-transacted session. +
+
+ Transactional Session + The transactional example shows you how to use a transactional + Session with HornetQ. +
+
+ XA Heuristic + The xa-heuristic example shows you how to make an XA heuristic + decision through HornetQ Management Interface. A heuristic decision is a unilateral + decision to commit or rollback an XA transaction branch after it has been + prepared. +
+
+ XA Receive + The xa-receive example shows you how message receiving behaves + in an XA transaction in HornetQ. +
+
+ XA Send + The xa-send example shows you how message sending behaves in an + XA transaction in HornetQ. +
+
+ XA with Transaction Manager + The xa-with-jta example shows you how to use JTA interfaces to + control transactions with HornetQ. +
+
+
+ Core API Examples + To run a core example, simply cd into the appropriate example + directory and type ant +
+ Embedded + The embedded example shows how to embed the HornetQ server + within your own code. +
+
+
+ Java EE Examples + Most of the Java EE examples can be run the following way. Simply navigate into the + appropriate example directory and type mvn verify. This will use Arquillian to run the Application + Server and deploy the application. Note that you must have WildFly installed and the JBOSS_HOME environment + variable set. Please refer to the examples documentation for further instructions. + + When running the Java EE examples you may see warning messages in the WildFly log about incompatible client and + server versions. This is normal if a newer version of the HornetQ project is being used with a version of WildFly that + ships an older version of HornetQ. These examples should still complete without any functional errors. + +
+ EJB/JMS Transaction + An example that shows using an EJB and JMS together within a transaction. +
+
+ Resource Adapter Configuration + This example demonstrates how to configure several properties on the HornetQ JCA + resource adaptor. +
+
+ Resource Adapter Remote Server Configuration + This example demonstrates how to configure the HornetQ resource adapter to talk to a remote HornetQ server +
+
+ JMS Bridge + An example demonstrating the use of the HornetQ JMS bridge. +
+
+ MDB (Message Driven Bean) + A simple set of examples of message driven beans, including failover examples. +
+
+ Servlet Transport + An example of how to use the HornetQ servlet transport. +
+
+ Servlet SSL Transport + An example of how to use the HornetQ servlet transport over SSL. +
+
+ XA Recovery + An example of how XA recovery works within the JBoss Application server using + HornetQ. +
+
+
diff --git a/docs/user-manual/en/filter-expressions.xml b/docs/user-manual/en/filter-expressions.xml new file mode 100644 index 0000000000..2cf7bd2762 --- /dev/null +++ b/docs/user-manual/en/filter-expressions.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + + Filter Expressions + HornetQ provides a powerful filter language based on a subset of the SQL 92 + expression syntax. + It is the same as the syntax used for JMS selectors, but the predefined identifiers are + different. For documentation on JMS selector syntax please the JMS javadoc for javax.jms.Message. + Filter expressions are used in several places in HornetQ + + + Predefined Queues. When pre-defining a queue, either in hornetq-configuration.xml or hornetq-jms.xml a filter + expression can be defined for a queue. Only messages that match the filter + expression will enter the queue. + + + Core bridges can be defined with an optional filter expression, only matching + messages will be bridged (see ). + + + Diverts can be defined with an optional filter expression, only matching messages + will be diverted (see ). + + + Filter are also used programmatically when creating consumers, queues and in + several places as described in . + + + There are some differences between JMS selector expressions and HornetQ core + filter expressions. Whereas JMS selector expressions operate on a JMS message, HornetQ + core filter expressions operate on a core message. + The following identifiers can be used in a core filter expressions to refer to attributes + of the core message in an expression: + + + HQPriority. To refer to the priority of a message. Message + priorities are integers with valid values from 0 - 9. 0 is the lowest priority and 9 is the highest. + E.g. HQPriority = 3 AND animal = 'aardvark' + + + HQExpiration. To refer to the expiration time of a message. + The value is a long integer. + + + HQDurable. To refer to whether a message is durable or not. + The value is a string with valid values: DURABLE or NON_DURABLE. + + + HQTimestamp. The timestamp of when the message was created. + The value is a long integer. + + + HQSize. The size of a message in bytes. The value is an + integer. + + + Any other identifiers used in core filter expressions will be assumed to be properties of + the message. + diff --git a/docs/user-manual/en/flow-control.xml b/docs/user-manual/en/flow-control.xml new file mode 100644 index 0000000000..0de82760cc --- /dev/null +++ b/docs/user-manual/en/flow-control.xml @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Flow Control + Flow control is used to limit the flow of data between a client and server, or a server and + another server in order to prevent the client or server being overwhelmed with data. +
+ Consumer Flow Control + This controls the flow of data between the server and the client as the client consumes + messages. For performance reasons clients normally buffer messages before delivering to the + consumer via the receive() method or asynchronously via a message + listener. If the consumer cannot process messages as fast as they are being delivered and + stored in the internal buffer, then you could end up with a situation where messages would + keep building up possibly causing out of memory on the client if they cannot be processed + in time. +
+ Window-Based Flow Control + By default, HornetQ consumers buffer messages from the server in a client side buffer + before the client consumes them. This improves performance: otherwise every time the + client consumes a message, HornetQ would have to go the server to request the next + message. In turn, this message would then get sent to the client side, if one was + available. + A network round trip would be involved for every message and + considerably reduce performance. + To prevent this, HornetQ pre-fetches messages into a buffer on each consumer. The + total maximum size of messages (in bytes) that will be buffered on each consumer is + determined by the consumer-window-size parameter. + By default, the consumer-window-size is set to 1 MiB (1024 * 1024 + bytes). + The value can be: + + + -1 for an unbounded buffer + + + 0 to not buffer any messages. See for working example of a consumer + with no buffering. + + + >0 for a buffer with the given maximum size in + bytes. + + + Setting the consumer window size can considerably improve performance depending on + the messaging use case. As an example, let's consider the two extremes: + + + Fast consumers + + Fast consumers can process messages as fast as they consume them (or even + faster) + To allow fast consumers, set the consumer-window-size to + -1. This will allow unbounded message buffering on the + client side. + Use this setting with caution: it can overflow the client memory if the + consumer is not able to process messages as fast as it receives them. + + + + Slow consumers + + Slow consumers takes significant time to process each message and it is + desirable to prevent buffering messages on the client side so that they can be + delivered to another consumer instead. + Consider a situation where a queue has 2 consumers; 1 of which is very slow. + Messages are delivered in a round robin fashion to both consumers, the fast + consumer processes all of its messages very quickly until its buffer is empty. + At this point there are still messages awaiting to be processed in the buffer + of the slow consumer thus preventing them being processed by the fast consumer. + The fast consumer is therefore sitting idle when it could be processing the + other messages. + To allow slow consumers, set the consumer-window-size to + 0 (for no buffer at all). This will prevent the slow consumer from buffering + any messages on the client side. Messages will remain on the server side ready + to be consumed by other consumers. + Setting this to 0 can give deterministic distribution between multiple + consumers on a queue. + + + + Most of the consumers cannot be clearly identified as fast or slow consumers but are + in-between. In that case, setting the value of consumer-window-size + to optimize performance depends on the messaging use case and requires benchmarks to + find the optimal value, but a value of 1MiB is fine in most cases. +
+ Using Core API + If HornetQ Core API is used, the consumer window size is specified by ServerLocator.setConsumerWindowSize() method and some of the + ClientSession.createConsumer() methods. +
+
+ Using JMS + if JNDI is used to look up the connection factory, the consumer window size is + configured in hornetq-jms.xml: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + + <!-- Set the consumer window size to 0 to have *no* buffer on the client side --> + <consumer-window-size>0</consumer-window-size> +</connection-factory> + If the connection factory is directly instantiated, the consumer window size is + specified by HornetQConnectionFactory.setConsumerWindowSize() + method. + Please see for an example which + shows how to configure HornetQ to prevent consumer buffering when dealing with slow + consumers. +
+
+
+ Rate limited flow control + It is also possible to control the rate at which a consumer can + consume messages. This is a form of throttling and can be used to make sure that a + consumer never consumes messages at a rate faster than the rate specified. + The rate must be a positive integer to enable this functionality and is the maximum + desired message consumption rate specified in units of messages per second. Setting this + to -1 disables rate limited flow control. The default value is + -1. + Please see for a working example of + limiting consumer rate. +
+ Using Core API + If the HornetQ core API is being used the rate can be set via the ServerLocator.setConsumerMaxRate(int consumerMaxRate) method or + alternatively via some of the ClientSession.createConsumer() + methods. +
+
+ Using JMS + If JNDI is used to look up the connection factory, the max rate can be configured + in hornetq-jms.xml: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <!-- We limit consumers created on this connection factory to consume messages at a maximum rate + of 10 messages per sec --> + <consumer-max-rate>10</consumer-max-rate> +</connection-factory> + If the connection factory is directly instantiated, the max rate size can be set + via the HornetQConnectionFactory.setConsumerMaxRate(int + consumerMaxRate) method. + + Rate limited flow control can be used in conjunction with window based flow + control. Rate limited flow control only effects how many messages a client can + consume in a second and not how many messages are in its buffer. So if you had a + slow rate limit and a high window based limit the clients internal buffer would + soon fill up with messages. + + Please see for an example which + shows how to configure HornetQ to prevent consumer buffering when dealing with slow + consumers. +
+
+
+
+ Producer flow control + HornetQ also can limit the amount of data sent from a client to a server to prevent the + server being overwhelmed. +
+ Window based flow control + In a similar way to consumer window based flow control, HornetQ producers, by + default, can only send messages to an address as long as they have sufficient credits to + do so. The amount of credits required to send a message is given by the size of the + message. + As producers run low on credits they request more from the server, when the server + sends them more credits they can send more messages. + The amount of credits a producer requests in one go is known as the window size. + The window size therefore determines the amount of bytes that can be in-flight at any + one time before more need to be requested - this prevents the remoting connection from + getting overloaded. +
+ Using Core API + If the HornetQ core API is being used, window size can be set via the ServerLocator.setProducerWindowSize(int producerWindowSize) + method. +
+
+ Using JMS + If JNDI is used to look up the connection factory, the producer window size can be + configured in hornetq-jms.xml: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <producer-window-size>10</producer-window-size> +</connection-factory> + If the connection factory is directly instantiated, the producer window size can + be set via the HornetQConnectionFactory.setProducerWindowSize(int + producerWindowSize) method. +
+
+ Blocking producer window based flow control + Normally the server will always give the same number of credits as have been + requested. However, it is also possible to set a maximum size on any address, and the + server will never send more credits than could cause the address's upper memory limit + to be exceeded. + For example, if I have a JMS queue called "myqueue", I could set the maximum + memory size to 10MiB, and the the server will control the number of credits sent to + any producers which are sending any messages to myqueue such that the total messages + in the queue never exceeds 10MiB. + When the address gets full, producers will block on the client side until more + space frees up on the address, i.e. until messages are consumed from the queue thus + freeing up space for more messages to be sent. + We call this blocking producer flow control, and it's an efficient way to prevent + the server running out of memory due to producers sending more messages than can be + handled at any time. + It is an alternative approach to paging, which does not block producers but + instead pages messages to storage. + To configure an address with a maximum size and tell the server that you want to + block producers for this address if it becomes full, you need to define an + AddressSettings () block for the + address and specify max-size-bytes and address-full-policy + The address block applies to all queues registered to that address. I.e. the total + memory for all queues bound to that address will not exceed max-size-bytes. In the case of JMS topics this means the total memory of all subscriptions in the topic won't + exceed max-size-bytes. + Here's an example: + +<address-settings> + <address-setting match="jms.queue.exampleQueue"> + <max-size-bytes>100000</max-size-bytes> + <address-full-policy>BLOCK</address-full-policy> + </address-setting> +</address-settings> + The above example would set the max size of the JMS queue "exampleQueue" to be + 100000 bytes and would block any producers sending to that address to prevent that + max size being exceeded. + Note the policy must be set to BLOCK to enable blocking producer + flow control. + Note that in the default configuration all addresses are set to block producers after 10 MiB of message data + is in the address. This means you cannot send more than 10MiB of message data to an address without it being consumed before the producers + will be blocked. If you do not want this behaviour increase the max-size-bytes parameter or change the + address full message policy. + +
+
+
+ Rate limited flow control + HornetQ also allows the rate a producer can emit message to be limited, in units of + messages per second. By specifying such a rate, HornetQ will ensure that producer never + produces messages at a rate higher than that specified. + The rate must be a positive integer to enable this functionality and is the maximum + desired message consumption rate specified in units of messages per second. Setting this + to -1 disables rate limited flow control. The default value is + -1. + Please see the for a working example + of limiting producer rate. +
+ Using Core API + If the HornetQ core API is being used the rate can be set via the ServerLocator.setProducerMaxRate(int consumerMaxRate) method or + alternatively via some of the ClientSession.createProducer() + methods. +
+
+ Using JMS + If JNDI is used to look up the connection factory, the max rate can be configured + in hornetq-jms.xml: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <!-- We limit producers created on this connection factory to produce messages at a maximum rate + of 10 messages per sec --> + <producer-max-rate>10</producer-max-rate> +</connection-factory> + If the connection factory is directly instantiated, the max rate size can be set + via the HornetQConnectionFactory.setProducerMaxRate(int + consumerMaxRate) method. +
+
+
+
diff --git a/docs/user-manual/en/ha.xml b/docs/user-manual/en/ha.xml new file mode 100644 index 0000000000..f4b2d2bed5 --- /dev/null +++ b/docs/user-manual/en/ha.xml @@ -0,0 +1,539 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + High Availability and Failover + + We define high availability as the ability for the system to continue + functioning after failure of one or more of the servers. + + A part of high availability is failover which we define as the + ability for client connections to migrate from one server to another in event of + server failure so client applications can continue to operate. + +
+ Live - Backup Groups + + HornetQ allows servers to be linked together as live - backup + groups where each live server can have 1 or more backup servers. A backup server is owned by + only one live server. Backup servers are not operational until failover occurs, however 1 + chosen backup, which will be in passive mode, announces its status and waits to take over + the live servers work + + Before failover, only the live server is serving the HornetQ clients while the backup + servers remain passive or awaiting to become a backup server. When a live server crashes or + is brought down in the correct mode, the backup server currently in passive mode will become + live and another backup server will become passive. If a live server restarts after a + failover then it will have priority and be the next server to become live when the current + live server goes down, if the current live server is configured to allow automatic failback + then it will detect the live server coming back up and automatically stop. + +
+ HA modes + HornetQ supports two different strategies for backing up a server shared + store and replication. + + Only persistent message data will survive failover. Any non persistent message + data will not be available after failover. + +
+ +
+ Data Replication + Support for network-based data replication was added in version 2.3. + When using replication, the live and the backup servers do not share the same + data directories, all data synchronization is done over the network. Therefore all (persistent) + data received by the live server will be duplicated to the backup. + + Notice that upon start-up the backup server will first need to synchronize all + existing data from the live server before becoming capable of replacing the live + server should it fail. So unlike when using shared storage, a replicating backup will + not be a fully operational backup right after start-up, but only after it finishes + synchronizing the data with its live server. The time it will take for this to happen + will depend on the amount of data to be synchronized and the connection speed. + + + Synchronization occurs in parallel with current network traffic so this won't cause any + blocking on current clients. + + Replication will create a copy of the data at the backup. One issue to be aware + of is: in case of a successful fail-over, the backup's data will be newer than + the one at the live's storage. If you configure your live server to perform a + 'fail-back' when restarted, it will synchronize + its data with the backup's. If both servers are shutdown, the administrator will have + to determine which one has the lastest data. + + The replicating live and backup pair must be part of a cluster. The Cluster + Connection also defines how backup servers will find the remote live servers to pair + with. Refer to for details on how this is done, and how + to configure a cluster connection. Notice that: + + + + Both live and backup servers must be part of the same cluster. Notice + that even a simple live/backup replicating pair will require a cluster configuration. + + + Their cluster user and password must match. + + + + Within a cluster, there are two ways that a backup server will locate a live server to replicate + from, these are: + + + + specifying a node group. You can specify a group of live servers that a backup + server can connect to. This is done by configuring backup-group-name in the main + hornetq-configuration.xml. A Backup server will only connect to a live server that + shares the same node group name + + + connecting to any live. Simply put not configuring backup-group-name + will allow a backup server to connect to any live server + + + + A backup-group-name example: suppose you have 5 live servers and 6 backup + servers: + + + live1, live2, live3: with + backup-group-name=fish + + + live4, live5: with backup-group-name=bird + + + backup1, backup2, backup3, + backup4: with backup-group-name=fish + + + backup5, backup6: with + backup-group-name=bird + + + After joining the cluster the backups with backup-group-name=fish will + search for live servers with backup-group-name=fish to pair with. Since there + is one backup too many, the fish will remain with one spare backup. + The 2 backups with backup-group-name=bird (backup5 and + backup6) will pair with live servers live4 and + live5. + + The backup will search for any live server that it is configured to connect to. It then tries to + replicate with each live server in turn until it finds a live server that has no current backup + configured. If no live server is available it will wait until the cluster topology changes and + repeats the process. + + This is an important distinction from a shared-store backup, as in that case if + the backup starts and does not find its live server, the server will just activate + and start to serve client requests. In the replication case, the backup just keeps + waiting for a live server to pair with. Notice that in replication the backup server + does not know whether any data it might have is up to date, so it really cannot + decide to activate automatically. To activate a replicating backup server using the data + it has, the administrator must change its configuration to make a live server of it, + that change backup=true to backup=false. + + + Much like in the shared-store case, when the live server stops or crashes, + its replicating backup will become active and take over its duties. Specifically, + the backup will become active when it loses connection to its live server. This can + be problematic because this can also happen because of a temporary network + problem. In order to address this issue, the backup will try to determine whether it + still can connect to the other servers in the cluster. If it can connect to more + than half the servers, it will become active, if more than half the servers also + disappeared with the live, the backup will wait and try reconnecting with the live. + This avoids a split brain situation. + +
+ Configuration + + To configure the live and backup servers to be a replicating pair, configure + both servers' hornetq-configuration.xml to have: + + +<!-- FOR BOTH LIVE AND BACKUP SERVERS' --> +<shared-store>false</shared-store> +. +. +<cluster-connections> + <cluster-connection name="my-cluster"> + ... + </cluster-connection> +</cluster-connections> + + + The backup server must also be configured as a backup. + + +<backup>true</backup> + +
+
+ +
+ Shared Store + When using a shared store, both live and backup servers share the + same entire data directory using a shared file system. + This means the paging directory, journal directory, large messages and binding + journal. + When failover occurs and a backup server takes over, it will load the + persistent storage from the shared file system and clients can connect to + it. + This style of high availability differs from data replication in that it + requires a shared file system which is accessible by both the live and backup + nodes. Typically this will be some kind of high performance Storage Area Network + (SAN). We do not recommend you use Network Attached Storage (NAS), e.g. NFS + mounts to store any shared journal (NFS is slow). + The advantage of shared-store high availability is that no replication occurs + between the live and backup nodes, this means it does not suffer any performance + penalties due to the overhead of replication during normal operation. + The disadvantage of shared store replication is that it requires a shared file + system, and when the backup server activates it needs to load the journal from + the shared store which can take some time depending on the amount of data in the + store. + If you require the highest performance during normal operation, have access to + a fast SAN, and can live with a slightly slower failover (depending on amount of + data), we recommend shared store high availability + + +
+ Configuration + To configure the live and backup servers to share their store, configure + all hornetq-configuration.xml: + +<shared-store>true</shared-store> + + Additionally, each backup server must be flagged explicitly as a backup: + +<backup>true</backup> + In order for live - backup groups to operate properly with a shared store, + both servers must have configured the location of journal directory to point + to the same shared location (as explained in + ) + + todo write something about GFS + + Also each node, live and backups, will need to have a cluster connection defined even if not + part of a cluster. The Cluster Connection info defines how backup servers announce there presence + to its live server or any other nodes in the cluster. Refer to for details + on how this is done. +
+
+
+ Failing Back to live Server + After a live server has failed and a backup taken has taken over its duties, you may want to + restart the live server and have clients fail back. + In case of "shared disk", simply restart the original live + server and kill the new live server. You can do this by killing the process itself or just waiting for the server to crash naturally. + In case of a replicating live server that has been replaced by a remote backup you will need to also set check-for-live-server. This option is necessary because a starting server cannot know whether there is a (remote) server running in its place, so with this option set, the server will check the cluster for another server using its node-ID and if it finds one it will try initiate a fail-back. This option only applies to live servers that are restarting, it is ignored by backup servers. + It is also possible to cause failover to occur on normal server shutdown, to enable + this set the following property to true in the hornetq-configuration.xml + configuration file like so: + +<failover-on-shutdown>true</failover-on-shutdown> + By default this is set to false, if by some chance you have set this to false but still + want to stop the server normally and cause failover then you can do this by using the management + API as explained at + You can also force the running live server to shutdown when the old live server comes back up allowing + the original live server to take over automatically by setting the following property in the + hornetq-configuration.xml configuration file as follows: + +<allow-failback>true</allow-failback> + In replication HA mode you need to set an extra property check-for-live-server + to true. If set to true, during start-up a live server will first search the cluster for another server using its nodeID. If it finds one, it will contact this server and try to "fail-back". Since this is a remote replication scenario, the "starting live" will have to synchronize its data with the server running with its ID, once they are in sync, it will request the other server (which it assumes it is a back that has assumed its duties) to shutdown for it to take over. This is necessary because otherwise the live server has no means to know whether there was a fail-over or not, and if there was if the server that took its duties is still running or not. To configure this option at your hornetq-configuration.xml configuration file as follows: + +<check-for-live-server>true</check-for-live-server> +
+
+ Colocated Backup Servers + It is also possible when running standalone to colocate backup servers in the same + JVM as another live server.The colocated backup will become a backup for another live + server in the cluster but not the one it shares the vm with. To configure a colocated + backup server simply add the following to the hornetq-configuration.xml file + +<backup-servers> + <backup-server name="backup2" inherit-configuration="true" port-offset="1000"> + <configuration> + <bindings-directory>target/server1/data/messaging/bindings</bindings-directory> + <journal-directory>target/server1/data/messaging/journal</journal-directory> + <large-messages-directory>target/server1/data/messaging/largemessages</large-messages-directory> + <paging-directory>target/server1/data/messaging/paging</paging-directory> + </configuration> + </backup-server> +</backup-servers> + + you will notice 3 attributes on the backup-server, name + which is a unique name used to identify the backup server, inherit-configuration + which if set to true means the server will inherit the configuration of its parent server + and port-offset which is what the port for any netty connectors or + acceptors will be increased by if the configuration is inherited. + it is also possible to configure the backup server in the normal way, in this example you will + notice we have changed the journal directories. +
+
+
+ Failover Modes + HornetQ defines two types of client failover: + + + Automatic client failover + + + Application-level client failover + + + HornetQ also provides 100% transparent automatic reattachment of connections to the + same server (e.g. in case of transient network problems). This is similar to failover, + except it is reconnecting to the same server and is discussed in + + During failover, if the client has consumers on any non persistent or temporary + queues, those queues will be automatically recreated during failover on the backup node, + since the backup node will not have any knowledge of non persistent queues. +
+ Automatic Client Failover + HornetQ clients can be configured to receive knowledge of all live and backup servers, so + that in event of connection failure at the client - live server connection, the + client will detect this and reconnect to the backup server. The backup server will + then automatically recreate any sessions and consumers that existed on each + connection before failover, thus saving the user from having to hand-code manual + reconnection logic. + HornetQ clients detect connection failure when it has not received packets from + the server within the time given by client-failure-check-period + as explained in section . If the client does not + receive data in good time, it will assume the connection has failed and attempt + failover. Also if the socket is closed by the OS, usually if the server process is + killed rather than the machine itself crashing, then the client will failover straight away. + + HornetQ clients can be configured to discover the list of live-backup server groups in a + number of different ways. They can be configured explicitly or probably the most + common way of doing this is to use server discovery for the + client to automatically discover the list. For full details on how to configure + server discovery, please see . + Alternatively, the clients can explicitly connect to a specific server and download + the current servers and backups see . + To enable automatic client failover, the client must be configured to allow + non-zero reconnection attempts (as explained in ). + By default failover will only occur after at least one connection has been made to + the live server. In other words, by default, failover will not occur if the client + fails to make an initial connection to the live server - in this case it will simply + retry connecting to the live server according to the reconnect-attempts property and + fail after this number of attempts. +
+ Failing over on the Initial Connection + + Since the client does not learn about the full topology until after the first + connection is made there is a window where it does not know about the backup. If a failure happens at + this point the client can only try reconnecting to the original live server. To configure + how many attempts the client will make you can set the property initialConnectAttempts + on the ClientSessionFactoryImpl or HornetQConnectionFactory or + initial-connect-attempts in xml. The default for this is 0, that + is try only once. Once the number of attempts has been made an exception will be thrown. + +
+ For examples of automatic failover with transacted and non-transacted JMS + sessions, please see and . +
+ A Note on Server Replication + HornetQ does not replicate full server state between live and backup servers. + When the new session is automatically recreated on the backup it won't have any + knowledge of messages already sent or acknowledged in that session. Any + in-flight sends or acknowledgements at the time of failover might also be + lost. + By replicating full server state, theoretically we could provide a 100% + transparent seamless failover, which would avoid any lost messages or + acknowledgements, however this comes at a great cost: replicating the full + server state (including the queues, session, etc.). This would require + replication of the entire server state machine; every operation on the live + server would have to replicated on the replica server(s) in the exact same + global order to ensure a consistent replica state. This is extremely hard to do + in a performant and scalable way, especially when one considers that multiple + threads are changing the live server state concurrently. + It is possible to provide full state machine replication using techniques such + as virtual synchrony, but this does not scale + well and effectively serializes all operations to a single thread, dramatically + reducing concurrency. + Other techniques for multi-threaded active replication exist such as + replicating lock states or replicating thread scheduling but this is very hard + to achieve at a Java level. + Consequently it has decided it was not worth massively reducing performance + and concurrency for the sake of 100% transparent failover. Even without 100% + transparent failover, it is simple to guarantee once and + only once delivery, even in the case of failure, by using a + combination of duplicate detection and retrying of transactions. However this is + not 100% transparent to the client code. +
+
+ Handling Blocking Calls During Failover + If the client code is in a blocking call to the server, waiting for a response + to continue its execution, when failover occurs, the new session will not have + any knowledge of the call that was in progress. This call might otherwise hang + for ever, waiting for a response that will never come. + To prevent this, HornetQ will unblock any blocking calls that were in progress + at the time of failover by making them throw a javax.jms.JMSException (if using JMS), or a HornetQException with error code HornetQException.UNBLOCKED. It is up to the client code to catch + this exception and retry any operations if desired. + If the method being unblocked is a call to commit(), or prepare(), then the + transaction will be automatically rolled back and HornetQ will throw a javax.jms.TransactionRolledBackException (if using JMS), or a + HornetQException with error code HornetQException.TRANSACTION_ROLLED_BACK if using the core + API. +
+
+ Handling Failover With Transactions + If the session is transactional and messages have already been sent or + acknowledged in the current transaction, then the server cannot be sure that + messages sent or acknowledgements have not been lost during the failover. + Consequently the transaction will be marked as rollback-only, and any + subsequent attempt to commit it will throw a javax.jms.TransactionRolledBackException (if using JMS), or a + HornetQException with error code HornetQException.TRANSACTION_ROLLED_BACK if using the core + API. + + 2 phase commit + + The caveat to this rule is when XA is used either via JMS or through the core API. + If 2 phase commit is used and prepare has already been called then rolling back could + cause a HeuristicMixedException. Because of this the commit will throw + a XAException.XA_RETRY exception. This informs the Transaction Manager + that it should retry the commit at some later point in time, a side effect of this is + that any non persistent messages will be lost. To avoid this use persistent + messages when using XA. With acknowledgements this is not an issue since they are + flushed to the server before prepare gets called. + + + It is up to the user to catch the exception, and perform any client side local + rollback code as necessary. There is no need to manually rollback the session - + it is already rolled back. The user can then just retry the transactional + operations again on the same session. + HornetQ ships with a fully functioning example demonstrating how to do this, + please see + If failover occurs when a commit call is being executed, the server, as + previously described, will unblock the call to prevent a hang, since no response + will come back. In this case it is not easy for the client to determine whether + the transaction commit was actually processed on the live server before failure + occurred. + + + If XA is being used either via JMS or through the core API then an XAException.XA_RETRY + is thrown. This is to inform Transaction Managers that a retry should occur at some point. At + some later point in time the Transaction Manager will retry the commit. If the original + commit has not occurred then it will still exist and be committed, if it does not exist + then it is assumed to have been committed although the transaction manager may log a warning. + + + To remedy this, the client can simply enable duplicate detection () in the transaction, and retry the + transaction operations again after the call is unblocked. If the transaction had + indeed been committed on the live server successfully before failover, then when + the transaction is retried, duplicate detection will ensure that any durable + messages resent in the transaction will be ignored on the server to prevent them + getting sent more than once. + + By catching the rollback exceptions and retrying, catching unblocked calls + and enabling duplicate detection, once and only once delivery guarantees for + messages can be provided in the case of failure, guaranteeing 100% no loss + or duplication of messages. + +
+
+ Handling Failover With Non Transactional Sessions + If the session is non transactional, messages or acknowledgements can be lost + in the event of failover. + If you wish to provide once and only once + delivery guarantees for non transacted sessions too, enabled duplicate + detection, and catch unblock exceptions as described in +
+
+
+ Getting Notified of Connection Failure + JMS provides a standard mechanism for getting notified asynchronously of + connection failure: java.jms.ExceptionListener. Please consult + the JMS javadoc or any good JMS tutorial for more information on how to use + this. + The HornetQ core API also provides a similar feature in the form of the class + org.hornet.core.client.SessionFailureListener + Any ExceptionListener or SessionFailureListener instance will always be called by + HornetQ on event of connection failure, irrespective of whether the connection was successfully failed over, + reconnected or reattached, however you can find out if reconnect or reattach has happened + by either the failedOver flag passed in on the connectionFailed + on SessionfailureListener or by inspecting the error code on the + javax.jms.JMSException which will be one of the following: + + JMSException error codes + + + + + + error code + Description + + + + + FAILOVER + + Failover has occurred and we have successfully reattached or reconnected. + + + + DISCONNECT + + No failover has occurred and we are disconnected. + + + + +
+
+
+ Application-Level Failover + In some cases you may not want automatic client failover, and prefer to handle any + connection failure yourself, and code your own manually reconnection logic in your + own failure handler. We define this as application-level + failover, since the failover is handled at the user application level. + To implement application-level failover, if you're using JMS then you need to set + an ExceptionListener class on the JMS connection. The + ExceptionListener will be called by HornetQ in the event that + connection failure is detected. In your ExceptionListener, you + would close your old JMS connections, potentially look up new connection factory + instances from JNDI and creating new connections. In this case you may well be using + HA-JNDI + to ensure that the new connection factory is looked up from a different server. + For a working example of application-level failover, please see + . + If you are using the core API, then the procedure is very similar: you would set a + FailureListener on the core ClientSession + instances. +
+
+
diff --git a/docs/user-manual/en/images/architecture1.jpg b/docs/user-manual/en/images/architecture1.jpg new file mode 100644 index 0000000000..cb1161f645 Binary files /dev/null and b/docs/user-manual/en/images/architecture1.jpg differ diff --git a/docs/user-manual/en/images/architecture2.jpg b/docs/user-manual/en/images/architecture2.jpg new file mode 100644 index 0000000000..274f578a5e Binary files /dev/null and b/docs/user-manual/en/images/architecture2.jpg differ diff --git a/docs/user-manual/en/images/architecture3.jpg b/docs/user-manual/en/images/architecture3.jpg new file mode 100644 index 0000000000..3c1dfd5742 Binary files /dev/null and b/docs/user-manual/en/images/architecture3.jpg differ diff --git a/docs/user-manual/en/images/console1.png b/docs/user-manual/en/images/console1.png new file mode 100644 index 0000000000..19b6cbd835 Binary files /dev/null and b/docs/user-manual/en/images/console1.png differ diff --git a/docs/user-manual/en/images/ha-replicated-store.png b/docs/user-manual/en/images/ha-replicated-store.png new file mode 100644 index 0000000000..9065dfee67 Binary files /dev/null and b/docs/user-manual/en/images/ha-replicated-store.png differ diff --git a/docs/user-manual/en/images/ha-shared-store.png b/docs/user-manual/en/images/ha-shared-store.png new file mode 100644 index 0000000000..0be2766553 Binary files /dev/null and b/docs/user-manual/en/images/ha-shared-store.png differ diff --git a/docs/user-manual/en/images/hornetQ-banner_final.png b/docs/user-manual/en/images/hornetQ-banner_final.png new file mode 100644 index 0000000000..6388dff1f5 Binary files /dev/null and b/docs/user-manual/en/images/hornetQ-banner_final.png differ diff --git a/docs/user-manual/en/images/hornetQ_logo_600px.png b/docs/user-manual/en/images/hornetQ_logo_600px.png new file mode 100644 index 0000000000..b71f4ba130 Binary files /dev/null and b/docs/user-manual/en/images/hornetQ_logo_600px.png differ diff --git a/docs/user-manual/en/intercepting-operations.xml b/docs/user-manual/en/intercepting-operations.xml new file mode 100644 index 0000000000..60db27417c --- /dev/null +++ b/docs/user-manual/en/intercepting-operations.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + + Intercepting Operations + HornetQ supports interceptors to intercept packets entering + and exiting the server. Incoming and outgoing interceptors are be called for any packet + entering or exiting the server respectively. This allows custom code to be executed, + e.g. for auditing packets, filtering or other reasons. Interceptors can change the + packets they intercept. This makes interceptors powerful, but also potentially + dangerous. +
+ Implementing The Interceptors + An interceptor must implement the Interceptor interface: + +package org.hornetq.api.core.interceptor; + +public interface Interceptor +{ + boolean intercept(Packet packet, RemotingConnection connection) throws HornetQException; +} + The returned boolean value is important: + + + if true is returned, the process continues normally + + + if false is returned, the process is aborted, no other interceptors + will be called and the packet will not be processed further by the server. + + +
+
+ Configuring The Interceptors + Both incoming and outgoing interceptors are configured in + hornetq-configuration.xml: + +<remoting-incoming-interceptors> + <class-name>org.hornetq.jms.example.LoginInterceptor</class-name> + <class-name>org.hornetq.jms.example.AdditionalPropertyInterceptor</class-name> +</remoting-incoming-interceptors> + +<remoting-outgoing-interceptors> + <class-name>org.hornetq.jms.example.LogoutInterceptor</class-name> + <class-name>org.hornetq.jms.example.AdditionalPropertyInterceptor</class-name> +</remoting-outgoing-interceptors> + The interceptors classes (and their dependencies) must be added to the server classpath + to be properly instantiated and called. +
+
+ Interceptors on the Client Side + The interceptors can also be run on the client side to intercept packets either sent by the + client to the server or by the server to the client. This is done by adding the interceptor to + the ServerLocator with the addIncomingInterceptor(Interceptor) or + addOutgoingInterceptor(Interceptor) methods. + As noted above, if an interceptor returns false then the sending of the + packet is aborted which means that no other interceptors are be called and the packet is not + be processed further by the client. Typically this process happens transparently to the client + (i.e. it has no idea if a packet was aborted or not). However, in the case of an outgoing packet + that is sent in a blocking fashion a HornetQException will + be thrown to the caller. The exception is thrown because blocking sends provide reliability and + it is considered an error for them not to succeed. Blocking sends occurs when, + for example, an application invokes setBlockOnNonDurableSend(true) or + setBlockOnDurableSend(true) on its ServerLocator or if an + application is using a JMS connection factory retrieved from JNDI that has either + block-on-durable-send or block-on-non-durable-send + set to true. Blocking is also used for packets dealing with transactions (e.g. + commit, roll-back, etc.). The HornetQException thrown will contain the name + of the interceptor that returned false. + As on the server, the client interceptor classes (and their dependencies) must be added to the classpath + to be properly instantiated and invoked. +
+
+ Example + See for an example which + shows how to use interceptors to add properties to a message on the server. +
+
diff --git a/docs/user-manual/en/interoperability.xml b/docs/user-manual/en/interoperability.xml new file mode 100644 index 0000000000..e4261d70b7 --- /dev/null +++ b/docs/user-manual/en/interoperability.xml @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Interoperability +
+ Stomp + Stomp is a text-orientated wire protocol that allows + Stomp clients to communicate with Stomp Brokers. HornetQ now supports Stomp 1.0, 1.1 and 1.2. + Stomp clients are available for + several languages and platforms making it a good choice for interoperability. +
+ Native Stomp support + HornetQ provides native support for Stomp. To be able to send and receive Stomp messages, + you must configure a NettyAcceptor with a protocols + parameter set to have stomp: + +<acceptor name="stomp-acceptor"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + <param key="protocols" value="STOMP"/> + <param key="port" value="61613"/> +</acceptor> + With this configuration, HornetQ will accept Stomp connections on + the port 61613 (which is the default port of the Stomp brokers). + See the stomp example which shows how to configure a HornetQ server with Stomp. +
+ Limitations + Message acknowledgements are not transactional. The ACK frame can not be part of a transaction + (it will be ignored if its transaction header is set). +
+
+ Stomp 1.1/1.2 Notes +
+ Virtual Hosting + HornetQ currently doesn't support virtual hosting, which means the 'host' header + in CONNECT fram will be ignored. +
+
+ Heart-beating + HornetQ specifies a minimum value for both client and server heart-beat intervals. + The minimum interval for both client and server heartbeats is 500 milliseconds. That means if + a client sends a CONNECT frame with heartbeat values lower than 500, the server will defaults + the value to 500 milliseconds regardless the values of the 'heart-beat' header in the frame. +
+
+
+ +
+ Mapping Stomp destinations to HornetQ addresses and queues + Stomp clients deals with destinations when sending messages and subscribing. + Destination names are simply strings which are mapped to some form of destination on the + server - how the server translates these is left to the server implementation. + In HornetQ, these destinations are mapped to addresses and queues. + When a Stomp client sends a message (using a SEND frame), the specified destination is mapped + to an address. + When a Stomp client subscribes (or unsubscribes) for a destination (using a SUBSCRIBE + or UNSUBSCRIBE frame), the destination is mapped to a HornetQ queue. +
+
+ STOMP and connection-ttl + Well behaved STOMP clients will always send a DISCONNECT frame before closing their connections. In this case the server + will clear up any server side resources such as sessions and consumers synchronously. However if STOMP clients exit without + sending a DISCONNECT frame or if they crash the server will have no way of knowing immediately whether the client is still alive + or not. STOMP connections therefore default to a connection-ttl value of 1 minute (see chapter on connection-ttl for more information. This value can be overridden using connection-ttl-override. + + If you need a specific connection-ttl for your stomp connections without affecting the connection-ttl-override setting, you + can configure your stomp acceptor with the "connection-ttl" property, which is used to set the ttl for connections that are + created from that acceptor. For example: + + +<acceptor name="stomp-acceptor"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + <param key="protocols" value="STOMP"/> + <param key="port" value="61613"/> + <param key="connection-ttl" value="20000"/> +</acceptor> + The above configuration will make sure that any stomp connection that is created from that acceptor will have its + connection-ttl set to 20 seconds. + + Please note that the STOMP protocol version 1.0 does not contain any heartbeat frame. It is therefore the user's + responsibility to make sure data is sent within connection-ttl or the server will assume the client is dead and clean up server + side resources. With Stomp 1.1 users can use heart-beats to maintain the life cycle of stomp + connections. +
+ +
+ Stomp and JMS interoperability +
+ Using JMS destinations + As explained in , JMS destinations are also mapped to HornetQ addresses and queues. + If you want to use Stomp to send messages to JMS destinations, the Stomp destinations must follow the same convention: + + + send or subscribe to a JMS Queue by prepending the queue name by jms.queue.. + For example, to send a message to the orders JMS Queue, the Stomp client must send the frame: + +SEND +destination:jms.queue.orders + +hello queue orders +^@ + + + send or subscribe to a JMS Topic by prepending the topic name by jms.topic.. + For example to subscribe to the stocks JMS Topic, the Stomp client must send the frame: + +SUBSCRIBE +destination:jms.topic.stocks + +^@ + + +
+ +
+ Sending and consuming Stomp message from JMS or HornetQ Core API + Stomp is mainly a text-orientated protocol. To make it simpler to interoperate with JMS and HornetQ Core API, + our Stomp implementation checks for presence of the content-length header to decide how to map a Stomp message + to a JMS Message or a Core message. + + If the Stomp message does not have a content-length header, it will be mapped to a JMS TextMessage + or a Core message with a single nullable SimpleString in the body buffer. + Alternatively, if the Stomp message has a content-length header, + it will be mapped to a JMS BytesMessage + or a Core message with a byte[] in the body buffer. + The same logic applies when mapping a JMS message or a Core message to Stomp. A Stomp client can check the presence + of the content-length header to determine the type of the message body (String or bytes). +
+
+ Message IDs for Stomp messages + When receiving Stomp messages via a JMS consumer or a QueueBrowser, the messages have + no properties like JMSMessageID by default. However this may bring some inconvenience to + clients who wants an ID for their purpose. HornetQ Stomp provides a parameter to enable + message ID on each incoming Stomp message. If you want each Stomp message to have a unique ID, + just set the stomp-enable-message-id to true. For example: + +<acceptor name="stomp-acceptor"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + <param key="protocols" value="STOMP"/> + <param key="port" value="61613"/> + <param key="stomp-enable-message-id" value="true"/> +</acceptor> + When the server starts with the above setting, each stomp message sent through this + acceptor will have an extra property added. The property key is + hq-message-id and the value is a String representation of a long type internal + message id prefixed with "STOMP", like: + +hq-message-id : STOMP12345 + If stomp-enable-message-id is not specified in the configuration, default + is false. +
+
+ Handling of Large Messages with Stomp + Stomp clients may send very large bodys of frames which can exceed the size of HornetQ + server's internal buffer, causing unexpected errors. To prevent this situation from happening, + HornetQ provides a stomp configuration attribute stomp-min-large-message-size. + This attribute can be configured inside a stomp acceptor, as a parameter. For example: + + <acceptor name="stomp-acceptor"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + <param key="protocols" value="STOMP"/> + <param key="port" value="61613"/> + <param key="stomp-min-large-message-size" value="10240"/> +</acceptor> + The type of this attribute is integer. When this attributed is configured, HornetQ server + will check the size of the body of each Stomp frame arrived from connections established with + this acceptor. If the size of the body is equal or greater than the value of + stomp-min-large-message, the message will be persisted as a large message. + When a large message is delievered to a stomp consumer, the HorentQ server will automatically + handle the conversion from a large message to a normal message, before sending it to the client. + If a large message is compressed, the server will uncompressed it before sending it to + stomp clients. The default value of stomp-min-large-message-size is the same + as the default value of min-large-message-size. +
+
+ +
+ Stomp Over Web Sockets + HornetQ also support Stomp over Web Sockets. Modern web browser which support Web Sockets can send and receive + Stomp messages from HornetQ. + To enable Stomp over Web Sockets, you must configure a NettyAcceptor with a protocol + parameter set to stomp_ws: + +<acceptor name="stomp-ws-acceptor"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + <param key="protocols" value="STOMP_WS"/> + <param key="port" value="61614"/> +</acceptor> + With this configuration, HornetQ will accept Stomp connections over Web Sockets on + the port 61614 with the URL path /stomp. + Web browser can then connect to ws://<server>:61614/stomp using a Web Socket to send and receive Stomp + messages. + A companion JavaScript library to ease client-side development is available from + GitHub (please see + its documentation for a complete description). + The stomp-websockets example shows how to configure HornetQ server to have web browsers and Java + applications exchanges messages on a JMS topic. +
+ +
+ StompConnect + StompConnect is a server that + can act as a Stomp broker and proxy the Stomp protocol to the standard JMS API. + Consequently, using StompConnect it is possible to turn HornetQ into a Stomp Broker and + use any of the available stomp clients. These include clients written in C, C++, c# and + .net etc. + To run StompConnect first start the HornetQ server and make sure that it is using + JNDI. + Stomp requires the file jndi.properties to be available on the + classpath. This should look something like: + +java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.provider.url=jnp://localhost:1099 +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces + Make sure this file is in the classpath along with the StompConnect jar and the + HornetQ jars and simply run java org.codehaus.stomp.jms.Main. +
+ +
+
+ REST + Please see +
+
+ AMQP + HornetQ supports the AMQP 1.0 + specification. To enable AMQP you must configure a Netty Acceptor to receive AMQP clients, like so: + +<acceptor name="stomp-acceptor"> +<factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> +<param key="protocols" value="AMQP"/> +<param key="port" value="5672"/> +</acceptor> + + HornetQ will then accept AMQP 1.0 clients on port 5672 which is the default AMQP port. + There are 2 Stomp examples available see proton-j and proton-ruby which use the qpid Java and Ruby clients + respectively +
+ AMQP and security + The HornetQ Server accepts AMQP SASL Authentication and will use this to map onto the underlying session created + for the connection so you can use the normal HornetQ security configuration. +
+
+ AMQP Links + An AMQP Link is a uni directional transport for messages between a source and a target, i.e. a client and the + HornetQ Broker. A link will have an endpoint of which there are 2 kinds, a Sender and A Receiver. At the Broker a + Sender will have its messages converted into a HornetQ Message and forwarded to its destination or target. A + Receiver will map onto a HornetQ Server Consumer and convert HornetQ messages back into AMQP messages before being delivered. +
+
+ AMQP and destinations + If an AMQP Link is dynamic then a temporary queue will be created and either the remote source or remote + target address will be set to the name of the temporary queue. If the Link is not dynamic then the the address + of the remote target or source will used for the queue. If this does not exist then an exception will be sent + For the next version we will add a flag to aut create durable queue but for now you will have to add them via + the configuration +
+
+ AMQP and Coordinations - Handling Transactions + An AMQP links target can also be a Coordinator, the Coordinator is used to handle transactions. If a + coordinator is used the the underlying HormetQ Server session will be transacted and will be either rolled back + or committed via the coordinator. + AMQP allows the use of multiple transactions per session, amqp:multi-txns-per-ssn, + however in this version HornetQ will only support single transactions per session +
+
+
diff --git a/docs/user-manual/en/jms-bridge.xml b/docs/user-manual/en/jms-bridge.xml new file mode 100644 index 0000000000..16bdfbf007 --- /dev/null +++ b/docs/user-manual/en/jms-bridge.xml @@ -0,0 +1,450 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + The JMS Bridge + HornetQ includes a fully functional JMS message bridge. + The function of the bridge is to consume messages from a source queue or topic, and + send them to a target queue or topic, typically on a different server. + The source and target servers do not have to be in the same cluster which makes + bridging suitable for reliably sending messages from one cluster to another, for + instance across a WAN, and where the connection may be unreliable. + A bridge can be deployed as a standalone application, with HornetQ standalone server or inside a JBoss AS + instance. The source and the target can be located in the same virtual machine or another one. + The bridge can also be used to bridge messages from other non HornetQ JMS servers, as + long as they are JMS 1.1 compliant.Do not confuse a JMS bridge with a core + bridge. A JMS bridge can be used to bridge any two JMS 1.1 compliant JMS + providers and uses the JMS API. A core bridge (described in ) is used to bridge any two HornetQ instances and + uses the core API. Always use a core bridge if you can in preference to a JMS + bridge. The core bridge will typically provide better performance than a JMS + bridge. Also the core bridge can provide once and only once + delivery guarantees without using XA. + The bridge has built-in resilience to failure so if the source or target server + connection is lost, e.g. due to network failure, the bridge will retry connecting to the + source and/or target until they come back online. When it comes back online it will + resume operation as normal. + The bridge can be configured with an optional JMS selector, so it will only consume + messages matching that JMS selector + It can be configured to consume from a queue or a topic. When it consumes from a topic + it can be configured to consume using a non durable or durable subscription + Typically, the bridge is deployed by the JBoss Micro Container via a beans configuration file. + This would typically be deployed inside the JBoss Application Server and the following + example shows an example of a beans file that bridges 2 destinations which are actually + on the same server. + +<?xml version="1.0" encoding="UTF-8"?> +<deployment xmlns="urn:jboss:bean-deployer:2.0"> + <bean name="JMSBridge" class="org.hornetq.api.jms.bridge.impl.JMSBridgeImpl"> + <!-- HornetQ must be started before the bridge --> + <depends>HornetQServer</depends> + <constructor> + <!-- Source ConnectionFactory Factory --> + <parameter> + <inject bean="SourceCFF"/> + </parameter> + <!-- Target ConnectionFactory Factory --> + <parameter> + <inject bean="TargetCFF"/> + </parameter> + <!-- Source DestinationFactory --> + <parameter> + <inject bean="SourceDestinationFactory"/> + </parameter> + <!-- Target DestinationFactory --> + <parameter> + <inject bean="TargetDestinationFactory"/> + </parameter> + <!-- Source User Name (no username here) --> + <parameter><null /></parameter> + <!-- Source Password (no password here)--> + <parameter><null /></parameter> + <!-- Target User Name (no username here)--> + <parameter><null /></parameter> + <!-- Target Password (no password here)--> + <parameter><null /></parameter> + <!-- Selector --> + <parameter><null /></parameter> + <!-- Failure Retry Interval (in ms) --> + <parameter>5000</parameter> + <!-- Max Retries --> + <parameter>10</parameter> + <!-- Quality Of Service --> + <parameter>ONCE_AND_ONLY_ONCE</parameter> + <!-- Max Batch Size --> + <parameter>1</parameter> + <!-- Max Batch Time (-1 means infinite) --> + <parameter>-1</parameter> + <!-- Subscription name (no subscription name here)--> + <parameter><null /></parameter> + <!-- Client ID (no client ID here)--> + <parameter><null /></parameter> + <!-- Add MessageID In Header --> + <parameter>true</parameter> + <!-- register the JMS Bridge in the AS MBeanServer --> + <parameter> + <inject bean="MBeanServer"/> + </parameter> + <parameter>org.hornetq:service=JMSBridge</parameter> + </constructor> + <property name="transactionManager"> + <inject bean="RealTransactionManager"/> + </property> + </bean> + + <!-- SourceCFF describes the ConnectionFactory used to connect to the source destination --> + <bean name="SourceCFF" + class="org.hornetq.api.jms.bridge.impl.JNDIConnectionFactoryFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/ConnectionFactory</parameter> + </constructor> + </bean> + + <!-- TargetCFF describes the ConnectionFactory used to connect to the target destination --> + <bean name="TargetCFF" + class="org.hornetq.api.jms.bridge.impl.JNDIConnectionFactoryFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/ConnectionFactory</parameter> + </constructor> + </bean> + + <!-- SourceDestinationFactory describes the Destination used as the source --> + <bean name="SourceDestinationFactory" class="org.hornetq.api.jms.bridge.impl.JNDIDestinationFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/queue/source</parameter> + </constructor> + </bean> + + <!-- TargetDestinationFactory describes the Destination used as the target --> + <bean name="TargetDestinationFactory" class="org.hornetq.api.jms.bridge.impl.JNDIDestinationFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/queue/target</parameter> + </constructor> + </bean> + + <!-- JNDI is a Hashtable containing the JNDI properties required --> + <!-- to connect to the sources and targets JMS resrouces --> + <bean name="JNDI" class="java.util.Hashtable"> + <constructor class="java.util.Map"> + <map class="java.util.Hashtable" keyClass="String" + valueClass="String"> + <entry> + <key>java.naming.factory.initial</key> + <value>org.jnp.interfaces.NamingContextFactory</value> + </entry> + <entry> + <key>java.naming.provider.url</key> + <value>jnp://localhost:1099</value> + </entry> + <entry> + <key>java.naming.factory.url.pkgs</key> + <value>org.jboss.naming:org.jnp.interfaces"</value> + </entry> + <entry> + <key>jnp.timeout</key> + <value>5000</value> + </entry> + <entry> + <key>jnp.sotimeout</key> + <value>5000</value> + </entry> + </map> + </constructor> + </bean> + + <bean name="MBeanServer" class="javax.management.MBeanServer"> + <constructor factoryClass="org.jboss.mx.util.MBeanServerLocator" factoryMethod="locateJBoss"/> + </bean> +</deployment> +
+ JMS Bridge Parameters + The main bean deployed is the JMSBridge bean. The bean is + configurable by the parameters passed to its constructor. + + To let a parameter be unspecified (for example, if the authentication is + anonymous or no message selector is provided), use <null + /> for the unspecified parameter value. + + + + Source Connection Factory Factory + This injects the SourceCFF bean (also defined in the + beans file). This bean is used to create the source + ConnectionFactory + + + + Target Connection Factory Factory + This injects the TargetCFF bean (also defined in the + beans file). This bean is used to create the target + ConnectionFactory + + + + Source Destination Factory Factory + This injects the SourceDestinationFactory bean (also + defined in the beans file). This bean is used to create the + source + Destination + + + + Target Destination Factory Factory + This injects the TargetDestinationFactory bean (also + defined in the beans file). This bean is used to create the + target + Destination + + + + Source User Name + this parameter is the username for creating the + source connection + + + Source Password + this parameter is the parameter for creating the + source connection + + + Target User Name + this parameter is the username for creating the + target connection + + + Target Password + this parameter is the password for creating the + target connection + + + Selector + This represents a JMS selector expression used for consuming messages from + the source destination. Only messages that match the selector expression + will be bridged from the source to the target destination + The selector expression must follow the JMS + selector syntax + + + Failure Retry Interval + This represents the amount of time in ms to wait between trying to + recreate connections to the source or target servers when the bridge has + detected they have failed + + + Max Retries + This represents the number of times to attempt to recreate connections to + the source or target servers when the bridge has detected they have failed. + The bridge will give up after trying this number of times. -1 represents 'try forever' + + + Quality Of Service + This parameter represents the desired quality of service mode + Possible values are: + + + AT_MOST_ONCE + + + DUPLICATES_OK + + + ONCE_AND_ONLY_ONCE + + + See for a explanation of these + modes. + + + Max Batch Size + This represents the maximum number of messages to consume from the source + destination before sending them in a batch to the target destination. Its + value must >= 1 + + + + Max Batch Time + This represents the maximum number of milliseconds to wait before sending + a batch to target, even if the number of messages consumed has not reached + MaxBatchSize. Its value must be -1 + to represent 'wait forever', or >= 1 to specify an actual + time + + + Subscription Name + If the source destination represents a topic, and you want to consume from + the topic using a durable subscription then this parameter represents the + durable subscription name + + + Client ID + If the source destination represents a topic, and you want to consume from + the topic using a durable subscription then this attribute represents the + the JMS client ID to use when creating/looking up the durable + subscription + + + Add MessageID In Header + If true, then the original message's message ID will be + appended in the message sent to the destination in the header HORNETQ_BRIDGE_MSG_ID_LIST. If the message is bridged more + than once, each message ID will be appended. This enables a distributed + request-response pattern to be used + + when you receive the message you can send back a response using the + correlation id of the first message id, so when the original sender gets + it back it will be able to correlate it. + + + + MBean Server + To manage the JMS Bridge using JMX, set the MBeanServer where the JMS Bridge MBean + must be registered (e.g. the JVM Platform MBeanServer or JBoss AS MBeanServer) + + + ObjectName + If you set the MBeanServer, you also need to set the ObjectName used to register + the JMS Bridge MBean (must be unique) + + + The "transactionManager" property points to a JTA transaction manager implementation. + HornetQ doesn't ship with such an implementation, but one is available in the JBoss + Community. If you are running HornetQ in standalone mode and wish to use a JMS bridge + simply download the latest version of JBossTS from http://www.jboss.org/jbosstm/downloads + and add it to HornetQ's classpath. If you are running HornetQ with JBoss AS then you + won't need to do this as JBoss AS ships with a JTA transaction manager already. The + bean definition for the transaction manager would look something like this: + + <bean name="RealTransactionManager" class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple"/> +
+
+ Source and Target Connection Factories + The source and target connection factory factories are used to create the + connection factory used to create the connection for the source or target + server. + The configuration example above uses the default implementation provided by + HornetQ that looks up the connection factory using JNDI. For other Application + Servers or JMS providers a new implementation may have to be provided. This can + easily be done by implementing the interface org.hornetq.jms.bridge.ConnectionFactoryFactory. +
+
+ Source and Target Destination Factories + Again, similarly, these are used to create or lookup up the destinations. + In the configuration example above, we have used the default provided by HornetQ + that looks up the destination using JNDI. + A new implementation can be provided by implementing org.hornetq.jms.bridge.DestinationFactory interface. +
+
+ Quality Of Service + The quality of service modes used by the bridge are described here in more + detail. +
+ AT_MOST_ONCE + With this QoS mode messages will reach the destination from the source at most + once. The messages are consumed from the source and acknowledged before sending + to the destination. Therefore there is a possibility that if failure occurs + between removing them from the source and them arriving at the destination they + could be lost. Hence delivery will occur at most once. + This mode is available for both durable and non-durable messages. +
+
+ DUPLICATES_OK + With this QoS mode, the messages are consumed from the source and then + acknowledged after they have been successfully sent to the destination. + Therefore there is a possibility that if failure occurs after sending to the + destination but before acknowledging them, they could be sent again when the + system recovers. I.e. the destination might receive duplicates after a + failure. + This mode is available for both durable and non-durable messages. +
+
+ ONCE_AND_ONLY_ONCE + This QoS mode ensures messages will reach the destination from the source once + and only once. (Sometimes this mode is known as "exactly once"). If both the + source and the destination are on the same HornetQ server instance then this can + be achieved by sending and acknowledging the messages in the same local + transaction. If the source and destination are on different servers this is + achieved by enlisting the sending and consuming sessions in a JTA transaction. + The JTA transaction is controlled by JBoss Transactions JTA * implementation + which is a fully recovering transaction manager, thus providing a very high + degree of durability. If JTA is required then both supplied connection factories + need to be XAConnectionFactory implementations. This is likely to be the slowest + mode since it requires extra persistence for the transaction logging. + This mode is only available for durable messages. + + For a specific application it may possible to provide once and only once + semantics without using the ONCE_AND_ONLY_ONCE QoS level. This can be done + by using the DUPLICATES_OK mode and then checking for duplicates at the + destination and discarding them. Some JMS servers provide automatic + duplicate message detection functionality, or this may be possible to + implement on the application level by maintaining a cache of received + message ids on disk and comparing received messages to them. The cache would + only be valid for a certain period of time so this approach is not as + watertight as using ONCE_AND_ONLY_ONCE but may be a good choice depending on + your specific application. + +
+
+ Time outs and the JMS bridge + There is a possibility that the target or source server will not be available at some point in time. + If this occurs then the bridge will try Max Retries to reconnect every + Failure Retry Interval milliseconds as specified in the JMS Bridge definition. + However since a third party JNDI is used, in this case the JBoss naming server, it is possible for the + JNDI lookup to hang if the network were to disappear during the JNDI lookup. To stop this from occurring the JNDI + definition can be configured to time out if this occurs. To do this set the jnp.timeout + and the jnp.sotimeout on the Initial Context definition. The first sets the connection + timeout for the initial connection and the second the read timeout for the socket. + + Once the initial JNDI connection has succeeded all calls are made using RMI. If you want to control + the timeouts for the RMI connections then this can be done via system properties. JBoss uses Sun's RMI + and the properties can be found here. + The default connection timeout is 10 seconds and the default read timeout is 18 seconds. + + If you implement your own factories for looking up JMS resources then you will have to bear in mind timeout issues. +
+
+ Examples + Please see which shows how to configure + and use a JMS Bridge with JBoss AS to send messages to the source destination and consume them + from the target destination. + Please see which shows how to configure + and use a JMS Bridge between two standalone HornetQ servers. +
+
+
diff --git a/docs/user-manual/en/jms-core-mapping.xml b/docs/user-manual/en/jms-core-mapping.xml new file mode 100644 index 0000000000..bc80b552af --- /dev/null +++ b/docs/user-manual/en/jms-core-mapping.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Mapping JMS Concepts to the Core API + This chapter describes how JMS destinations are mapped to HornetQ addresses. + HornetQ core is JMS-agnostic. It does not have any concept of a JMS topic. A JMS topic is + implemented in core as an address (the topic name) with zero or more queues bound to it. + Each queue bound to that address represents a topic subscription. Likewise, a JMS queue is + implemented as an address (the JMS queue name) with one single queue bound to it which + represents the JMS queue. + By convention, all JMS queues map to core queues where the core queue name has the string + jms.queue. prepended to it. E.g. the JMS queue with the name + "orders.europe" would map to the core queue with the name "jms.queue.orders.europe". The + address at which the core queue is bound is also given by the core queue name. + For JMS topics the address at which the queues that represent the subscriptions are bound + is given by prepending the string "jms.topic." to the name of the JMS topic. E.g. the JMS + topic with name "news.europe" would map to the core address "jms.topic.news.europe" + In other words if you send a JMS message to a JMS queue with name "orders.europe" it will + get routed on the server to any core queues bound to the address "jms.queue.orders.europe". + If you send a JMS message to a JMS topic with name "news.europe" it will get routed on the + server to any core queues bound to the address "jms.topic.news.europe". + If you want to configure settings for a JMS Queue with the name "orders.europe", you need + to configure the corresponding core queue "jms.queue.orders.europe": + +<!-- expired messages in JMS Queue "orders.europe" will be sent to the JMS Queue "expiry.europe" --> +<address-setting match="jms.queue.orders.europe"> + <expiry-address>jms.queue.expiry.europe</expiry-address> + ... +</address-setting> + diff --git a/docs/user-manual/en/large-messages.xml b/docs/user-manual/en/large-messages.xml new file mode 100644 index 0000000000..f28083a62c --- /dev/null +++ b/docs/user-manual/en/large-messages.xml @@ -0,0 +1,297 @@ + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Large Messages + HornetQ supports sending and receiving of huge messages, even when the client and server + are running with limited memory. The only realistic limit to the size of a message that can + be sent or consumed is the amount of disk space you have available. We have tested sending + and consuming messages up to 8 GiB in size with a client and server running in just 50MiB of + RAM! + To send a large message, the user can set an InputStream on a message + body, and when that message is sent, HornetQ will read the InputStream. A + FileInputStream could be used for example to send a huge message from + a huge file on disk. + As the InputStream is read the data is sent to the server as a stream + of fragments. The server persists these fragments to disk as it receives them and when the + time comes to deliver them to a consumer they are read back of the disk, also in fragments + and sent down the wire. When the consumer receives a large message it initially receives + just the message with an empty body, it can then set an OutputStream on + the message to stream the huge message body to a file on disk or elsewhere. At no time is + the entire message body stored fully in memory, either on the client or the server. +
+ Configuring the server + Large messages are stored on a disk directory on the server side, as configured on the + main configuration file. + The configuration property large-messages-directory specifies where + large messages are stored. + +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd"> +... +<large-messages-directory>/data/large-messages</large-messages-directory> +... +</configuration + By default the large message directory is data/largemessages + For the best performance we recommend large messages directory is stored on a + different physical volume to the message journal or paging directory. +
+
+ Configuring Parameters + Any message larger than a certain size is considered a large message. Large messages + will be split up and sent in fragments. This is determined by the parameter min-large-message-size + + HornetQ messages are encoded using 2 bytes per character so if the message data is filled + with ASCII characters (which are 1 byte) the size of the resulting HornetQ message would roughly + double. This is important when calculating the size of a "large" message as it may appear to be + less than the min-large-message-size before it is sent, but it then turns into + a "large" message once it is encoded. + + The default value is 100KiB. +
+ Using Core API + If the HornetQ Core API is used, the minimal large message size is specified by + ServerLocator.setMinLargeMessageSize. + +ServerLocator locator = HornetQClient.createServerLocatorWithoutHA(new TransportConfiguration(NettyConnectorFactory.class.getName())) + +locator.setMinLargeMessageSize(25 * 1024); + +ClientSessionFactory factory = HornetQClient.createClientSessionFactory(); + will provide more information + on how to instantiate the session factory. +
+
+ Using JMS + If JNDI is used to look up the connection factory, the minimum large message size + is specified in hornetq-jms.xml + ... +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + <entry name="XAConnectionFactory"/> + </entries> + + <min-large-message-size>250000</min-large-message-size> +</connection-factory> +... + If the connection factory is being instantiated directly, the minimum large + message size is specified by HornetQConnectionFactory.setMinLargeMessageSize. +
+
+ Compressed Large Messages + + You can choose to send large messages in compressed form using + compress-large-messages attributes. + +
+ <literal>compress-large-messages</literal> + If you specify the boolean property compress-large-messages on + the server locator or ConnectionFactory as true, The + system will use the ZIP algorithm to compress the message body as the message is + transferred to the server's side. Notice that there's no special treatment at the + server's side, all the compressing and uncompressing is done at the client. + If the compressed size of a large message is below + min-large-message-size, it is sent to server as regular messages. This means + that the message won't be written into the server's large-message + data directory, thus reducing the disk I/O. +
+
+ If you use JMS, you can achieve large messages compression by configuring your + connection factories. For example, + ... +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> +... + <compress-large-messages>true</compress-large-messages> +</connection-factory> +... +
+
+
+
+ Streaming large messages + HornetQ supports setting the body of messages using input and output streams (java.lang.io) + These streams are then used directly for sending (input streams) and receiving (output + streams) messages. + When receiving messages there are 2 ways to deal with the output stream; you may + choose to block while the output stream is recovered using the method ClientMessage.saveOutputStream or alternatively using the method ClientMessage.setOutputstream which will asynchronously write the message + to the stream. If you choose the latter the consumer must be kept alive until the + message has been fully received. + You can use any kind of stream you like. The most common use case is to send files + stored in your disk, but you could also send things like JDBC Blobs, SocketInputStream, things you recovered from HTTPRequests etc. Anything as long as it implements java.io.InputStream for sending messages or java.io.OutputStream for receiving them. +
+ Streaming over Core API + The following table shows a list of methods available at ClientMessage which are also available through JMS by the use of + object properties. + + org.hornetq.api.core.client.ClientMessage API + + + + + + + Name + Description + JMS Equivalent Property + + + + + setBodyInputStream(InputStream) + Set the InputStream used to read a message body when sending + it. + JMS_HQ_InputStream + + + setOutputStream(OutputStream) + Set the OutputStream that will receive the body of a message. + This method does not block. + JMS_HQ_OutputStream + + + saveOutputStream(OutputStream) + Save the body of the message to the OutputStream. It will block until the entire content + is transferred to the OutputStream. + JMS_HQ_SaveStream + + + +
+ To set the output stream when receiving a core message: + +... +ClientMessage msg = consumer.receive(...); + + +// This will block here until the stream was transferred +msg.saveOutputStream(someOutputStream); + +ClientMessage msg2 = consumer.receive(...); + +// This will not wait the transfer to finish +msg.setOutputStream(someOtherOutputStream); +... + Set the input stream when sending a core message: + +... +ClientMessage msg = session.createMessage(); +msg.setInputStream(dataInputStream); +... + Notice also that for messages with more than 2GiB the getBodySize() will return + invalid values since this is an integer (which is also exposed to the JMS API). On + those cases you can use the message property _HQ_LARGE_SIZE. +
+
+ Streaming over JMS + When using JMS, HornetQ maps the streaming methods on the core API (see ) by setting object properties . You + can use the method Message.setObjectProperty to set the input and + output streams. + The InputStream can be defined through the JMS Object Property + JMS_HQ_InputStream on messages being sent: + +BytesMessage message = session.createBytesMessage(); + +FileInputStream fileInputStream = new FileInputStream(fileInput); + +BufferedInputStream bufferedInput = new BufferedInputStream(fileInputStream); + +message.setObjectProperty("JMS_HQ_InputStream", bufferedInput); + +someProducer.send(message); + The OutputStream can be set through the JMS Object Property + JMS_HQ_SaveStream on messages being received in a blocking way. + +BytesMessage messageReceived = (BytesMessage)messageConsumer.receive(120000); + +File outputFile = new File("huge_message_received.dat"); + +FileOutputStream fileOutputStream = new FileOutputStream(outputFile); + +BufferedOutputStream bufferedOutput = new BufferedOutputStream(fileOutputStream); + +// This will block until the entire content is saved on disk +messageReceived.setObjectProperty("JMS_HQ_SaveStream", bufferedOutput); + Setting the OutputStream could also be done in a non blocking + way using the property JMS_HQ_OutputStream. + +// This won't wait the stream to finish. You need to keep the consumer active. +messageReceived.setObjectProperty("JMS_HQ_OutputStream", bufferedOutput); + + When using JMS, Streaming large messages are only supported on StreamMessage and BytesMessage. + +
+
+
+ Streaming Alternative + If you choose not to use the InputStream or OutputStream capability of HornetQ You could still access the data + directly in an alternative fashion. + On the Core API just get the bytes of the body as you normally would. + +ClientMessage msg = consumer.receive(); + +byte[] bytes = new byte[1024]; +for (int i = 0 ; i < msg.getBodySize(); i += bytes.length) +{ + msg.getBody().readBytes(bytes); + // Whatever you want to do with the bytes +} + If using JMS API, BytesMessage and StreamMessage + also supports it transparently. + +BytesMessage rm = (BytesMessage)cons.receive(10000); + +byte data[] = new byte[1024]; + +for (int i = 0; i < rm.getBodyLength(); i += 1024) +{ + int numberOfBytes = rm.readBytes(data); + // Do whatever you want with the data +} +
+
+ Large message example + Please see for an example which shows how + large message is configured and used with JMS. +
+
diff --git a/docs/user-manual/en/last-value-queues.xml b/docs/user-manual/en/last-value-queues.xml new file mode 100644 index 0000000000..def6115716 --- /dev/null +++ b/docs/user-manual/en/last-value-queues.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Last-Value Queues + Last-Value queues are special queues which discard any messages when a newer message with + the same value for a well-defined Last-Value property is put in the queue. In other words, a + Last-Value queue only retains the last value. + A typical example for Last-Value queue is for stock prices, where you are only interested + by the latest value for a particular stock. +
+ Configuring Last-Value Queues + Last-value queues are defined in the address-setting configuration: + +<address-setting match="jms.queue.lastValueQueue"> + <last-value-queue>true</last-value-queue> +</address-setting> + By default, last-value-queue is false. Address wildcards can be used + to configure Last-Value queues for a set of addresses (see ). +
+
+ Using Last-Value Property + The property name used to identify the last value is "_HQ_LVQ_NAME" + (or the constant Message.HDR_LAST_VALUE_NAME from the Core API). + For example, if two messages with the same value for the Last-Value property are sent to + a Last-Value queue, only the latest message will be kept in the queue: + +// send 1st message with Last-Value property set to STOCK_NAME +TextMessage message = session.createTextMessage("1st message with Last-Value property set"); +message.setStringProperty("_HQ_LVQ_NAME", "STOCK_NAME"); +producer.send(message); + +// send 2nd message with Last-Value property set to STOCK_NAME +message = session.createTextMessage("2nd message with Last-Value property set"); +message.setStringProperty("_HQ_LVQ_NAME", "STOCK_NAME"); +producer.send(message); + +... + +// only the 2nd message will be received: it is the latest with +// the Last-Value property set +TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000); +System.out.format("Received message: %s\n", messageReceived.getText()); +
+
+ Example + See for an example which shows how last + value queues are configured and used with JMS. +
+
diff --git a/docs/user-manual/en/libaio.xml b/docs/user-manual/en/libaio.xml new file mode 100644 index 0000000000..d0e2c760a4 --- /dev/null +++ b/docs/user-manual/en/libaio.xml @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Libaio Native Libraries + HornetQ distributes a native library, used as a bridge between HornetQ and Linux + libaio. + libaio is a library, developed as part of the Linux kernel project. + With libaio we submit writes to the operating system where they are + processed asynchronously. Some time later the OS will call our code back when they have been + processed. + We use this in our high performance journal if configured to do so, please see . + These are the native libraries distributed by HornetQ: + + + libHornetQAIO32.so - x86 32 bits + + + libHornetQAIO64.so - x86 64 bits + + + When using libaio, HornetQ will always try loading these files as long as they are on the + library path. +
+ Compiling the native libraries + In the case that you are using Linux on a platform other than x86_32 or x86_64 + (for example Itanium 64 bits or IBM Power) you may need to compile the native library, since we + do not distribute binaries for those platforms with the release. +
+ Install requirements + + At the moment the native layer is only available on Linux. If you are in a + platform other than Linux the native compilation will not work + + The native library uses autoconf what makes the compilation process easy, however you need to + install extra packages as a requirement for compilation: + + + gcc - C Compiler + + + gcc-c++ or g++ - Extension to gcc with support for C++ + + + autoconf - Tool for automating native build process + + + make - Plain old make + + + automake - Tool for automating make generation + + + libtool - Tool for link editing native libraries + + + libaio - library to disk asynchronous IO kernel functions + + + libaio-dev - Compilation support for libaio + + + A full JDK installed with the environment variable JAVA_HOME set to its + location + + + To perform this installation on RHEL or Fedora, you can simply type this at a + command line: + sudo yum install automake libtool autoconf gcc-c++ gcc libaio libaio-devel make + Or on Debian systems: + sudo apt-get install automake libtool autoconf gcc-g++ gcc libaio libaio-dev make + + You could find a slight variation of the package names depending on the + version and Linux distribution. (for example gcc-c++ on Fedora versus g++ on + Debian systems) + +
+
+ Invoking the compilation + In the distribution, in the native-src directory, execute the + shell script bootstrap. This script will invoke automake and make what will create all the make + files and the native library. + someUser@someBox:/messaging-distribution/native-src$ ./bootstrap +checking for a BSD-compatible install... /usr/bin/install -c +checking whether build environment is sane... yes +checking for a thread-safe mkdir -p... /bin/mkdir -p + +... + +configure: creating ./config.status +config.status: creating Makefile +config.status: creating ./src/Makefile +config.status: creating config.h +config.status: config.h is unchanged +config.status: executing depfiles commands +config.status: executing libtool commands + +... + The produced library will be at ./native-src/src/.libs/libHornetQAIO.so. Simply move that file over + bin on the distribution or the place you have chosen on the + library path. + If you want to perform changes on the HornetQ libaio code, you could just call + make directly at the native-src directory. +
+
+
diff --git a/docs/user-manual/en/logging.xml b/docs/user-manual/en/logging.xml new file mode 100644 index 0000000000..b21b587375 --- /dev/null +++ b/docs/user-manual/en/logging.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Logging + HornetQ uses the JBoss Logging framework to do its logging and is configurable via the logging.properties + file found in the configuration directories. This is configured by Default to log to both the console and to a file. + There are 6 loggers available which are as follows: + + Global Configuration Properties + + + + + + Logger + Logger Description + + + + + org.jboss.logging + Logs any calls not handled by the HornetQ loggers + + + org.hornetq.core.server + Logs the core server + + + org.hornetq.utils + Logs utility calls + + + org.hornetq.journal + Logs Journal calls + + + org.hornetq.jms + Logs JMS calls + + + org.hornetq.integration.bootstrap + Logs bootstrap calls + + + + you can configure the levels on these loggers independently in the appropriate logging.properties + file +
+
+ Logging in a client or with an Embedded server + + Firstly, if you want to enable logging on the client side you need to include the jboss logging jars in your library. + If you are using the distribution make sure the jnp-client.jar is included or if you are using maven add the following + dependencies. + +<dependency> +<groupId>org.jboss.naming</groupId> +<artifactId>jnp-client</artifactId> +<version>5.0.5.Final</version> + <exclusions> + <exclusion> + <groupId>org.jboss.logging</groupId> + <artifactId>jboss-logging-spi</artifactId> + </exclusion> + </exclusions> +</dependency> +<dependency> + <groupId>org.jboss.logmanager</groupId> + <artifactId>jboss-logmanager</artifactId> + <version>1.3.1.Final</version> +</dependency> +<dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-core-client</artifactId> + <version>2.3.0.Final</version> +</dependency> + The first dependency jnp-client is not actually needed for logging, however this is needed for + using JNDI and imports a previous version JBoss logging which needs to be excluded + + + There are 2 properties you need to set when starting your java program, the first is to set the Log Manager to use + the JBoss Log Manager, this is done by setting the -Djava.util.logging.manager property i.e. + -Djava.util.logging.manager=org.jboss.logmanager.LogManager + + + The second is to set the location of the logging.properties file to use, this is done via the -Dlogging.configuration + for instance -Dlogging.configuration=file:///home/user/projects/myProject/logging.properties. + The value for this needs to be valid URL + + + The following is a typical logging.properties for a client + +# Root logger option +loggers=org.jboss.logging,org.hornetq.core.server,org.hornetq.utils,org.hornetq.journal,org.hornetq.jms,org.hornetq.ra + +# Root logger level +logger.level=INFO +# HornetQ logger levels +logger.org.hornetq.core.server.level=INFO +logger.org.hornetq.utils.level=INFO +logger.org.hornetq.jms.level=DEBUG + +# Root logger handlers +logger.handlers=FILE,CONSOLE + +# Console handler configuration +handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler +handler.CONSOLE.properties=autoFlush +handler.CONSOLE.level=FINE +handler.CONSOLE.autoFlush=true +handler.CONSOLE.formatter=PATTERN + +# File handler configuration +handler.FILE=org.jboss.logmanager.handlers.FileHandler +handler.FILE.level=FINE +handler.FILE.properties=autoFlush,fileName +handler.FILE.autoFlush=true +handler.FILE.fileName=hornetq.log +handler.FILE.formatter=PATTERN + +# Formatter pattern configuration +formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter +formatter.PATTERN.properties=pattern +formatter.PATTERN.pattern=%d{HH:mm:ss,SSS} %-5p [%c] %s%E%n + +
+
+ Logging With The JBoss Application Server + When HornetQ is deployed within the JBoss Application Server version 7.x or above then + it will still use JBoss Logging, refer to the AS7 documentation on how to configure AS7 logging. +
+
diff --git a/docs/user-manual/en/management.xml b/docs/user-manual/en/management.xml new file mode 100644 index 0000000000..be5cd32c3e --- /dev/null +++ b/docs/user-manual/en/management.xml @@ -0,0 +1,1109 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Management + HornetQ has an extensive management API that allows a user to modify a server + configuration, create new resources (e.g. JMS queues and topics), inspect these resources + (e.g. how many messages are currently held in a queue) and interact with it (e.g. to remove + messages from a queue). All the operations allows a client to manage + HornetQ. It also allows clients to subscribe to management notifications. + There are 3 ways to manage HornetQ: + + + Using JMX -- JMX is the standard way to manage Java applications + + + Using the core API -- management operations are sent to HornetQ server using + core messages + + + Using the JMS API -- management operations are sent to HornetQ server using + JMS messages + + + Although there are 3 different ways to manage HornetQ each API supports the same + functionality. If it is possible to manage a resource using JMX it is also possible to achieve + the same result using Core messages or JMS messages. + This choice depends on your requirements, your application settings and your environment to + decide which way suits you best. +
+ The Management API + Regardless of the way you invoke management operations, the + management API is the same. + For each managed resource, there exists a Java interface describing + what can be invoked for this type of resource. + HornetQ exposes its managed resources in 2 packages: + + + Core resources are located in the org.hornetq.api.core.management package + + + JMS resources are located in the org.hornetq.api.jms.management package + + + The way to invoke a management operations depends whether JMX, core + messages, or JMS messages are used. + + A few management operations requires a filter parameter to chose + which messages are involved by the operation. Passing null or an + empty string means that the management operation will be performed on all + messages. + +
+ Core Management API + HornetQ defines a core management API to manage core resources. For full details of + the API please consult the javadoc. In summary: +
+ Core Server Management + + + Listing, creating, deploying and destroying queues + A list of deployed core queues can be retrieved using the getQueueNames() method. + Core queues can be created or destroyed using the management operations + createQueue() or deployQueue() or + destroyQueue())on the HornetQServerControl (with the ObjectName org.hornetq:module=Core,type=Server or the resource name core.server) + createQueue will fail if the queue already exists while + deployQueue will do nothing. + + + Pausing and resuming Queues + The QueueControl can pause and resume the underlying + queue. When a queue is paused, it will receive messages but will not deliver + them. When it's resumed, it'll begin delivering the queued messages, if any. + + + + Listing and closing remote connections + Client's remote addresses can be retrieved using listRemoteAddresses(). It is also possible to close the + connections associated with a remote address using the closeConnectionsForAddress() method. + Alternatively, connection IDs can be listed using listConnectionIDs() and all the sessions for a given connection + ID can be listed using listSessions(). + + + Transaction heuristic operations + In case of a server crash, when the server restarts, it it possible that + some transaction requires manual intervention. The listPreparedTransactions() method lists the transactions which + are in the prepared states (the transactions are represented as opaque Base64 + Strings.) To commit or rollback a given prepared transaction, the commitPreparedTransaction() or rollbackPreparedTransaction() method can be used to resolve + heuristic transactions. Heuristically completed transactions can be listed + using the listHeuristicCommittedTransactions() and listHeuristicRolledBackTransactions methods. + + + Enabling and resetting Message counters + Message counters can be enabled or disabled using the enableMessageCounters() or disableMessageCounters() method. To reset message counters, it is + possible to invoke resetAllMessageCounters() and resetAllMessageCounterHistories() methods. + + + Retrieving the server configuration and attributes + The HornetQServerControl exposes HornetQ server + configuration through all its attributes (e.g. getVersion() + method to retrieve the server's version, etc.) + + + Listing, creating and destroying Core bridges and diverts + A list of deployed core bridges (resp. diverts) can be retrieved using the getBridgeNames() (resp. getDivertNames()) method. + Core bridges (resp. diverts) can be created or destroyed using the management operations + createBridge() and destroyBridge() + (resp. createDivert() and destroyDivert()) on the HornetQServerControl (with the ObjectName org.hornetq:module=Core,type=Server or the resource name core.server). + + + It is possible to stop the server and force failover to occur with any currently attached clients. + to do this use the forceFailover() on the HornetQServerControl (with the ObjectName org.hornetq:module=Core,type=Server or the resource name core.server) + + Since this method actually stops the server you will probably receive some sort of error + depending on which management service you use to call it. + + + +
+
+ Core Address Management + Core addresses can be managed using the AddressControl class + (with the ObjectName org.hornetq:module=Core,type=Address,name="<the + address name>" or the resource name core.address.<the + address name>). + + + Modifying roles and permissions for an address + You can add or remove roles associated to a queue using the addRole() or removeRole() methods. You can + list all the roles associated to the queue with the getRoles() method + + +
+
+ Core Queue Management + The bulk of the core management API deals with core queues. The QueueControl class defines the Core queue management operations (with + the ObjectName org.hornetq:module=Core,type=Queue,address="<the bound + address>",name="<the queue name>" or the resource name core.queue.<the queue name>). + Most of the management operations on queues take either a single message ID (e.g. + to remove a single message) or a filter (e.g. to expire all messages with a given + property.) + + + Expiring, sending to a dead letter address and moving messages + Messages can be expired from a queue by using the expireMessages() method. If an expiry address is defined, + messages will be sent to it, otherwise they are discarded. The queue's + expiry address can be set with the setExpiryAddress() + method. + Messages can also be sent to a dead letter address with the sendMessagesToDeadLetterAddress() method. It returns the number + of messages which are sent to the dead letter address. If a dead letter address + is not defined, message are removed from the queue and discarded. The queue's + dead letter address can be set with the setDeadLetterAddress() method. + Messages can also be moved from a queue to another queue by using the + moveMessages() method. + + + Listing and removing messages + Messages can be listed from a queue by using the listMessages() method which returns an array of Map, one Map for each message. + Messages can also be removed from the queue by using the removeMessages() method which returns a boolean for the single message ID variant or the number of + removed messages for the filter variant. The removeMessages() method takes a filter + argument to remove only filtered messages. Setting the filter to an empty + string will in effect remove all messages. + + + Counting messages + The number of messages in a queue is returned by the getMessageCount() method. Alternatively, the countMessages() will return the number of messages in the queue + which match a given filter + + + Changing message priority + The message priority can be changed by using the changeMessagesPriority() method which returns a boolean for the single message ID variant or the number of + updated messages for the filter variant. + + + Message counters + Message counters can be listed for a queue with the listMessageCounter() and listMessageCounterHistory() methods (see ). The message counters can also be + reset for a single queue using the resetMessageCounter() + method. + + + Retrieving the queue attributes + The QueueControl exposes Core queue settings through its + attributes (e.g. getFilter() to retrieve the queue's filter + if it was created with one, isDurable() to know whether the + queue is durable or not, etc.) + + + Pausing and resuming Queues + The QueueControl can pause and resume the underlying + queue. When a queue is paused, it will receive messages but will not deliver + them. When it's resume, it'll begin delivering the queued messages, if any. + + + +
+
+ Other Core Resources Management + HornetQ allows to start and stop its remote resources (acceptors, diverts, + bridges, etc.) so that a server can be taken off line for a given period of time + without stopping it completely (e.g. if other management operations must be performed + such as resolving heuristic transactions). These resources are: + + + Acceptors + They can be started or stopped using the start() or. + stop() method on the AcceptorControl + class (with the ObjectName org.hornetq:module=Core,type=Acceptor,name="<the acceptor + name>" or the resource name core.acceptor.<the + address name>). The acceptors parameters can be retrieved using + the AcceptorControl attributes (see ) + + + Diverts + They can be started or stopped using the start() or + stop() method on the DivertControl + class (with the ObjectName org.hornetq:module=Core,type=Divert,name=<the divert name> + or the resource name core.divert.<the divert name>). + Diverts parameters can be retrieved using the DivertControl + attributes (see ) + + + Bridges + They can be started or stopped using the start() (resp. + stop()) method on the BridgeControl + class (with the ObjectName org.hornetq:module=Core,type=Bridge,name="<the bridge + name>" or the resource name core.bridge.<the bridge + name>). Bridges parameters can be retrieved using the BridgeControl attributes (see ) + + + Broadcast groups + They can be started or stopped using the start() or + stop() method on the BroadcastGroupControl class (with the ObjectName org.hornetq:module=Core,type=BroadcastGroup,name="<the broadcast group + name>" or the resource name core.broadcastgroup.<the broadcast group name>). Broadcast + groups parameters can be retrieved using the BroadcastGroupControl attributes (see ) + + + Discovery groups + They can be started or stopped using the start() or + stop() method on the DiscoveryGroupControl class (with the ObjectName org.hornetq:module=Core,type=DiscoveryGroup,name="<the discovery group + name>" or the resource name core.discovery.<the + discovery group name>). Discovery groups parameters can be + retrieved using the DiscoveryGroupControl attributes (see + ) + + + Cluster connections + They can be started or stopped using the start() or + stop() method on the ClusterConnectionControl class (with the ObjectName org.hornetq:module=Core,type=ClusterConnection,name="<the cluster + connection name>" or the resource name core.clusterconnection.<the cluster connection name>). + Cluster connections parameters can be retrieved using the ClusterConnectionControl attributes (see ) + + +
+
+
+ JMS Management API + HornetQ defines a JMS Management API to manage JMS administrated + objects (i.e. JMS queues, topics and connection factories). +
+ JMS Server Management + JMS Resources (connection factories and destinations) can be created using the + JMSServerControl class (with the ObjectName org.hornetq:module=JMS,type=Server or the resource name jms.server). + + + Listing, creating, destroying connection factories + Names of the deployed connection factories can be retrieved by the getConnectionFactoryNames() method. + JMS connection factories can be created or destroyed using the createConnectionFactory() methods or destroyConnectionFactory() methods. These connection factories + are bound to JNDI so that JMS clients can look them up. If a graphical console + is used to create the connection factories, the transport parameters are + specified in the text field input as a comma-separated list of key=value (e.g. + key1=10, key2="value", key3=false). If there are multiple + transports defined, you need to enclose the key/value pairs between curly + braces. For example {key=10}, {key=20}. In that case, the + first key will be associated to the first transport + configuration and the second key will be associated to the + second transport configuration (see + for a list of the transport parameters) + + + Listing, creating, destroying queues + Names of the deployed JMS queues can be retrieved by the getQueueNames() method. + JMS queues can be created or destroyed using the createQueue() methods or destroyQueue() + methods. These queues are bound to JNDI so that JMS clients can look them + up + + + Listing, creating/destroying topics + Names of the deployed topics can be retrieved by the getTopicNames() method. + JMS topics can be created or destroyed using the createTopic() or destroyTopic() methods. These + topics are bound to JNDI so that JMS clients can look them up + + + Listing and closing remote connections + JMS Clients remote addresses can be retrieved using listRemoteAddresses(). It is also possible to close the + connections associated with a remote address using the closeConnectionsForAddress() method. + Alternatively, connection IDs can be listed using listConnectionIDs() and all the sessions for a given connection + ID can be listed using listSessions(). + + +
+
+ JMS ConnectionFactory Management + JMS Connection Factories can be managed using the ConnectionFactoryControl class (with the ObjectName org.hornetq:module=JMS,type=ConnectionFactory,name="<the connection factory + name>" or the resource name jms.connectionfactory.<the + connection factory name>). + + + Retrieving connection factory attributes + The ConnectionFactoryControl exposes JMS + ConnectionFactory configuration through its attributes (e.g. getConsumerWindowSize() to retrieve the consumer window size for + flow control, isBlockOnNonDurableSend() to know whether the + producers created from the connection factory will block or not when sending + non-durable messages, etc.) + + +
+
+ JMS Queue Management + JMS queues can be managed using the JMSQueueControl class (with + the ObjectName org.hornetq:module=JMS,type=Queue,name="<the queue + name>" or the resource name jms.queue.<the queue + name>). + The management operations on a JMS queue are very similar to the + operations on a core queue. + + + Expiring, sending to a dead letter address and moving messages + Messages can be expired from a queue by using the expireMessages() method. If an expiry address is defined, + messages will be sent to it, otherwise they are discarded. The queue's + expiry address can be set with the setExpiryAddress() + method. + Messages can also be sent to a dead letter address with the sendMessagesToDeadLetterAddress() method. It returns the number + of messages which are sent to the dead letter address. If a dead letter address + is not defined, message are removed from the queue and discarded. The queue's + dead letter address can be set with the setDeadLetterAddress() method. + Messages can also be moved from a queue to another queue by using the + moveMessages() method. + + + Listing and removing messages + Messages can be listed from a queue by using the listMessages() method which returns an array of Map, one Map for each message. + Messages can also be removed from the queue by using the removeMessages() method which returns a boolean for the single message ID variant or the number of + removed messages for the filter variant. The removeMessages() method takes a filter + argument to remove only filtered messages. Setting the filter to an empty + string will in effect remove all messages. + + + Counting messages + The number of messages in a queue is returned by the getMessageCount() method. Alternatively, the countMessages() will return the number of messages in the queue + which match a given filter + + + Changing message priority + The message priority can be changed by using the changeMessagesPriority() method which returns a boolean for the single message ID variant or the number of + updated messages for the filter variant. + + + Message counters + Message counters can be listed for a queue with the listMessageCounter() and listMessageCounterHistory() methods (see ) + + + Retrieving the queue attributes + The JMSQueueControl exposes JMS queue settings through + its attributes (e.g. isTemporary() to know whether the queue + is temporary or not, isDurable() to know whether the queue is + durable or not, etc.) + + + Pausing and resuming queues + The JMSQueueControl can pause and resume the underlying + queue. When the queue is paused it will continue to receive messages but will + not deliver them. When resumed again it will deliver the enqueued messages, if + any. + + +
+
+ JMS Topic Management + JMS Topics can be managed using the TopicControl class (with + the ObjectName org.hornetq:module=JMS,type=Topic,name="<the topic + name>" or the resource name jms.topic.<the topic + name>). + + + Listing subscriptions and messages + JMS topics subscriptions can be listed using the listAllSubscriptions(), listDurableSubscriptions(), listNonDurableSubscriptions() methods. These methods return + arrays of Object representing the subscriptions information + (subscription name, client ID, durability, message count, etc.). It is also + possible to list the JMS messages for a given subscription with the listMessagesForSubscription() method. + + + Dropping subscriptions + Durable subscriptions can be dropped from the topic using the dropDurableSubscription() method. + + + Counting subscriptions messages + The countMessagesForSubscription() method can be used to + know the number of messages held for a given subscription (with an optional + message selector to know the number of messages matching the selector) + + +
+
+
+
+ Using Management Via JMX + HornetQ can be managed using JMX. + The management API is exposed by HornetQ using MBeans interfaces. HornetQ registers its + resources with the domain org.hornetq. + For example, the ObjectName to manage a JMS Queue exampleQueue is: + +org.hornetq:module=JMS,type=Queue,name="exampleQueue" + and the MBean is: + +org.hornetq.api.jms.management.JMSQueueControl + The MBean's ObjectName are built using the helper class org.hornetq.api.core.management.ObjectNameBuilder. You can also use jconsole to find the ObjectName of the MBeans you want to + manage. + Managing HornetQ using JMX is identical to management of any Java Applications using + JMX. It can be done by reflection or by creating proxies of the MBeans. +
+ Configuring JMX + By default, JMX is enabled to manage HornetQ. It can be disabled by setting jmx-management-enabled to false in hornetq-configuration.xml: + +<!-- false to disable JMX management for HornetQ --> +<jmx-management-enabled>false</jmx-management-enabled> + If JMX is enabled, HornetQ can be managed locally using jconsole. + + Remote connections to JMX are not enabled by default for security reasons. Please refer + to Java Management guide to configure the server for remote management (system + properties must be set in run.sh or run.bat + scripts). + + By default, HornetQ server uses the JMX domain "org.hornetq". To manage several + HornetQ servers from the same MBeanServer, the JMX domain can be + configured for each individual HornetQ server by setting jmx-domain + in hornetq-configuration.xml: + +<!-- use a specific JMX domain for HornetQ MBeans --> +<jmx-domain>my.org.hornetq</jmx-domain> +
+ MBeanServer configuration + When HornetQ is run in standalone, it uses the Java Virtual Machine's Platform MBeanServer to register its MBeans. This is configured in + JBoss Microcontainer Beans file (see ): + +<!-- MBeanServer --> +<bean name="MBeanServer" class="javax.management.MBeanServer"> + <constructor factoryClass="java.lang.management.ManagementFactory" + factoryMethod="getPlatformMBeanServer" /> +</bean> + When it is integrated in JBoss AS 5+, it uses the Application Server's own MBean + Server so that it can be managed using AS 5's jmx-console: + +<!-- MBeanServer --> +<bean name="MBeanServer" class="javax.management.MBeanServer"> + <constructor factoryClass="org.jboss.mx.util.MBeanServerLocator" + factoryMethod="locateJBoss" /> +</bean> +
+
+
+ Example + See for an example which shows how to use a remote + connection to JMX and MBean proxies to manage HornetQ. +
+
+
+ Using Management Via Core API + The core management API in HornetQ is called by sending Core messages to a special + address, the management address. + Management messages are regular Core messages with well-known + properties that the server needs to understand to interact with the management API: + + + The name of the managed resource + + + The name of the management operation + + + The parameters of the management operation + + + When such a management message is sent to the management address, HornetQ server will + handle it, extract the information, invoke the operation on the managed resources and send + a management reply to the management message's reply-to address + (specified by ClientMessageImpl.REPLYTO_HEADER_NAME). + A ClientConsumer can be used to consume the management reply and + retrieve the result of the operation (if any) stored in the reply's body. For portability, + results are returned as a JSON String rather than Java + Serialization (the org.hornetq.api.core.management.ManagementHelper can + be used to convert the JSON string to Java objects). + These steps can be simplified to make it easier to invoke management operations using + Core messages: + + + Create a ClientRequestor to send messages to the management + address and receive replies + + + Create a ClientMessage + + + Use the helper class org.hornetq.api.core.management.ManagementHelper to fill the message + with the management properties + + + Send the message using the ClientRequestor + + + Use the helper class org.hornetq.api.core.management.ManagementHelper to retrieve the + operation result from the management reply + + + For example, to find out the number of messages in the core queue exampleQueue: + +ClientSession session = ... +ClientRequestor requestor = new ClientRequestor(session, "jms.queue.hornetq.management"); +ClientMessage message = session.createMessage(false); +ManagementHelper.putAttribute(message, "core.queue.exampleQueue", "messageCount"); +session.start(); +ClientMessage reply = requestor.request(m); +int count = (Integer) ManagementHelper.getResult(reply); +System.out.println("There are " + count + " messages in exampleQueue"); + Management operation name and parameters must conform to the Java interfaces defined in + the management packages. + Names of the resources are built using the helper class org.hornetq.api.core.management.ResourceNames and are straightforward + (core.queue.exampleQueue for the Core Queue exampleQueue, jms.topic.exampleTopic for the JMS Topic + exampleTopic, etc.). +
+ Configuring Core Management + The management address to send management messages is configured in hornetq-configuration.xml: + +<management-address>jms.queue.hornetq.management</management-address> + By default, the address is jms.queue.hornetq.management (it is + prepended by "jms.queue" so that JMS clients can also send management messages). + The management address requires a special user permission + manage to be able to receive and handle management messages. This + is also configured in hornetq-configuration.xml: + +<!-- users with the admin role will be allowed to manage --> +<!-- HornetQ using management messages --> +<security-setting match="jms.queue.hornetq.management"> + <permission type="manage" roles="admin" /> +</security-setting> +
+
+
+ Using Management Via JMS + Using JMS messages to manage HornetQ is very similar to using core API. + An important difference is that JMS requires a JMS queue to send the messages to + (instead of an address for the core API). + The management queue is a special queue and needs to be + instantiated directly by the client: + +Queue managementQueue = HornetQJMSClient.createQueue("hornetq.management"); + All the other steps are the same than for the Core API but they use JMS API + instead: + + + create a QueueRequestor to send messages to the management + address and receive replies + + + create a Message + + + use the helper class org.hornetq.api.jms.management.JMSManagementHelper to fill the message + with the management properties + + + send the message using the QueueRequestor + + + use the helper class org.hornetq.api.jms.management.JMSManagementHelper to retrieve the + operation result from the management reply + + + For example, to know the number of messages in the JMS queue exampleQueue: + +Queue managementQueue = HornetQJMSClient.createQueue("hornetq.management"); + +QueueSession session = ... +QueueRequestor requestor = new QueueRequestor(session, managementQueue); +connection.start(); +Message message = session.createMessage(); +JMSManagementHelper.putAttribute(message, "jms.queue.exampleQueue", "messageCount"); +Message reply = requestor.request(message); +int count = (Integer)JMSManagementHelper.getResult(reply); +System.out.println("There are " + count + " messages in exampleQueue"); +
+ Configuring JMS Management + Whether JMS or the core API is used for management, the configuration steps are the + same (see ). +
+
+ Example + See for an example which shows how to use JMS + messages to manage HornetQ server. +
+
+ +
+ Management Notifications + HornetQ emits notifications to inform listeners of potentially + interesting events (creation of new resources, security violation, etc.). + These notifications can be received by 3 different ways: + + + JMX notifications + + + Core messages + + + JMS messages + + +
+ JMX Notifications + If JMX is enabled (see ), JMX + notifications can be received by subscribing to 2 MBeans: + + + org.hornetq:module=Core,type=Server for notifications on + Core resources + + + org.hornetq:module=JMS,type=Server for notifications on + JMS resources + + +
+
+ Core Messages Notifications + HornetQ defines a special management notification address. Core + queues can be bound to this address so that clients will receive management + notifications as Core messages + A Core client which wants to receive management notifications must create a core + queue bound to the management notification address. It can then receive the + notifications from its queue. + Notifications messages are regular core messages with additional properties + corresponding to the notification (its type, when it occurred, the resources which were + concerned, etc.). + Since notifications are regular core messages, it is possible to use message + selectors to filter out notifications and receives only a subset of all the + notifications emitted by the server. +
+ Configuring The Core Management Notification Address + The management notification address to receive management notifications is + configured in hornetq-configuration.xml: + +<management-notification-address>hornetq.notifications</management-notification-address> + By default, the address is hornetq.notifications. +
+
+
+ JMS Messages Notifications + HornetQ's notifications can also be received using JMS messages. + It is similar to receiving notifications using Core API but an important difference + is that JMS requires a JMS Destination to receive the messages (preferably a + Topic). + To use a JMS Destination to receive management notifications, you must change the server's + management notification address to start with jms.queue if it is a JMS Queue + or jms.topic if it is a JMS Topic: + +<!-- notifications will be consumed from "notificationsTopic" JMS Topic --> +<management-notification-address>jms.topic.notificationsTopic</management-notification-address> + Once the notification topic is created, you can receive messages from it or set a + MessageListener: + +Topic notificationsTopic = HornetQJMSClient.createTopic("notificationsTopic"); + +Session session = ... +MessageConsumer notificationConsumer = session.createConsumer(notificationsTopic); +notificationConsumer.setMessageListener(new MessageListener() +{ + public void onMessage(Message notif) + { + System.out.println("------------------------"); + System.out.println("Received notification:"); + try + { + Enumeration propertyNames = notif.getPropertyNames(); + while (propertyNames.hasMoreElements()) + { + String propertyName = (String)propertyNames.nextElement(); + System.out.format(" %s: %s\n", propertyName, notif.getObjectProperty(propertyName)); + } + } + catch (JMSException e) + { + } + System.out.println("------------------------"); + } +}); +
+
+ Example + See for an example which shows + how to use a JMS MessageListener to receive management notifications + from HornetQ server. +
+
+ Notification Types and Headers + Below is a list of all the different kinds of notifications as well as which headers are + on the messages. Every notification has a _HQ_NotifType (value noted in parentheses) + and _HQ_NotifTimestamp header. The timestamp is the un-formatted result of a call + to java.lang.System.currentTimeMillis(). + + + BINDING_ADDED (0) + _HQ_Binding_Type, _HQ_Address, + _HQ_ClusterName, _HQ_RoutingName, + _HQ_Binding_ID, _HQ_Distance, + _HQ_FilterString + + + + + BINDING_REMOVED (1) + _HQ_Address, _HQ_ClusterName, + _HQ_RoutingName, _HQ_Binding_ID, + _HQ_Distance, _HQ_FilterString + + + + + CONSUMER_CREATED (2) + _HQ_Address, _HQ_ClusterName, + _HQ_RoutingName, _HQ_Distance, + _HQ_ConsumerCount, _HQ_User, + _HQ_RemoteAddress, _HQ_SessionName, + _HQ_FilterString + + + + + CONSUMER_CLOSED (3) + _HQ_Address, _HQ_ClusterName, + _HQ_RoutingName, _HQ_Distance, + _HQ_ConsumerCount, _HQ_User, + _HQ_RemoteAddress, _HQ_SessionName, + _HQ_FilterString + + + + + SECURITY_AUTHENTICATION_VIOLATION (6) + _HQ_User + + + + + SECURITY_PERMISSION_VIOLATION (7) + _HQ_Address, _HQ_CheckType, + _HQ_User + + + + + DISCOVERY_GROUP_STARTED (8) + name + + + + + DISCOVERY_GROUP_STOPPED (9) + name + + + + + BROADCAST_GROUP_STARTED (10) + name + + + + + BROADCAST_GROUP_STOPPED (11) + name + + + + + BRIDGE_STARTED (12) + name + + + + + BRIDGE_STOPPED (13) + name + + + + + CLUSTER_CONNECTION_STARTED (14) + name + + + + + CLUSTER_CONNECTION_STOPPED (15) + name + + + + + ACCEPTOR_STARTED (16) + factory, id + + + + + ACCEPTOR_STOPPED (17) + factory, id + + + + + PROPOSAL (18) + _JBM_ProposalGroupId, _JBM_ProposalValue, + _HQ_Binding_Type, _HQ_Address, + _HQ_Distance + + + + + PROPOSAL_RESPONSE (19) + _JBM_ProposalGroupId, _JBM_ProposalValue, + _JBM_ProposalAltValue, _HQ_Binding_Type, + _HQ_Address, _HQ_Distance + + +
+
+
+ Message Counters + Message counters can be used to obtain information on queues over + time as HornetQ keeps a history on queue metrics. + They can be used to show trends on queues. For example, using the + management API, it would be possible to query the number of messages in a queue at regular + interval. However, this would not be enough to know if the queue is used: the number of + messages can remain constant because nobody is sending or receiving messages from the queue + or because there are as many messages sent to the queue than messages consumed from it. The + number of messages in the queue remains the same in both cases but its use is widely + different. + Message counters gives additional information about the queues: + + + count + The total number of messages added to the queue since the + server was started + + + countDelta + the number of messages added to the queue since the last message counter + update + + + messageCount + The current number of messages in the queue + + + messageCountDelta + The overall number of messages added/removed from the queue + since the last message counter update. For example, if + messageCountDelta is equal to -10 this means that + overall 10 messages have been removed from the queue (e.g. 2 messages were added and + 12 were removed) + + + lastAddTimestamp + The timestamp of the last time a message was added to the queue + + + udpateTimestamp + The timestamp of the last message counter update + + + These attributes can be used to determine other meaningful data as well. For example, to know + specifically how many messages were consumed from the queue since the last update + simply subtract the messageCountDelta from countDelta. +
+ Configuring Message Counters + By default, message counters are disabled as it might have a small negative effect on + memory. + To enable message counters, you can set it to true in hornetq-configuration.xml: + +<message-counter-enabled>true</message-counter-enabled> + Message counters keeps a history of the queue metrics (10 days by default) and + samples all the queues at regular interval (10 seconds by default). If message counters + are enabled, these values should be configured to suit your messaging use case in + hornetq-configuration.xml: + +<!-- keep history for a week --> +<message-counter-max-day-history>7</message-counter-max-day-history> +<!-- sample the queues every minute (60000ms) --> +<message-counter-sample-period>60000</message-counter-sample-period> + Message counters can be retrieved using the Management API. For example, to retrieve + message counters on a JMS Queue using JMX: + +// retrieve a connection to HornetQ's MBeanServer +MBeanServerConnection mbsc = ... +JMSQueueControlMBean queueControl = (JMSQueueControl)MBeanServerInvocationHandler.newProxyInstance(mbsc, + on, + JMSQueueControl.class, + false); +// message counters are retrieved as a JSON String +String counters = queueControl.listMessageCounter(); +// use the MessageCounterInfo helper class to manipulate message counters more easily +MessageCounterInfo messageCounter = MessageCounterInfo.fromJSON(counters); +System.out.format("%s message(s) in the queue (since last sample: %s)\n", +messageCounter.getMessageCount(), +messageCounter.getMessageCountDelta()); +
+
+ Example + See for an example which shows how to use + message counters to retrieve information on a JMS Queue. +
+
+
+ Administering HornetQ Resources Using The JBoss AS Admin Console + Its possible to create and configure HornetQ resources via the admin console within the JBoss Application Server. + The Admin Console will allow you to create destinations (JMS Topics and Queues) and JMS Connection Factories. + Once logged in to the admin console you will see a JMS Manager item in the left hand tree. All HornetQ resources + will be configured via this. This will have a child items for JMS Queues, Topics and Connection Factories, clicking + on each node will reveal which resources are currently available. The following sections explain how to create + and configure each resource in turn. +
+ JMS Queues + To create a new JMS Queue click on the JMS Queues item to reveal the available queues. On the right hand + panel you will see an add a new resource button, click on this and then choose the default(JMS Queue) template + and click continue. The important things to fill in here are the name of the queue and the JNDI name of the + queue. The JNDI name is what you will use to look up the queue in JNDI from your client. For most queues this + will be the only info you will need to provide as sensible defaults are provided for the others. You will also + see a security roles section near the bottom. If you do not provide any roles for this queue then the servers + default security configuration will be used, after you have created the queue these will be shown in the configuration. + All configuration values, except the name and JNDI name, can be changed via the configuration tab after clicking + on the queue in the admin console. The following section explains these in more detail + After highlighting the configuration you will see the following screen + + + + The name and JNDI name can't be changed, if you want to change these recreate the queue with the appropriate + settings. The rest of the configuration options, apart from security roles, relate to address settings for a particular + address. The default address settings are picked up from the servers configuration, if you change any of these + settings or create a queue via the console a new Address Settings entry will be added. For a full explanation on + Address Settings see + To delete a queue simply click on the delete button beside the queue name in the main JMS Queues screen. + This will also delete any address settings or security settings previously created for the queues address + The last part of the configuration options are security roles. If non are provided on creation then the + servers default security settings will be shown. If these are changed or updated then new security settings are + created for the address of this queue. For more information on security setting see + It is also possible via the metrics tab to view statistics for this queue. This will show statistics such + as message count, consumer count etc. + Operations can be performed on a queue via the control tab. This will allow you to start and stop the queue, + list,move,expire and delete messages from the queue and other useful operations. To invoke an operation click on + the button for the operation you want, this will take you to a screen where you can parameters for the operation can be set. + Once set clicking the ok button will invoke the operation, results appear at the bottom of the screen. +
+
+ JMS Topics + Creating and configuring JMS Topics is almost identical to creating queues. The only difference is that the + configuration will be applied to the queue representing a subscription. +
+
+ JMS Connection Factories + The format for creating connection factories is the same as for JMS Queues and topics apart from the configuration + being different. For as list of all the connection factory settings see the configuration index +
+
+
diff --git a/docs/user-manual/en/message-expiry.xml b/docs/user-manual/en/message-expiry.xml new file mode 100644 index 0000000000..e4d1f3762d --- /dev/null +++ b/docs/user-manual/en/message-expiry.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Message Expiry + Messages can be set with an optional time to live when sending + them. + HornetQ will not deliver a message to a consumer after it's time to live has been exceeded. + If the message hasn't been delivered by the time that time to live is reached the server can + discard it. + HornetQ's addresses can be assigned a expiry address so that, when messages are expired, + they are removed from the queue and sent to the expiry address. Many different queues can be + bound to an expiry address. These expired messages can later be consumed + for further inspection. +
+ Message Expiry + Using HornetQ Core API, you can set an expiration time directly on the message: + +// message will expire in 5000ms from now +message.setExpiration(System.currentTimeMillis() + 5000); + JMS MessageProducer allows to set a TimeToLive for the messages it sent: + +// messages sent by this producer will be retained for 5s (5000ms) before expiration +producer.setTimeToLive(5000); + Expired messages which are consumed from an expiry address have the following + properties: + + + _HQ_ORIG_ADDRESS + a String property containing the original address of the + expired message + + + _HQ_ORIG_QUEUE + a String property containing the original queue of the + expired message + + + _HQ_ACTUAL_EXPIRY + a Long property containing the actual expiration time of the + expired message + + +
+
+ Configuring Expiry Addresses + Expiry address are defined in the address-setting configuration: + +<!-- expired messages in exampleQueue will be sent to the expiry address expiryQueue --> +<address-setting match="jms.queue.exampleQueue"> + <expiry-address>jms.queue.expiryQueue</expiry-address> +</address-setting> + If messages are expired and no expiry address is specified, messages are simply removed + from the queue and dropped. Address wildcards can be used to configure expiry address for a + set of addresses (see ). +
+
+ Configuring The Expiry Reaper Thread + A reaper thread will periodically inspect the queues to check if messages have + expired. + The reaper thread can be configured with the following properties in hornetq-configuration.xml + + + message-expiry-scan-period + How often the queues will be scanned to detect expired messages (in milliseconds, + default is 30000ms, set to -1 to disable the reaper thread) + + + message-expiry-thread-priority + The reaper thread priority (it must be between 0 and 9, 9 being the highest + priority, default is 3) + + +
+
+ Example + See for an example which shows how message expiry is + configured and used with JMS. +
+
diff --git a/docs/user-manual/en/message-grouping.xml b/docs/user-manual/en/message-grouping.xml new file mode 100644 index 0000000000..ce4e04c718 --- /dev/null +++ b/docs/user-manual/en/message-grouping.xml @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Message Grouping + Message groups are sets of messages that have the following characteristics: + + + Messages in a message group share the same group id, i.e. they have same group + identifier property (JMSXGroupID for JMS, _HQ_GROUP_ID for HornetQ Core API). + + + Messages in a message group are always consumed by the same consumer, even if there + are many consumers on a queue. They pin all messages with the same group id to the same + consumer. If that consumer closes another consumer is chosen and will receive all + messages with the same group id. + + + Message groups are useful when you want all messages for a certain value of the property to + be processed serially by the same consumer. + An example might be orders for a certain stock. You may want orders for any particular + stock to be processed serially by the same consumer. To do this you can create a pool of + consumers (perhaps one for each stock, but less will work too), then set the stock name as the + value of the _HQ_GROUP_ID property. + This will ensure that all messages for a particular stock will always be processed by the + same consumer. + + Grouped messages can impact the concurrent processing of non-grouped messages due to the + underlying FIFO semantics of a queue. For example, if there is a chunk of 100 grouped messages at + the head of a queue followed by 1,000 non-grouped messages then all the grouped messages will need + to be sent to the appropriate client (which is consuming those grouped messages serially) before + any of the non-grouped messages can be consumed. The functional impact in this scenario is a + temporary suspension of concurrent message processing while all the grouped messages are processed. + This can be a performance bottleneck so keep it in mind when determining the size of your message + groups, and consider whether or not you should isolate your grouped messages from your non-grouped + messages. + +
+ Using Core API + The property name used to identify the message group is "_HQ_GROUP_ID" (or the constant MessageImpl.HDR_GROUP_ID). Alternatively, you can set autogroup to true on the SessionFactory which will pick a + random unique id. +
+
+ Using JMS + The property name used to identify the message group is JMSXGroupID. + + // send 2 messages in the same group to ensure the same + // consumer will receive both + Message message = ... + message.setStringProperty("JMSXGroupID", "Group-0"); + producer.send(message); + + message = ... + message.setStringProperty("JMSXGroupID", "Group-0"); + producer.send(message); + Alternatively, you can set autogroup to true on the HornetQConnectonFactory which will pick a random unique id. This can also be + set in the hornetq-jms.xml file like this: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <autogroup>true</autogroup> +</connection-factory> + Alternatively you can set the group id via the connection factory. All messages sent + with producers created via this connection factory will set the JMSXGroupID to the specified value on all messages sent. To configure the + group id set it on the connection factory in the hornetq-jms.xml config + file as follows + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <group-id>Group-0</group-id> +</connection-factory> +
+
+ Example + See for an example which shows how message + groups are configured and used with JMS. +
+
+ Example + See for an example which shows how message + groups are configured via a connection factory. +
+
+ Clustered Grouping + Using message groups in a cluster is a bit more complex. This is because messages with a + particular group id can arrive on any node so each node needs to know about which group + id's are bound to which consumer on which node. The consumer handling messages for a + particular group id may be on a different node of the cluster, so each node needs to know + this information so it can route the message correctly to the node which has that consumer. + To solve this there is the notion of a grouping handler. Each node will have its own + grouping handler and when a messages is sent with a group id assigned, the handlers will + decide between them which route the message should take. + There are 2 types of handlers; Local and Remote. Each cluster should choose 1 node to + have a local grouping handler and all the other nodes should have remote handlers- it's the + local handler that actually makes the decision as to what route should be used, all the + other remote handlers converse with this. Here is a sample config for both types of + handler, this should be configured in the hornetq-configuration.xml + file. +<grouping-handler name="my-grouping-handler"> + <type>LOCAL</type> + <address>jms</address> + <timeout>5000</timeout> +</grouping-handler> + +<grouping-handler name="my-grouping-handler"> + <type>REMOTE</type> + <address>jms</address> + <timeout>5000</timeout> +</grouping-handler> + The address attribute refers to a + cluster connection and the address it uses, + refer to the clustering section on how to configure clusters. The + timeout attribute referees to how long to wait for a + decision to be made, an exception will be thrown during the send if this timeout is + reached, this ensures that strict ordering is kept. + The decision as to where a message should be routed to is initially proposed by the node + that receives the message. The node will pick a suitable route as per the normal clustered + routing conditions, i.e. round robin available queues, use a local queue first and choose a + queue that has a consumer. If the proposal is accepted by the grouping handlers the node + will route messages to this queue from that point on, if rejected an alternative route will + be offered and the node will again route to that queue indefinitely. All other nodes will + also route to the queue chosen at proposal time. Once the message arrives at the queue then + normal single server message group semantics take over and the message is pinned to a + consumer on that queue. + You may have noticed that there is a single point of failure with the single local + handler. If this node crashes then no decisions will be able to be made. Any messages sent + will be not be delivered and an exception thrown. To avoid this happening Local Handlers + can be replicated on another backup node. Simple create your back up node and configure it + with the same Local handler. + +
+ Clustered Grouping Best Practices + Some best practices should be followed when using clustered grouping: + + Make sure your consumers are distributed evenly across the different nodes + if possible. This is only an issue if you are creating and closing consumers + regularly. Since messages are always routed to the same queue once pinned, + removing a consumer from this queue may leave it with no consumers meaning the + queue will just keep receiving the messages. Avoid closing consumers or make + sure that you always have plenty of consumers, i.e., if you have 3 nodes have 3 + consumers. + + + Use durable queues if possible. If queues are removed once a group is bound + to it, then it is possible that other nodes may still try to route messages to + it. This can be avoided by making sure that the queue is deleted by the session + that is sending the messages. This means that when the next message is sent it + is sent to the node where the queue was deleted meaning a new proposal can + successfully take place. Alternatively you could just start using a different + group id. + + + Always make sure that the node that has the Local Grouping Handler is + replicated. These means that on failover grouping will still occur. + + + In case you are using group-timeouts, the remote node should have a smaller group-timeout with at least half + of the value on the main coordinator. This is because this will determine how often the last-time-use + value should be updated with a round trip for a request to the group between the nodes. + + +
+
+ Clustered Grouping Example + See for an example of how to configure + message groups with a HornetQ cluster +
+
+
diff --git a/docs/user-manual/en/messaging-concepts.xml b/docs/user-manual/en/messaging-concepts.xml new file mode 100644 index 0000000000..241fd98608 --- /dev/null +++ b/docs/user-manual/en/messaging-concepts.xml @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Messaging Concepts + HornetQ is an asynchronous messaging system, an example of Message Oriented + Middleware , we'll just call them messaging systems in the remainder of this + book. + 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. + If you're already familiar with what a messaging system is and what it's capable of, then + you can skip this chapter. +
+ Messaging Concepts + Messaging systems allow you to loosely couple heterogeneous systems together, whilst + typically providing reliability, transactions and many other features. + Unlike systems based on a Remote Procedure + Call (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. + 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 latency of your network. With an + asynchronous system you can pipeline flows of messages in different directions, so are + limited by the network bandwidth not the latency. + This typically allows you to create much higher performance applications. + 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. + 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 + Enterprise Service + Bus. (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. +
+
+ Messaging styles + Messaging systems normally support two main styles of asynchronous messaging: message queue messaging + (also known as point-to-point messaging) and publish subscribe + messaging. We'll summarise them briefly here: +
+ The Message Queue Pattern + 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. + 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 producers) to the queue are + completely decoupled from receivers (also known as consumers) of the queue - they do not know of each other's + existence. + 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. + 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 ACID properties. +
+
+ The Publish-Subscribe Pattern + With publish-subscribe messaging many senders can send messages to an entity on + the server, often called a topic (e.g. in the JMS + world). + There can be many subscriptions on a topic, a subscription is + just another word for a consumer of a topic. Each subscription receives a + copy of each message + sent to the topic. This differs from the message queue pattern where each message is + only consumed by a single consumer. + Subscriptions can optionally be durable 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. + 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. +
+
+
+ Delivery guarantees + A key feature of most messaging systems is reliable + messaging. 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. + 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. +
+
+ Transactions + 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. +
+
+ Durability + 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. +
+
+ Messaging APIs and protocols + How do client applications interact with messaging systems in order to send and + consume messages? + Several messaging systems provide their own proprietary APIs with which the client + communicates with the messaging system. + There are also some standard ways of operating with messaging systems and some + emerging standards in this space. + Let's take a brief look at these: +
+ Java Message Service (JMS) + JMS 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. + JMS is a very popular API and is implemented by most messaging systems. JMS is + only available to clients running Java. + 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. + HornetQ provides a fully compliant JMS 1.1 and JMS 2.0 API. +
+
+ System specific APIs + 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. + 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. +
+
+ RESTful API + REST approaches to messaging are showing a lot interest + recently. + 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. + 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. + 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. + Please see for using HornetQ's RESTful interface. +
+
+ STOMP + Stomp 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. + Please see for using STOMP with HornetQ. +
+
+ AMQP + AMQP 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. + HornetQ implements the AMQP 1.0 + specification. Any client that supports the 1.0 specification will be able to interact with HornetQ. +
+
+
+ High Availability + 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. + HornetQ provides automatic failover where your sessions are automatically reconnected + to the backup server on event of live server failure. + For more information on HA, please see . +
+
+ Clusters + Many messaging systems allow you to create groups of messaging servers called + clusters. 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. + 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. + 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. + HornetQ also has the ability to automatically redistribute messages between nodes of a + cluster to prevent starvation on any particular node. + For full details on clustering, please see . +
+
+ Bridges and routing + 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. + 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. + HornetQ bridges can be configured with filter expressions to only forward certain + messages, and transformation can also be hooked in. + 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. + For more information please see and . +
+
diff --git a/docs/user-manual/en/notice.xml b/docs/user-manual/en/notice.xml new file mode 100644 index 0000000000..5ed879bd2d --- /dev/null +++ b/docs/user-manual/en/notice.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + + Legal Notice + + Copyright © 2010 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. + \ No newline at end of file diff --git a/docs/user-manual/en/paging.xml b/docs/user-manual/en/paging.xml new file mode 100644 index 0000000000..4a69037ab2 --- /dev/null +++ b/docs/user-manual/en/paging.xml @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Paging + HornetQ transparently supports huge queues containing millions of messages while the + server is running with limited memory. + In such a situation it's not possible to store all of the queues in memory at any one + time, so HornetQ transparently pages messages into and out of memory as + they are needed, thus allowing massive queues with a low memory footprint. + HornetQ will start paging messages to disk, when the size of all messages in memory for an + address exceeds a configured maximum size. + By default, HornetQ does not page messages - this must be explicitly configured to + activate it. +
+ Page Files + Messages are stored per address on the file system. Each address has an individual + folder where messages are stored in multiple files (page files). Each file will contain + messages up to a max configured size (page-size-bytes). The system + will navigate on the files as needed, and it will remove the page file as soon as all + the messages are acknowledged up to that point. + Browsers will read through the page-cursor system. + Consumers with selectors will also navigate through the page-files and it will ignore + messages that don't match the criteria. +
+
+ Configuration + You can configure the location of the paging folder + Global paging parameters are specified on the main configuration file (hornetq-configuration.xml). + +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd"> +... +<paging-directory>/somewhere/paging-directory</paging-directory> +... + + + Paging Configuration Parameters + + + + + + + Property Name + Description + Default + + + + + paging-directory + Where page files are stored. HornetQ will create one folder for + each address being paged under this configured location. + data/paging + + + +
+
+
+
+ Paging Mode + As soon as messages delivered to an address exceed the configured size, that address + alone goes into page mode. + + Paging is done individually per address. If you configure a max-size-bytes for an + address, that means each matching address will have a maximum size that you + specified. It DOES NOT mean that the total overall size of all matching addresses is + limited to max-size-bytes. + +
+ Configuration + Configuration is done at the address settings, done at the main configuration file + (hornetq-configuration.xml). + +<address-settings> + <address-setting match="jms.someaddress"> + <max-size-bytes>104857600</max-size-bytes> + <page-size-bytes>10485760</page-size-bytes> + <address-full-policy>PAGE</address-full-policy> + </address-setting> +</address-settings> + This is the list of available parameters on the address settings. + + + Paging Address Settings + + + + + + + Property Name + Description + Default + + + + + max-size-bytes + What's the max memory the address could have before entering + on page mode. + -1 (disabled) + + + page-size-bytes + The size of each page file used on the paging system + 10MiB (10 * 1024 * 1024 bytes) + + + address-full-policy + This must be set to PAGE for paging to enable. If the value + is PAGE then further messages will be paged to disk. If the + value is DROP then further messages will be silently dropped. If + the value is FAIL then the messages will be dropped and the client + message producers will receive an exception. If the value is + BLOCK then client message producers will block when they try and + send further messages. + PAGE + + + page-max-cache-size + The system will keep up to <page-max-cache-size page files in memory to + optimize IO during paging navigation. + 5 + + + +
+
+
+
+
+ Dropping messages + Instead of paging messages when the max size is reached, an address can also be + configured to just drop messages when the address is full. + To do this just set the address-full-policy to DROP in the address settings +
+
+ Dropping messages and throwing an exception to producers + Instead of paging messages when the max size is reached, an address can also be + configured to drop messages and also throw an exception on the client-side + when the address is full. + To do this just set the address-full-policy to FAIL in the address settings +
+
+ Blocking producers + Instead of paging messages when the max size is reached, an address can also be + configured to block producers from sending further messages when the address is full, + thus preventing the memory being exhausted on the server. + When memory is freed up on the server, producers will automatically unblock and be + able to continue sending. + To do this just set the address-full-policy to BLOCK in the address settings + In the default configuration, all addresses are configured to block producers after 10 + MiB of data are in the address. +
+
+ Caution with Addresses with Multiple Queues + When a message is routed to an address that has multiple queues bound to it, e.g. a + JMS subscription in a Topic, there is only 1 copy of the message in memory. Each queue + only deals with a reference to this. Because of this the memory is only freed up once + all queues referencing the message have delivered it. + If you have a single lazy subscription, the entire address will suffer IO performance + hit as all the queues will have messages being sent through an extra storage on the + paging system. + For example: + + + An address has 10 queues + + + One of the queues does not deliver its messages (maybe because of a slow + consumer). + + + Messages continually arrive at the address and paging is started. + + + The other 9 queues are empty even though messages have been sent. + + + In this example all the other 9 queues will be consuming messages from the page + system. This may cause performance issues if this is an undesirable state. +
+
+ Example + See for an example which shows how to use paging + with HornetQ. +
+
diff --git a/docs/user-manual/en/perf-tuning.xml b/docs/user-manual/en/perf-tuning.xml new file mode 100644 index 0000000000..da0c2ede70 --- /dev/null +++ b/docs/user-manual/en/perf-tuning.xml @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Performance Tuning + In this chapter we'll discuss how to tune HornetQ for optimum performance. +
+ Tuning persistence + + + Put the message journal on its own physical volume. If the disk is shared with + other processes e.g. transaction co-ordinator, database or other journals which + are also reading and writing from it, then this may greatly reduce performance + since the disk head may be skipping all over the place between the different + files. One of the advantages of an append only journal is that disk head + movement is minimised - this advantage is destroyed if the disk is shared. If + you're using paging or large messages make sure they're ideally put on separate + volumes too. + + + Minimum number of journal files. Set journal-min-files to a + number of files that would fit your average sustainable rate. If you see new + files being created on the journal data directory too often, i.e. lots of data + is being persisted, you need to increase the minimal number of files, this way + the journal would reuse more files instead of creating new data files. + + + Journal file size. The journal file size should be aligned to the capacity of + a cylinder on the disk. The default value 10MiB should be enough on most + systems. + + + Use AIO journal. If using Linux, try to keep your journal type as AIO. AIO + will scale better than Java NIO. + + + Tune journal-buffer-timeout. The timeout can be increased + to increase throughput at the expense of latency. + + + If you're running AIO you might be able to get some better performance by + increasing journal-max-io. DO NOT change this parameter if + you are running NIO. + + +
+
+ Tuning JMS + There are a few areas where some tweaks can be done if you are using the JMS + API + + + Disable message id. Use the setDisableMessageID() method on + the MessageProducer class to disable message ids if you don't + need them. This decreases the size of the message and also avoids the overhead + of creating a unique ID. + + + Disable message timestamp. Use the setDisableMessageTimeStamp() method on the MessageProducer class to disable message timestamps if you don't + need them. + + + Avoid ObjectMessage. ObjectMessage is + convenient but it comes at a cost. The body of a ObjectMessage uses Java serialization to serialize it to bytes. + The Java serialized form of even small objects is very verbose so takes up a lot + of space on the wire, also Java serialization is slow compared to custom + marshalling techniques. Only use ObjectMessage if you really + can't use one of the other message types, i.e. if you really don't know the type + of the payload until run-time. + + + Avoid AUTO_ACKNOWLEDGE. AUTO_ACKNOWLEDGE + mode requires an acknowledgement to be sent from the server for each message + received on the client, this means more traffic on the network. If you can, use + DUPS_OK_ACKNOWLEDGE or use CLIENT_ACKNOWLEDGE or a transacted session and batch up many + acknowledgements with one acknowledge/commit. + + + Avoid durable messages. By default JMS messages are durable. If you don't + really need durable messages then set them to be non-durable. Durable messages + incur a lot more overhead in persisting them to storage. + + + Batch many sends or acknowledgements in a single transaction. HornetQ will + only require a network round trip on the commit, not on every send or + acknowledgement. + + +
+
+ Other Tunings + There are various other places in HornetQ where we can perform some tuning: + + + Use Asynchronous Send Acknowledgements. If you need to send durable messages + non transactionally and you need a guarantee that they have reached the server + by the time the call to send() returns, don't set durable messages to be sent + blocking, instead use asynchronous send acknowledgements to get your + acknowledgements of send back in a separate stream, see for more information on this. + + + Use pre-acknowledge mode. With pre-acknowledge mode, messages are acknowledged + before they are sent to the client. This reduces the + amount of acknowledgement traffic on the wire. For more information on this, see + . + + + Disable security. You may get a small performance boost by disabling security + by setting the security-enabled parameter to false in hornetq-configuration.xml. + + + Disable persistence. If you don't need message persistence, turn it off + altogether by setting persistence-enabled to false in + hornetq-configuration.xml. + + + Sync transactions lazily. Setting journal-sync-transactional to false in + hornetq-configuration.xml can give you better + transactional persistent performance at the expense of some possibility of loss + of transactions on failure. See for more + information. + + + Sync non transactional lazily. Setting journal-sync-non-transactional to false in + hornetq-configuration.xml can give you better + non-transactional persistent performance at the expense of some possibility of + loss of durable messages on failure. See for + more information. + + + Send messages non blocking. Setting block-on-durable-send + and block-on-non-durable-send to false in + hornetq-jms.xml (if you're using JMS and JNDI) or + directly on the ServerLocator. This means you don't have to wait a whole + network round trip for every message sent. See + for more information. + + + If you have very fast consumers, you can increase consumer-window-size. This + effectively disables consumer flow control. + + + Socket NIO vs Socket Old IO. By default HornetQ uses old (blocking) on the + server and the client side (see the chapter on configuring transports for more + information ). NIO is much more scalable + but can give you some latency hit compared to old blocking IO. If you need to be + able to service many thousands of connections on the server, then you should + make sure you're using NIO on the server. However, if don't expect many + thousands of connections on the server you can keep the server acceptors using + old IO, and might get a small performance advantage. + + + Use the core API not JMS. Using the JMS API you will have slightly lower + performance than using the core API, since all JMS operations need to be + translated into core operations before the server can handle them. If using the + core API try to use methods that take SimpleString as much as + possible. SimpleString, unlike java.lang.String does not + require copying before it is written to the wire, so if you re-use SimpleString instances between calls then you can avoid some + unnecessary copying. + + +
+
+ Tuning Transport Settings + + + TCP buffer sizes. If you have a fast network and fast machines you may get a + performance boost by increasing the TCP send and receive buffer sizes. See the + for more information on this. + + Note that some operating systems like later versions of Linux include TCP + auto-tuning and setting TCP buffer sizes manually can prevent auto-tune from + working and actually give you worse performance! + + + + Increase limit on file handles on the server. If you expect a lot of + concurrent connections on your servers, or if clients are rapidly opening and + closing connections, you should make sure the user running the server has + permission to create sufficient file handles. + This varies from operating system to operating system. On Linux systems you + can increase the number of allowable open file handles in the file /etc/security/limits.conf e.g. add the lines + +serveruser soft nofile 20000 +serveruser hard nofile 20000 + This would allow up to 20000 file handles to be open by the user serveruser. + + + Use batch-delay and set direct-deliver + to false for the best throughput for very small messages. HornetQ comes with a + preconfigured connector/acceptor pair (netty-throughput) in + hornetq-configuration.xml and JMS connection factory + (ThroughputConnectionFactory) in hornetq-jms.xmlwhich can be used to give the very best + throughput, especially for small messages. See the for more information on this. + + +
+
+ Tuning the VM + We highly recommend you use the latest Java JVM for the best performance. We test + internally using the Sun JVM, so some of these tunings won't apply to JDKs from other + providers (e.g. IBM or JRockit) + + + Garbage collection. For smooth server operation we recommend using a parallel + garbage collection algorithm, e.g. using the JVM argument -XX:+UseParallelOldGC on Sun JDKs. + + + Memory settings. Give as much memory as you can to the server. HornetQ can run + in low memory by using paging (described in ) but if it + can run with all queues in RAM this will improve performance. The amount of + memory you require will depend on the size and number of your queues and the + size and number of your messages. Use the JVM arguments -Xms + and -Xmx to set server available RAM. We recommend setting + them to the same high value. + + + Aggressive options. Different JVMs provide different sets of JVM tuning + parameters, for the Sun Hotspot JVM the full list of options is available here. We recommend at least using -XX:+AggressiveOpts and + -XX:+UseFastAccessorMethods. You may get some mileage with the + other tuning parameters depending on your OS platform and application usage + patterns. + + +
+
+ Avoiding Anti-Patterns + + + Re-use connections / sessions / consumers / producers. Probably the most + common messaging anti-pattern we see is users who create a new + connection/session/producer for every message they send or every message they + consume. This is a poor use of resources. These objects take time to create and + may involve several network round trips. Always re-use them. + + Some popular libraries such as the Spring JMS Template are known to use + these anti-patterns. If you're using Spring JMS Template and you're getting + poor performance you know why. Don't blame HornetQ! The Spring JMS Template + can only safely be used in an app server which caches JMS sessions (e.g. + using JCA), and only then for sending messages. It cannot be safely be used + for synchronously consuming messages, even in an app server. + + + + Avoid fat messages. Verbose formats such as XML take up a lot of space on the + wire and performance will suffer as result. Avoid XML in message bodies if you + can. + + + Don't create temporary queues for each request. This common anti-pattern + involves the temporary queue request-response pattern. With the temporary queue + request-response pattern a message is sent to a target and a reply-to header is + set with the address of a local temporary queue. When the recipient receives the + message they process it then send back a response to the address specified in + the reply-to. A common mistake made with this pattern is to create a new + temporary queue on each message sent. This will drastically reduce performance. + Instead the temporary queue should be re-used for many requests. + + + Don't use Message-Driven Beans for the sake of it. As soon as you start using + MDBs you are greatly increasing the codepath for each message received compared + to a straightforward message consumer, since a lot of extra application server + code is executed. Ask yourself do you really need MDBs? Can you accomplish the + same task using just a normal message consumer? + + +
+
diff --git a/docs/user-manual/en/persistence.xml b/docs/user-manual/en/persistence.xml new file mode 100644 index 0000000000..1e15c65ad3 --- /dev/null +++ b/docs/user-manual/en/persistence.xml @@ -0,0 +1,357 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Persistence + In this chapter we will describe how persistence works with HornetQ and how to configure + it. + HornetQ ships with a high performance journal. Since HornetQ handles its own persistence, + rather than relying on a database or other 3rd party persistence engine it is very highly + optimised for the specific messaging use cases. + A HornetQ journal is an append only journal. It consists of a set of + files on disk. Each file is pre-created to a fixed size and initially filled with padding. + As operations are performed on the server, e.g. add message, update message, delete message, + records are appended to the journal. When one journal file is full we move to the next + one. + Because records are only appended, i.e. added to the end of the journal we minimise disk + head movement, i.e. we minimise random access operations which is typically the slowest + operation on a disk. + Making the file size configurable means that an optimal size can be chosen, i.e. making + each file fit on a disk cylinder. Modern disk topologies are complex and we are not in + control over which cylinder(s) the file is mapped onto so this is not an exact science. But + by minimising the number of disk cylinders the file is using, we can minimise the amount of + disk head movement, since an entire disk cylinder is accessible simply by the disk rotating + - the head does not have to move. + As delete records are added to the journal, HornetQ has a sophisticated file garbage + collection algorithm which can determine if a particular journal file is needed any more - + i.e. has all its data been deleted in the same or other files. If so, the file can be + reclaimed and re-used. + HornetQ also has a compaction algorithm which removes dead space from the journal and + compresses up the data so it takes up less files on disk. + The journal also fully supports transactional operation if required, supporting both local + and XA transactions. + The majority of the journal is written in Java, however we abstract out the interaction + with the actual file system to allow different pluggable implementations. HornetQ ships with + two implementations: + + + Java NIO. + The first implementation uses standard Java NIO to interface with the file system. + This provides extremely good performance and runs on any platform where there's a + Java 6+ runtime. + + + Linux Asynchronous IO + The second implementation uses a thin native code wrapper to talk to the Linux + asynchronous IO library (AIO). With AIO, HornetQ will be called back when the data + has made it to disk, allowing us to avoid explicit syncs altogether and simply send + back confirmation of completion when AIO informs us that the data has been + persisted. + Using AIO will typically provide even better performance than using Java + NIO. + The AIO journal is only available when running Linux kernel 2.6 or later and after + having installed libaio (if it's not already installed). For instructions on how to + install libaio please see . + Also, please note that AIO will only work with the following file systems: ext2, + ext3, ext4, jfs, xfs. With other file systems, e.g. NFS it may appear to work, but + it will fall back to a slower synchronous behaviour. Don't put the journal on a NFS + share! + For more information on libaio please see . + libaio is part of the kernel project. + + + The standard HornetQ core server uses two instances of the journal: + + + Bindings journal. + This journal is used to store bindings related data. That includes the set of + queues that are deployed on the server and their attributes. It also stores data + such as id sequence counters. + The bindings journal is always a NIO journal as it is typically low throughput + compared to the message journal. + The files on this journal are prefixed as hornetq-bindings. + Each file has a bindings extension. File size is 1048576, and it is located at the bindings folder. + + + JMS journal. + This journal instance stores all JMS related data, This is basically any JMS + Queues, Topics and Connection Factories and any JNDI bindings for these + resources. + Any JMS Resources created via the management API will be persisted to this + journal. Any resources configured via configuration files will not. The JMS Journal + will only be created if JMS is being used. + The files on this journal are prefixed as hornetq-jms. Each + file has a jms extension. File size is 1048576, and it is located at the bindings folder. + + + Message journal. + This journal instance stores all message related data, including the message + themselves and also duplicate-id caches. + By default HornetQ will try and use an AIO journal. If AIO is not available, e.g. + the platform is not Linux with the correct kernel version or AIO has not been + installed then it will automatically fall back to using Java NIO which is available + on any Java platform. + The files on this journal are prefixed as hornetq-data. Each + file has a hq extension. File size is by the default 10485760 (configurable), and it is located at the journal + folder. + + + For large messages, HornetQ persists them outside the message journal. This is discussed + in . + HornetQ can also be configured to page messages to disk in low memory situations. This is + discussed in . + If no persistence is required at all, HornetQ can also be configured not to persist any + data at all to storage as discussed in . +
+ Configuring the bindings journal + The bindings journal is configured using the following attributes in hornetq-configuration.xml + + + bindings-directory + This is the directory in which the bindings journal lives. The default value + is data/bindings. + + + create-bindings-dir + If this is set to true then the bindings directory will be + automatically created at the location specified in bindings-directory if it does not already exist. The default + value is true + + +
+
+ Configuring the jms journal + The jms config shares its configuration with the bindings journal. +
+
+ Configuring the message journal + The message journal is configured using the following attributes in hornetq-configuration.xml + + + journal-directory + This is the directory in which the message journal lives. The default value is + data/journal. + For the best performance, we recommend the journal is located on its own + physical volume in order to minimise disk head movement. If the journal is on a + volume which is shared with other processes which might be writing other files + (e.g. bindings journal, database, or transaction coordinator) then the disk head + may well be moving rapidly between these files as it writes them, thus + drastically reducing performance. + When the message journal is stored on a SAN we recommend each journal instance + that is stored on the SAN is given its own LUN (logical unit). + + + create-journal-dir + If this is set to true then the journal directory will be + automatically created at the location specified in journal-directory if it does not already exist. The default value + is true + + + journal-type + Valid values are NIO or ASYNCIO. + Choosing NIO chooses the Java NIO journal. Choosing + AIO chooses the Linux asynchronous IO journal. If you + choose AIO but are not running Linux or you do not have + libaio installed then HornetQ will detect this and automatically fall back to + using NIO. + + + journal-sync-transactional + If this is set to true then HornetQ will make sure all transaction data is + flushed to disk on transaction boundaries (commit, prepare and rollback). The + default value is true. + + + journal-sync-non-transactional + If this is set to true then HornetQ will make sure non transactional message + data (sends and acknowledgements) are flushed to disk each time. The default + value for this is true. + + + journal-file-size + The size of each journal file in bytes. The default value for this is 10485760 bytes (10MiB). + + + journal-min-files + The minimum number of files the journal will maintain. When HornetQ starts and + there is no initial message data, HornetQ will pre-create journal-min-files number of files. + Creating journal files and filling them with padding is a fairly expensive + operation and we want to minimise doing this at run-time as files get filled. By + pre-creating files, as one is filled the journal can immediately resume with the + next one without pausing to create it. + Depending on how much data you expect your queues to contain at steady state + you should tune this number of files to match that total amount of data. + + + journal-max-io + Write requests are queued up before being submitted to the system for + execution. This parameter controls the maximum number of write requests that can + be in the IO queue at any one time. If the queue becomes full then writes will + block until space is freed up. + When using NIO, this value should always be equal to 1 + When using AIO, the default should be 500. + The system maintains different defaults for this parameter depending on whether + it's NIO or AIO (default for NIO is 1, default for AIO is 500) + There is a limit and the total max AIO can't be higher than what is configured + at the OS level (/proc/sys/fs/aio-max-nr) usually at 65536. + + + journal-buffer-timeout + Instead of flushing on every write that requires a flush, we maintain an + internal buffer, and flush the entire buffer either when it is full, or when a + timeout expires, whichever is sooner. This is used for both NIO and AIO and + allows the system to scale better with many concurrent writes that require + flushing. + This parameter controls the timeout at which the buffer will be flushed if it + hasn't filled already. AIO can typically cope with a higher flush rate than NIO, + so the system maintains different defaults for both NIO and AIO (default for NIO + is 3333333 nanoseconds - 300 times per second, default for AIO is 500000 + nanoseconds - ie. 2000 times per second). + + By increasing the timeout, you may be able to increase system throughput + at the expense of latency, the default parameters are chosen to give a + reasonable balance between throughput and latency. + + + + journal-buffer-size + The size of the timed buffer on AIO. The default value is 490KiB. + + + journal-compact-min-files + The minimal number of files before we can consider compacting the journal. The + compacting algorithm won't start until you have at least journal-compact-min-files + The default for this parameter is 10 + + + journal-compact-percentage + The threshold to start compacting. When less than this percentage is + considered live data, we start compacting. Note also that compacting won't kick + in until you have at least journal-compact-min-files data + files on the journal + The default for this parameter is 30 + + +
+
+ An important note on disabling disk write cache. + + Most disks contain hardware write caches. A write cache can increase the apparent + performance of the disk because writes just go into the cache and are then lazily + written to the disk later. + This happens irrespective of whether you have executed a fsync() from the + operating system or correctly synced data from inside a Java program! + By default many systems ship with disk write cache enabled. This means that even + after syncing from the operating system there is no guarantee the data has actually + made it to disk, so if a failure occurs, critical data can be lost. + Some more expensive disks have non volatile or battery backed write caches which + won't necessarily lose data on event of failure, but you need to test them! + If your disk does not have an expensive non volatile or battery backed cache and + it's not part of some kind of redundant array (e.g. RAID), and you value your data + integrity you need to make sure disk write cache is disabled. + Be aware that disabling disk write cache can give you a nasty shock performance + wise. If you've been used to using disks with write cache enabled in their default + setting, unaware that your data integrity could be compromised, then disabling it + will give you an idea of how fast your disk can perform when acting really + reliably. + On Linux you can inspect and/or change your disk's write cache settings using the + tools hdparm (for IDE disks) or sdparm or + sginfo (for SDSI/SATA disks) + On Windows you can check / change the setting by right clicking on the disk and + clicking properties. + +
+
+ Installing AIO + The Java NIO journal gives great performance, but If you are running HornetQ using + Linux Kernel 2.6 or later, we highly recommend you use the AIO + journal for the very best persistence performance. + It's not possible to use the AIO journal under other operating systems or earlier + versions of the Linux kernel. + If you are running Linux kernel 2.6 or later and don't already have libaio installed, you can easily install it using the following + steps: + Using yum, (e.g. on Fedora or Red Hat Enterprise Linux): + yum install libaio + Using aptitude, (e.g. on Ubuntu or Debian system): + apt-get install libaio +
+
+ Configuring HornetQ for Zero Persistence + In some situations, zero persistence is sometimes required for a messaging system. + Configuring HornetQ to perform zero persistence is straightforward. Simply set the + parameter persistence-enabled in hornetq-configuration.xml to false. + Please note that if you set this parameter to false, then zero + persistence will occur. That means no bindings data, message data, large message data, + duplicate id caches or paging data will be persisted. +
+
+ Import/Export the Journal Data + You may want to inspect the existent records on each one of the journals used by + HornetQ, and you can use the export/import tool for that purpose. The export/import are + classes located at the hornetq-core.jar, you can export the journal as a text file by + using this command: + java -cp hornetq-core.jar org.hornetq.core.journal.impl.ExportJournal + <JournalDirectory> <JournalPrefix> <FileExtension> <FileSize> + <FileOutput> + To import the file as binary data on the journal (Notice you also require + netty.jar): + java -cp hornetq-core.jar:netty.jar org.hornetq.core.journal.impl.ImportJournal + <JournalDirectory> <JournalPrefix> <FileExtension> <FileSize> + <FileInput> + + + JournalDirectory: Use the configured folder for your selected folder. Example: + ./hornetq/data/journal + + + JournalPrefix: Use the prefix for your selected journal, as discussed + here + + + FileExtension: Use the extension for your selected journal, as discussed + here + + + FileSize: Use the size for your selected journal, as discussed here + + + FileOutput: text file that will contain the exported data + + +
+
diff --git a/docs/user-manual/en/pre-acknowledge.xml b/docs/user-manual/en/pre-acknowledge.xml new file mode 100644 index 0000000000..81abbe9c7d --- /dev/null +++ b/docs/user-manual/en/pre-acknowledge.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + %BOOK_ENTITIES; + ]> + + Extra Acknowledge Modes + JMS specifies 3 acknowledgement modes: + + + AUTO_ACKNOWLEDGE + + + CLIENT_ACKNOWLEDGE + + + DUPS_OK_ACKNOWLEDGE + + + HornetQ supports two additional modes: PRE_ACKNOWLEDGE and INDIVIDUAL_ACKNOWLEDGE + In some cases you can afford + to lose messages in event of failure, so it would make sense to acknowledge the message on the + server before delivering it to the client. + This extra mode is supported by HornetQ and will call it + pre-acknowledge mode. + The disadvantage of acknowledging on the server before delivery is that the message will be + lost if the system crashes after acknowledging the message on the server + but before it is delivered to the client. In that case, the message is + lost and will not be recovered when the system restart. + Depending on your messaging case, pre-acknowledgement mode can avoid + extra network traffic and CPU at the cost of coping with message loss. + An example of a use case for pre-acknowledgement is for stock price update messages. With + these messages it might be reasonable to lose a message in event of crash, since the next + price update message will arrive soon, overriding the previous price. + + Please note, that if you use pre-acknowledge mode, then you will lose transactional + semantics for messages being consumed, since clearly they are being acknowledged first on + the server, not when you commit the transaction. This may be stating the obvious but we + like to be clear on these things to avoid confusion! + +
+ Using PRE_ACKNOWLEDGE + This can be configured in the hornetq-jms.xml file on the connection factory like this: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <pre-acknowledge>true</pre-acknowledge> +</connection-factory> + Alternatively, to use pre-acknowledgement mode using the JMS API, create a JMS Session + with the HornetQSession.PRE_ACKNOWLEDGE constant. + +// messages will be acknowledge on the server *before* being delivered to the client +Session session = connection.createSession(false, HornetQJMSConstants.PRE_ACKNOWLEDGE); + Or you can set pre-acknowledge directly on the HornetQConnectionFactory instance using the setter method. + To use pre-acknowledgement mode using the core API you can set it directly on the + ClientSessionFactory instance using the setter method. +
+
+ Individual Acknowledge + A valid use-case for individual acknowledgement would be when you need to have your own scheduling and you don't know when your message processing will be finished. You should prefer having one consumer per thread worker + but this is not possible in some circumstances depending on how complex is your processing. For that you can use the individual Acknowledgement. + You basically setup Individual ACK by creating a session with the acknowledge mode with HornetQJMSConstants.INDIVIDUAL_ACKNOWLEDGE. Individual ACK inherits all the semantics from Client Acknowledge, + with the exception the message is individually acked. + + Please note, that to avoid confusion on MDB processing, Individual ACKNOWLEDGE is not supported through MDBs (or the inbound resource adapter). this is because you have to finish the process of your message inside the MDB. + + +
+
+ Example + See for an example which shows how to use + pre-acknowledgement mode with JMS. +
+
diff --git a/docs/user-manual/en/preface.xml b/docs/user-manual/en/preface.xml new file mode 100644 index 0000000000..2c1483b3de --- /dev/null +++ b/docs/user-manual/en/preface.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Preface + What is HornetQ? + + + HornetQ is an open source project to build a multi-protocol, embeddable, very high + performance, clustered, asynchronous messaging system. + + + HornetQ is an example of Message Oriented Middleware (MoM). For a description of + MoMs and other messaging concepts please see the . + + + For answers to more questions about what HornetQ is and what it isn't please visit + the FAQs wiki + page. + + + Why use HornetQ? Here are just a few of the reasons: + + + 100% open source software. HornetQ is licensed using the Apache Software License v + 2.0 to minimise barriers to adoption. + + + HornetQ is designed with usability in mind. + + + Written in Java. Runs on any platform with a Java 6+ runtime, that's everything + from Windows desktops to IBM mainframes. + + + Amazing performance. Our ground-breaking high performance journal provides + persistent messaging performance at rates normally seen for non-persistent + messaging, our non-persistent messaging performance rocks the boat too. + + + Full feature set. All the features you'd expect in any serious messaging system, + and others you won't find anywhere else. + + + Elegant, clean-cut design with minimal third party dependencies. Run HornetQ + stand-alone, run it in integrated in your favourite JEE application server, or run + it embedded inside your own product. It's up to you. + + + Seamless high availability. We provide a HA solution with automatic client + failover so you can guarantee zero message loss or duplication in event of server + failure. + + + Hugely flexible clustering. Create clusters of servers that know how to load + balance messages. Link geographically distributed clusters over unreliable + connections to form a global network. Configure routing of messages in a highly + flexible way. + + + For a full list of features, please see the features wiki + page . + + + diff --git a/docs/user-manual/en/project-info.xml b/docs/user-manual/en/project-info.xml new file mode 100644 index 0000000000..5bd6ca9b95 --- /dev/null +++ b/docs/user-manual/en/project-info.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Project Information + The official HornetQ project page is http://hornetq.org/. +
+ Software Download + The software can be download from the Download page:http://hornetq.org/downloads.html +
+
+ Project Information + + + + Please take a look at our project wiki + + + If you have any user questions please use our user + forum + + + If you have development related questions, please use our developer forum + + + Pop in and chat to us in our IRC channel + + + Our project blog + + + Follow us on twitter + + + HornetQ Git repository is https://github.com/hornetq/hornetq + + + All release tags are available from https://github.com/hornetq/hornetq/tags + + + + Red Hat kindly employs developers to work full time on HornetQ, they are: + + Clebert Suconic (project lead) + + + Andy Taylor + + + Howard Gao + + + Justin Bertram + + + And many thanks to all our contributors, both old and new who helped create HornetQ, + for a full list of the people who made it happen, take a look at our team page. +
+
diff --git a/docs/user-manual/en/queue-attributes.xml b/docs/user-manual/en/queue-attributes.xml new file mode 100644 index 0000000000..8ec06b511a --- /dev/null +++ b/docs/user-manual/en/queue-attributes.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Queue Attributes + Queue attributes can be set in one of two ways. Either by configuring them using the + configuration file or by using the core API. This chapter will explain how to configure each + attribute and what effect the attribute has. +
+ Predefined Queues + Queues can be predefined via configuration at a core level or at a JMS level. Firstly + let's look at a JMS level. + The following shows a queue predefined in the hornetq-jms.xml + configuration file. + +<queue name="selectorQueue"> + <entry name="/queue/selectorQueue"/> + <selector string="color='red'"/> + <durable>true</durable> +</queue> + This name attribute of queue defines the name of the queue. When we do this at a jms + level we follow a naming convention so the actual name of the core queue will be + jms.queue.selectorQueue. + The entry element configures the name that will be used to bind the queue to JNDI. + This is a mandatory element and the queue can contain multiple of these to bind the same + queue to different names. + The selector element defines what JMS message selector the predefined queue will have. + Only messages that match the selector will be added to the queue. This is an optional + element with a default of null when omitted. + The durable element specifies whether the queue will be persisted. This again is + optional and defaults to true if omitted. + Secondly a queue can be predefined at a core level in the hornetq-configuration.xml file. The following is an example. + +<queues> + <queue name="jms.queue.selectorQueue"> + <address>jms.queue.selectorQueue</address> + <filter string="color='red'"/> + <durable>true</durable> + </queue> +</queues> + This is very similar to the JMS configuration, with 3 real differences which + are. + + + The name attribute of queue is the actual name used for the queue with no + naming convention as in JMS. + + + The address element defines what address is used for routing messages. + + + There is no entry element. + + + The filter uses the Core filter syntax (described in + ), not the JMS + selector syntax. + + +
+
+ Using the API + Queues can also be created using the core API or the management API. + For the core API, queues can be created via the org.hornetq.api.core.client.ClientSession interface. There are multiple + createQueue methods that support setting all of the previously + mentioned attributes. There is one extra attribute that can be set via this API which is + temporary. setting this to true means that the queue will be + deleted once the session is disconnected. + Take a look at for a description of the management API + for creating queues. +
+
+ Configuring Queues Via Address Settings + There are some attributes that are defined against an address wildcard rather than a + specific queue. Here an example of an address-setting entry that + would be found in the hornetq-configuration.xml file. + +<address-settings> + <address-setting match="jms.queue.exampleQueue"> + <dead-letter-address>jms.queue.deadLetterQueue</dead-letter-address> + <max-delivery-attempts>3</max-delivery-attempts> + <redelivery-delay>5000</redelivery-delay> + <expiry-address>jms.queue.expiryQueue</expiry-address> + <last-value-queue>true</last-value-queue> + <max-size-bytes>100000</max-size-bytes> + <page-size-bytes>20000</page-size-bytes> + <redistribution-delay>0</redistribution-delay> + <send-to-dla-on-no-route>true</send-to-dla-on-no-route> + <address-full-policy>PAGE</address-full-policy> + </address-setting> +</address-settings> + The idea with address settings, is you can provide a block of settings which will be + applied against any addresses that match the string in the match attribute. In the + above example the settings would only be applied to any addresses which exactly match + the address jms.queue.exampleQueue, but you can also use wildcards to apply sets of + configuration against many addresses. The wildcard syntax used is described here. + For example, if you used the match string jms.queue.# the settings would be applied + to all addresses which start with jms.queue. which would be all JMS queues. + The meaning of the specific settings are explained fully throughout the user manual, however here is a brief + description with a link to the appropriate chapter if available. + max-delivery-attempts defines how many time a cancelled message can + be redelivered before sending to the dead-letter-address. A full + explanation can be found here. + redelivery-delay defines how long to wait before attempting + redelivery of a cancelled message. see here. + expiry-address defines where to send a message that has expired. + see here. + expiry-delay defines the expiration time that will be used for messages which are using + the default expiration time (i.e. 0). For example, if expiry-delay is set to "10" and a + message which is using the default expiration time (i.e. 0) arrives then its expiration time of "0" will be + changed to "10." However, if a message which is using an expiration time of "20" arrives then its expiration + time will remain unchanged. Setting expiry-delay to "-1" will disable this feature. The + default is "-1". + last-value-queue defines whether a queue only uses last values or + not. see here. + max-size-bytes and page-size-bytes are used to + set paging on an address. This is explained here. + redistribution-delay defines how long to wait when the last + consumer is closed on a queue before redistributing any messages. see here. + send-to-dla-on-no-route. If a message is sent to an address, but the server does not route it to any queues, + for example, there might be no queues bound to that address, or none of the queues have filters that match, then normally that message + would be discarded. However if this parameter is set to true for that address, if the message is not routed to any queues it will instead + be sent to the dead letter address (DLA) for that address, if it exists. + address-full-policy. This attribute can have one of the following values: PAGE, DROP, FAIL or BLOCK and determines what happens when + an address where max-size-bytes is specified becomes full. The default value is PAGE. If the value is PAGE then further messages will be paged to disk. + If the value is DROP then further messages will be silently dropped. + If the value is FAIL then further messages will be dropped and an exception will be thrown on the client-side. + If the value is BLOCK then client message producers will block when they try and send further messages. + + See the following chapters for more info , . + + + +
+
diff --git a/docs/user-manual/en/rest.xml b/docs/user-manual/en/rest.xml new file mode 100644 index 0000000000..ae5c416eff --- /dev/null +++ b/docs/user-manual/en/rest.xml @@ -0,0 +1,2151 @@ + + + + + + + + + + + + + + + + + + + + REST Interface + + The HornetQ REST interface allows you to leverage the reliability + and scalability features of HornetQ over a simple REST/HTTP interface. + Messages are produced and consumed by sending and receiving simple HTTP + messages that contain the content you want to push around. For instance, + here's a simple example of posting an order to an order processing queue + express as an HTTP message: + + + +POST /queue/orders/create HTTP/1.1 +Host: example.com +Content-Type: application/xml + +<order> + <name>Bill</name> + <item>iPhone 4</item> + <cost>$199.99</cost> +</order> + + As you can see, we're just posting some arbitrary XML + document to a URL. When the XML is received on the server is it processed + within HornetQ as a JMS message and distributed through core HornetQ. + Simple and easy. Consuming messages from a queue or topic looks very + similar. We'll discuss the entire interface in detail later in this + docbook. + + +
+ Goals of REST Interface + + Why would you want to use HornetQ's REST interface? What are the + goals of the REST interface? + + + + + Easily usable by machine-based (code) clients. + + + + Zero client footprint. We want HornetQ to be usable by any + client/programming language that has an adequate HTTP client + library. You shouldn't have to download, install, and configure a + special library to interact with HornetQ. + + + + + Lightweight interoperability. The HTTP protocol is strong + enough to be our message exchange protocol. Since interactions are + RESTful the HTTP uniform interface provides all the interoperability + you need to communicate between different languages, platforms, and + even messaging implementations that choose to implement the same + RESTful interface as HornetQ (i.e. the + REST-* effort.) + + + + + No envelope (e.g. SOAP) or feed (e.g. Atom) format + requirements. You shouldn't have to learn, use, or parse a specific + XML document format in order to send and receive messages through + HornetQ's REST interface. + + + + + Leverage the reliability, scalability, and clustering features + of HornetQ on the back end without sacrificing the simplicity of a + REST interface. + + + +
+ + +
+ Installation and Configuration + + HornetQ's REST interface is installed as a Web archive (WAR). It + depends on the + RESTEasy + project and can currently only run within a servlet container. Installing + the HornetQ REST interface is a little bit different depending whether + HornetQ is already installed and configured for your environment (e.g. + you're deploying within JBoss AS 7) or you want the HornetQ REST + WAR to startup and manage the HornetQ server (e.g. you're deploying + within something like Apache Tomcat). + + +
+ Installing Within Pre-configured Environment + + This section should be used when you want to use the HornetQ REST + interface in an environment that already has HornetQ installed and + running, e.g. JBoss AS 7. You must create a Web archive + (.WAR) file with the following web.xml settings: + + + +<web-app> + <listener> + <listener-class> + org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap + </listener-class> + </listener> + + <listener> + <listener-class> + org.hornetq.rest.integration.RestMessagingBootstrapListener + </listener-class> + </listener> + + <filter> + <filter-name>Rest-Messaging</filter-name> + <filter-class> + org.jboss.resteasy.plugins.server.servlet.FilterDispatcher + </filter-class> + </filter> + + <filter-mapping> + <filter-name>Rest-Messaging</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> +</web-app> + + Within your WEB-INF/lib directory you must have the + hornetq-rest.jar file. If RESTEasy is not installed within your + environment, you must add the RESTEasy jar files within the lib + directory as well. Here's a sample Maven pom.xml that can build your WAR + for this case. + + + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.somebody</groupId> + <artifactId>myapp</artifactId> + <packaging>war</packaging> + <name>My App</name> + <version>0.1-SNAPSHOT</version> + <repositories> + <repository> + <id>jboss</id> + <url>http://repository.jboss.org/nexus/content/groups/public/</url> + </repository> + </repositories> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.6</source> + <target>1.6</target> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.hornetq.rest</groupId> + <artifactId>hornetq-rest</artifactId> + <version>2.3.0-SNAPSHOT</version> + </dependency> + </dependencies> +</project> + + + JBoss AS 7 loads classes differently than previous versions. + To work properly in AS 7 the WAR will need this in its MANIFEST.MF: + + Dependencies: org.hornetq, org.jboss.netty + You can add this to the<plugins> + section of the pom.xml to create this entry automatically: + + +<plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <configuration> + <archive> + <manifestEntries> + <Dependencies>org.hornetq, org.jboss.netty</Dependencies> + </manifestEntries> + </archive> + </configuration> +</plugin> + + + + It is worth noting that when deploying a WAR in a Java EE application server + like AS7 the URL for the resulting application will include the name of the + WAR by default. For example, if you've constructed a WAR as described above + named "hornetq-rest.war" then clients will access it at, e.g. + http://localhost:8080/hornetq-rest/[queues|topics]. We'll see more about + this later. + + + + It is possible to put the WAR file at the "root context" of AS7, but + that is beyond the scope of this documentation. + + +
+ +
+ Bootstrapping HornetQ Along with REST + + You can bootstrap HornetQ within your WAR as well. To do this, you + must have the HornetQ core and JMS jars along with Netty, Resteasy, and + the HornetQ REST jar within your WEB-INF/lib. You must also have a + hornetq-configuration.xml, hornetq-jms.xml, and hornetq-users.xml config + files within WEB-INF/classes. The examples that come with the HornetQ + REST distribution show how to do this. You must also add an additional + listener to your web.xml file. Here's an example: + + + +<web-app> + <listener> + <listener-class> + org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap + </listener-class> + </listener> + + <listener> + <listener-class> + org.hornetq.rest.integration.HornetqBootstrapListener + </listener-class> + </listener> + + <listener> + <listener-class> + org.hornetq.rest.integration.RestMessagingBootstrapListener + </listener-class> + </listener> + + <filter> + <filter-name>Rest-Messaging</filter-name> + <filter-class> + org.jboss.resteasy.plugins.server.servlet.FilterDispatcher + </filter-class> + </filter> + + <filter-mapping> + <filter-name>Rest-Messaging</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> +</web-app> + + Here's a Maven pom.xml file for creating a WAR for this + environment. Make sure your hornetq configuration files are within the + src/main/resources directory so that they are stuffed within the WAR's + WEB-INF/classes directory! + + + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.somebody</groupId> + <artifactId>myapp</artifactId> + <packaging>war</packaging> + <name>My App</name> + <version>0.1-SNAPSHOT</version> + <repositories> + <repository> + <id>jboss</id> + <url>http://repository.jboss.org/nexus/content/groups/public/</url> + </repository> + </repositories> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.6</source> + <target>1.6</target> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-core</artifactId> + <version>2.3.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty</artifactId> + <version>3.4.5.Final</version> + </dependency> + <dependency> + <groupId>org.hornetq</groupId> + <artifactId>hornetq-jms</artifactId> + <version>2.3.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.jboss.spec.javax.jms</groupId> + <artifactId>jboss-jms-api_2.0_spec</artifactId> + <version>1.0.0.Final</version> + </dependency> + <dependency> + <groupId>org.hornetq.rest</groupId> + <artifactId>hornetq-rest</artifactId> + <version>2.3.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.jboss.resteasy</groupId> + <artifactId>resteasy-jaxrs</artifactId> + <version>2.3.4.Final</version> + </dependency> + <dependency> + <groupId>org.jboss.resteasy</groupId> + <artifactId>resteasy-jaxb-provider</artifactId> + <version>2.3.4.Final</version> + </dependency> + </dependencies> +</project> +
+ +
+ REST Configuration + + The HornetQ REST implementation does have some configuration + options. These are configured via XML configuration file that must be in + your WEB-INF/classes directory. You must set the web.xml context-param + rest.messaging.config.file to specify the name of the + configuration file. Below is the format of the XML configuration file + and the default values for each. + + + +<rest-messaging> + <server-in-vm-id>0</server-in-vm-id> + <use-link-headers>false</use-link-headers> + <default-durable-send>false</default-durable-send> + <dups-ok>true</dups-ok> + <topic-push-store-dir>topic-push-store</topic-push-store-dir> + <queue-push-store-dir>queue-push-store</queue-push-store-dir> + <producer-time-to-live>0</producer-time-to-live> + <producer-session-pool-size>10</producer-session-pool-size> + <session-timeout-task-interval>1</session-timeout-task-interval> + <consumer-session-timeout-seconds>300</consumer-session-timeout-seconds> + <consumer-window-size>-1</consumer-window-size> +</rest-messaging> + + Let's give an explanation of each config option. + + + + server-in-vm-id. The HornetQ REST + impl uses the IN-VM transport to communicate with HornetQ. + It uses the default server id, which is "0". + + + + use-link-headers. By default, all + links (URLs) are published using custom headers. You can + instead have the HornetQ REST implementation publish links + using the + Link Header specification + instead if you desire. + + + + default-durable-send. Whether a posted + message should be persisted by default if the user does not + specify a durable query parameter. + + + + dups-ok. If this is true, no duplicate + detection protocol will be enforced for message posting. + + + + topic-push-store-dir. This must be + a relative or absolute file system path. This is a directory + where push registrations for topics are stored. See + Pushing Messages. + + + + queue-push-store-dir. This must be + a relative or absolute file system path. This is a + directory where push registrations for queues are stored. + See Pushing Messages. + + + + producer-session-pool-size. The REST + implementation pools HornetQ sessions for sending messages. + This is the size of the pool. That number of sessions will + be created at startup time. + + + + producer-time-to-live. Default time + to live for posted messages. Default is no ttl. + + + + session-timeout-task-interval. Pull + consumers and pull subscriptions can time out. This is + the interval the thread that checks for timed-out sessions + will run at. A value of 1 means it will run every 1 second. + + + + consumer-session-timeout-seconds. + Timeout in seconds for pull consumers/subscriptions that + remain idle for that amount of time. + + + + consumer-window-size. For consumers, + this config option is the same as the HornetQ one of the + same name. It will be used by sessions created by the + HornetQ REST implementation. + + + +
+
+ + +
+ HornetQ REST Interface Basics + + The HornetQ REST interface publishes a variety of REST resources to + perform various tasks on a queue or topic. Only the top-level queue and + topic URI schemes are published to the outside world. You must discover + all over resources to interact with by looking for and traversing links. + You'll find published links within custom response headers and embedded in + published XML representations. Let's look at how this works. + + +
+ Queue and Topic Resources + + To interact with a queue or topic you do a HEAD or GET request on + the following relative URI pattern: + + + +/queues/{name} +/topics/{name} + + The base of the URI is the base URL of the WAR you deployed the + HornetQ REST server within as defined in the + Installation and Configuration + section of this document. Replace the {name} + string within the above URI pattern with the name of the queue or + topic you are interested in interacting with. For example if you + have configured a JMS topic named "foo" within your + hornetq-jms.xml file, the URI name should be + "jms.topic.foo". If you have configured a JMS queue name "bar" within + your hornetq-jms.xml file, the URI name should be + "jms.queue.bar". Internally, HornetQ prepends the "jms.topic" or + "jms.queue" strings to the name of the deployed destination. Next, + perform your HEAD or GET request on this URI. Here's what a + request/response would look like. + + + +HEAD /queues/jms.queue.bar HTTP/1.1 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +msg-create: http://example.com/queues/jms.queue.bar/create +msg-create-with-id: http://example.com/queues/jms.queue.bar/create/{id} +msg-pull-consumers: http://example.com/queues/jms.queue.bar/pull-consumers +msg-push-consumers: http://example.com/queues/jms.queue.bar/push-consumers + + + + You can use the "curl" utility to test this easily. Simply execute + a command like this: + + + +curl --head http://example.com/queues/jms.queue.bar + + + The HEAD or GET response contains a number of custom response + headers that are URLs to additional REST resources that allow you to + interact with the queue or topic in different ways. It is important not + to rely on the scheme of the URLs returned within these headers as they + are an implementation detail. Treat them as opaque and query for them + each and every time you initially interact (at boot time) with the + server. If you treat all URLs as opaque then you will be isolated from + implementation changes as the HornetQ REST interface evolves over + time. + +
+ +
+ Queue Resource Response Headers + + Below is a list of response headers you should expect when + interacting with a Queue resource. + + + + + msg-create. This is a URL you POST messages + to. The semantics of this link are described in + Posting Messages. + + + + msg-create-with-id. This is a URL + template you can use to POST messages. + The semantics of this link are described in + Posting Messages. + + + + msg-pull-consumers. This is a URL for + creating consumers that will pull from a queue. The semantics + of this link are described in + Consuming Messages via Pull. + + + + msg-push-consumers. This is a URL for + registering other URLs you want the HornetQ REST server to + push messages to. The semantics of this link are described + in Pushing Messages. + + + +
+ +
+ Topic Resource Response Headers + + Below is a list of response headers you should expect when + interacting with a Topic resource. + + + + + msg-create. This is a URL you POST + messages to. The semantics of this link are described in + Posting Messages. + + + + msg-create-with-id. This is a URL + template you can use to POST messages. + The semantics of this link are described in + Posting Messages. + + + + msg-pull-subscriptions. This is a + URL for creating subscribers that will pull from a topic. + The semantics of this link are described in + Consuming Messages via Pull. + + + + msg-push-subscriptions. This is a + URL for registering other URLs you want the HornetQ REST + server to push messages to. The semantics of this link + are described in Pushing + Messages. + + + +
+
+ + +
+ Posting Messages + + This chapter discusses the protocol for posting messages to a queue + or a topic. In HornetQ REST Interface Basics, + you saw that a queue or topic resource publishes variable custom headers + that are links to other RESTful resources. The msg-create + header is a URL you can post a message to. Messages are published to a queue + or topic by sending a simple HTTP message to the URL published by the + msg-create header. The HTTP message contains whatever + content you want to publish to the HornetQ destination. Here's an example + scenario: + + + + You can also post messages to the URL template found in + msg-create-with-id, but this is a more advanced + use-case involving duplicate detection that we will discuss later in + this section. + + + + + + Obtain the starting msg-create header from + the queue or topic resource. + + + + +HEAD /queues/jms.queue.bar HTTP/1.1 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +msg-create: http://example.com/queues/jms.queue.bar/create +msg-create-with-id: http://example.com/queues/jms.queue.bar/create/{id} + + + + + Do a POST to the URL contained in the msg-create + header. + + + +POST /queues/jms.queue.bar/create +Host: example.com +Content-Type: application/xml + +<order> + <name>Bill</name> + <item>iPhone4</name> + <cost>$199.99</cost> +</order> + +--- Response --- +HTTP/1.1 201 Created +msg-create-next: http://example.com/queues/jms.queue.bar/create + + + You can use the "curl" utility to test this easily. Simply execute + a command like this: + + +curl --verbose --data "123" http://example.com/queues/jms.queue.bar/create + + + A successful response will return a 201 response code. Also + notice that a msg-create-next response header + is sent as well. You must use this URL to POST your next message. + + + + + POST your next message to the queue using the URL returned in + the msg-create-next header. + + + +POST /queues/jms.queue.bar/create +Host: example.com +Content-Type: application/xml + +<order> + <name>Monica</name> + <item>iPad</item> + <cost>$499.99</cost> +</order> + +--- Response -- +HTTP/1.1 201 Created +msg-create-next: http://example.com/queues/jms.queue.bar/create + Continue using the new msg-create-next + header returned with each response. + + + + + + It is VERY IMPORTANT that you never re-use returned + msg-create-next headers to post new messages. If the + dups-ok configuration property is set to + false on the server then this URL will be uniquely + generated for each message and used for duplicate detection. If you lose + the URL within the msg-create-next header, then just + go back to the queue or topic resource to get the + msg-create URL again. + + + +
+ Duplicate Detection + + Sometimes you might have network problems when posting new + messages to a queue or topic. You may do a POST and never receive a + response. Unfortunately, you don't know whether or not the server + received the message and so a re-post of the message might cause + duplicates to be posted to the queue or topic. By default, the HornetQ + REST interface is configured to accept and post duplicate messages. You + can change this by turning on duplicate message detection by setting the + dups-ok config option to false + as described in HornetQ REST Interface Basics. + When you do this, the initial POST to the msg-create + URL will redirect you, using the standard HTTP 307 redirection mechanism + to a unique URL to POST to. All other interactions remain the same as + discussed earlier. Here's an example: + + + + + Obtain the starting msg-create header from + the queue or topic resource. + + + + +HEAD /queues/jms.queue.bar HTTP/1.1 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +msg-create: http://example.com/queues/jms.queue.bar/create +msg-create-with-id: http://example.com/queues/jms.queue.bar/create/{id} + + + + + Do a POST to the URL contained in the msg-create + header. + + + +POST /queues/jms.queue.bar/create +Host: example.com +Content-Type: application/xml + +<order> + <name>Bill</name> + <item>iPhone4</name> + <cost>$199.99</cost> +</order> + +--- Response --- +HTTP/1.1 307 Redirect +Location: http://example.com/queues/jms.queue.bar/create/13582001787372 + + A successful response will return a 307 response code. This + is standard HTTP protocol. It is telling you that you must re-POST + to the URL contained within the Location + header. + + + + + re-POST your message to the URL provided within the + Location header. + + + +POST /queues/jms.queue.bar/create/13582001787372 +Host: example.com +Content-Type: application/xml + +<order> + <name>Bill</name> + <item>iPhone4</name> + <cost>$199.99</cost> +</order> + +--- Response -- +HTTP/1.1 201 Created +msg-create-next: http://example.com/queues/jms.queue.bar/create/13582001787373 + You should receive a 201 Created response. If there is a + network failure, just re-POST to the Location header. For new + messages, use the returned msg-create-next + header returned with each response. + + + + + POST any new message to the returned + msg-create-next header. + + + +POST /queues/jms.queue.bar/create/13582001787373 +Host: example.com +Content-Type: application/xml + +<order> + <name>Monica</name> + <item>iPad</name> + <cost>$499.99</cost> +</order> + +--- Response -- +HTTP/1.1 201 Created +msg-create-next: http://example.com/queues/jms.queue.bar/create/13582001787374 + If there ever is a network problem, just repost to the URL + provided in the msg-create-next header. + + + + + How can this work? As you can see, with each successful response, + the HornetQ REST server returns a uniquely generated URL within the + msg-create-next header. This URL is dedicated to the next new message + you want to post. Behind the scenes, the code extracts an identify from + the URL and uses HornetQ's duplicate detection mechanism by setting the + DUPLICATE_DETECTION_ID property of the JMS message + that is actually posted to the system. + + + If you happen to use the same ID more than once you'll see a message + like this on the server: + + +WARN [org.hornetq.core.server] (Thread-3 (HornetQ-remoting-threads-HornetQServerImpl::serverUUID=8d6be6f8-5e8b-11e2-80db-51bbde66f473-26319292-267207)) HQ112098: Duplicate message detected - message will not be routed. Message information: +ServerMessage[messageID=20,priority=4, bodySize=1500,expiration=0, durable=true, address=jms.queue.bar,properties=TypedProperties[{http_content$type=application/x-www-form-urlencoded, http_content$length=3, postedAsHttpMessage=true, _HQ_DUPL_ID=42}]]@12835058 + + An alternative to this approach is to use the msg-create-with-id + header. This is not an invokable URL, but a URL template. The idea is that + the client provides the DUPLICATE_DETECTION_ID and creates + its own create-next URL. The msg-create-with-id + header looks like this (you've see it in previous examples, but we haven't used it): + + + +msg-create-with-id: http://example.com/queues/jms.queue.bar/create/{id} + + You see that it is a regular URL appended with a {id}. This + {id} is a pattern matching substring. A client would generate its + DUPLICATE_DETECTION_ID and replace {id} + with that generated id, then POST to the new URL. The URL the client creates + works exactly like a create-next URL described earlier. The + response of this POST would also return a new msg-create-next + header. The client can continue to generate its own DUPLICATE_DETECTION_ID, or + use the new URL returned via the msg-create-next header. + + + The advantage of this approach is that the client does not have to + repost the message. It also only has to come up with a unique + DUPLICATE_DETECTION_ID once. + +
+ +
+ Persistent Messages + + By default, posted messages are not durable and will not be + persisted in HornetQ's journal. You can create durable messages by + modifying the default configuration as expressed in Chapter 2 so that + all messages are persisted when sent. Alternatively, you can set a URL + query parameter called durable to true when you post + your messages to the URLs returned in the msg-create, + msg-create-with-id, or msg-create-next + headers. here's an example of that. + + + +POST /queues/jms.queue.bar/create?durable=true +Host: example.com +Content-Type: application/xml + +<order> + <name>Bill</name> + <item>iPhone4</item> + <cost>$199.99</cost> +</order> +
+ +
+ TTL, Expiration and Priority + + You can set the time to live, expiration, and/or the priority of + the message in the queue or topic by setting an additional query + parameter. The expiration query parameter is an long + specify the time in milliseconds since epoch (a long date). The + ttl query parameter is a time in milliseconds you + want the message active. The priority is another + query parameter with an integer value between 0 and 9 expressing the + priority of the message. i.e.: + + + +POST /queues/jms.queue.bar/create?expiration=30000&priority=3 +Host: example.com +Content-Type: application/xml + +<order> + <name>Bill</name> + <item>iPhone4</item> + <cost>$199.99</cost> +</order> +
+
+ +
+ Consuming Messages via Pull + + There are two different ways to consume messages from a topic or + queue. You can wait and have the messaging server push them to you, or you + can continuously poll the server yourself to see if messages are + available. This chapter discusses the latter. Consuming messages via a + pull works almost identically for queues and topics with some minor, but + important caveats. To start consuming you must create a consumer resource + on the server that is dedicated to your client. Now, this pretty much + breaks the stateless principle of REST, but after much prototyping, this + is the best way to work most effectively with HornetQ through a REST + interface. + + + You create consumer resources by doing a simple POST to the URL + published by the msg-pull-consumers + response header if you are interacting with a queue, the + msg-pull-subscribers response header if you're + interacting with a topic. These headers are provided by the main queue or + topic resource discussed in HornetQ REST Interface + Basics. Doing an empty POST to one of these + URLs will create a consumer resource that follows an auto-acknowledge + protocol and, if you are interacting with a topic, creates a temporarily + subscription to the topic. If you want to use the acknowledgement protocol + and/or create a durable subscription (topics only), then you must use the + form parameters (application/x-www-form-urlencoded) + described below. + + + + + autoAck. A value of true + or false can be given. This defaults to + true if you do not pass this parameter. + + + + durable. A value of true + or false can be given. This defaults to + false if you do not pass this parameter. + Only available on topics. This specifies whether you want a + durable subscription or not. A durable subscription persists + through server restart. + + + + name. This is the name of the durable + subscription. If you do not provide this parameter, the name + will be automatically generated by the server. Only usable + on topics. + + + + selector. This is an optional JMS selector + string. The HornetQ REST interface adds HTTP headers to the + JMS message for REST produced messages. HTTP headers are + prefixed with "http_" and every '-' character is converted + to a '$'. + + + + idle-timeout. For a topic subscription, + idle time in milliseconds in which the consumer connections + will be closed if idle. + + + + delete-when-idle. Boolean value, If + true, a topic subscription will be deleted (even if it is + durable) when an the idle timeout is reached. + + + + + + If you have multiple pull-consumers active at the same time + on the same destination be aware that unless the + consumer-window-size is 0 then one consumer + might buffer messages while the other consumer gets none. + + + +
+ Auto-Acknowledge + + This section focuses on the auto-acknowledge protocol for + consuming messages via a pull. Here's a list of the response + headers and URLs you'll be interested in. + + + + + msg-pull-consumers. The URL of + a factory resource for creating queue consumer + resources. You will pull from these created resources. + + + + msg-pull-subscriptions. The URL + of a factory resource for creating topic subscription + resources. You will pull from the created resources. + + + + msg-consume-next. The URL you + will pull the next message from. This is returned + with every response. + + + + msg-consumer. This is a URL + pointing back to the consumer or subscription + resource created for the client. + + + + +
+ Creating an Auto-Ack Consumer or Subscription + + Here is an example of creating an auto-acknowledged + queue pull consumer. + + + + + Find the pull-consumers URL by doing a HEAD or + GET request to the base queue resource. + + + +HEAD /queues/jms.queue.bar HTTP/1.1 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +msg-create: http://example.com/queues/jms.queue.bar/create +msg-pull-consumers: http://example.com/queues/jms.queue.bar/pull-consumers +msg-push-consumers: http://example.com/queues/jms.queue.bar/push-consumers + + + + Next do an empty POST to the URL returned in the + msg-pull-consumers + header. + + + +POST /queues/jms.queue.bar/pull-consumers HTTP/1.1 +Host: example.com + +--- response --- +HTTP/1.1 201 Created +Location: http://example.com/queues/jms.queue.bar/pull-consumers/auto-ack/333 +msg-consume-next: http://example.com/queues/jms.queue.bar/pull-consumers/auto-ack/333/consume-next-1 + + The + Location + header points to the JMS + consumer resource that was created on the server. It is good to + remember this URL, although, as you'll see later, it is + transmitted with each response just to remind you. + + + + + Creating an auto-acknowledged consumer for a topic is pretty + much the same. Here's an example of creating a durable + auto-acknowledged topic pull subscription. + + + + + Find the + pull-subscriptions + URL by doing + a HEAD or GET request to the base topic resource + + + +HEAD /topics/jms.topic.bar HTTP/1.1 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +msg-create: http://example.com/topics/jms.topic.foo/create +msg-pull-subscriptions: http://example.com/topics/jms.topic.foo/pull-subscriptions +msg-push-subscriptions: http://example.com/topics/jms.topic.foo/push-subscriptions + + + + Next do a POST to the URL returned in the + msg-pull-subscriptions + header passing in a true + value for the durable + form parameter. + + + +POST /topics/jms.topic.foo/pull-subscriptions HTTP/1.1 +Host: example.com +Content-Type: application/x-www-form-urlencoded + +durable=true + +--- Response --- +HTTP/1.1 201 Created +Location: http://example.com/topics/jms.topic.foo/pull-subscriptions/auto-ack/222 +msg-consume-next: +http://example.com/topics/jms.topic.foo/pull-subscriptions/auto-ack/222/consume-next-1 + + The + Location + header points to the JMS + subscription resource that was created on the server. It is good + to remember this URL, although, as you'll see later, it is + transmitted with each response just to remind you. + + + +
+ +
+ Consuming Messages + + After you have created a consumer resource, you are ready to + start pulling messages from the server. Notice that when you created + the consumer for either the queue or topic, the response contained a + msg-consume-next response header. POST to the URL + contained within this header to consume the next message in the queue + or topic subscription. A successful POST causes the server to extract + a message from the queue or topic subscription, acknowledge it, and + return it to the consuming client. If there are no messages in the + queue or topic subscription, a 503 (Service Unavailable) HTTP code is + returned. + + + + For both successful and unsuccessful posts to the + msg-consume-next URL, the response will contain a new + msg-consume-next header. You must ALWAYS use this new URL returned + within the new msg-consume-next header to consume new + messages. + + + + Here's an example of pulling multiple messages from the consumer + resource. + + + + + Do a POST on the msg-consume-next URL that was returned with + the consumer or subscription resource discussed earlier. + + + +POST /queues/jms.queue.bar/pull-consumers/consume-next-1 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +Content-Type: application/xml +msg-consume-next: http://example.com/queues/jms.queue.bar/pull-consumers/333/consume-next-2 +msg-consumer: http://example.com/queues/jms.queue.bar/pull-consumers/333 + +<order>...</order> + + The POST returns the message consumed from the queue. It + also returns a new msg-consume-next link. Use this new link to get + the next message. Notice also a msg-consumer response header is + returned. This is a URL that points back to the consumer or + subscription resource. You will need that to clean up your + connection after you are finished using the queue or topic. + + + + + The POST returns the message consumed from the queue. It + also returns a new msg-consume-next link. Use this new link to get + the next message. + + + +POST /queues/jms.queue.bar/pull-consumers/consume-next-2 +Host: example.com + +--- Response --- +Http/1.1 503 Service Unavailable +Retry-After: 5 +msg-consume-next: http://example.com/queues/jms.queue.bar/pull-consumers/333/consume-next-2 + + In this case, there are no messages in the queue, so we get + a 503 response back. As per the HTTP 1.1 spec, a 503 response may + return a Retry-After head specifying the time in seconds that you + should retry a post. Also notice, that another new + msg-consume-next URL is present. Although it probably is the same + URL you used last post, get in the habit of using URLs returned in + response headers as future versions of HornetQ REST might be + redirecting you or adding additional data to the URL after + timeouts like this. + + + + + POST to the URL within the last + msg-consume-next + to get the next + message. + + + +POST /queues/jms.queue.bar/pull-consumers/consume-next-2 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +Content-Type: application/xml +msg-consume-next: http://example.com/queues/jms.queue.bar/pull-consumers/333/consume-next-3 + +<order>...</order> + + +
+ +
+ Recovering From Network Failures + + If you experience a network failure and do not know if your post + to a msg-consume-next URL was successful or not, just re-do your POST. + A POST to a msg-consume-next URL is idempotent, meaning that it will + return the same result if you execute on any one msg-consume-next URL + more than once. Behind the scenes, the consumer resource caches the + last consumed message so that if there is a message failure and you do + a re-post, the cached last message will be returned (along with a new + msg-consume-next URL). This is the reason why the protocol always + requires you to use the next new msg-consume-next URL returned with + each response. Information about what state the client is in is + embedded within the actual URL. + +
+ +
+ Recovering From Client or Server Crashes + + If the server crashes and you do a POST to the msg-consume-next + URL, the server will return a 412 (Preconditions Failed) response + code. This is telling you that the URL you are using is out of sync + with the server. The response will contain a new msg-consume-next + header to invoke on. + + + If the client crashes there are multiple ways you can recover. + If you have remembered the last msg-consume-next link, you can just + re-POST to it. If you have remembered the consumer resource URL, you + can do a GET or HEAD request to obtain a new msg-consume-next URL. If + you have created a topic subscription using the name parameter + discussed earlier, you can re-create the consumer. Re-creation will + return a msg-consume-next URL you can use. If you cannot do any of + these things, you will have to create a new consumer. + + + The problem with the auto-acknowledge protocol is that if the + client or server crashes, it is possible for you to skip messages. The + scenario would happen if the server crashes after auto-acknowledging a + message and before the client receives the message. If you want more + reliable messaging, then you must use the acknowledgement + protocol. + +
+
+ +
+ Manual Acknowledgement + + The manual acknowledgement protocol is similar to the auto-ack + protocol except there is an additional round trip to the server to tell + it that you have received the message and that the server can internally + ack the message. Here is a list of the response headers you will be + interested in. + + + + + msg-pull-consumers. The URL of a factory resource for creating queue + consumer + resources. You will pull from these created resources + + + + msg-pull-subscriptions. The URL of a factory resource for creating topic + subscription resources. You will pull from the created + resources. + + + + msg-acknowledge-next. URL used to obtain the next message in the queue or + topic + subscription. It does not acknowledge the message though. + + + + msg-acknowledgement. URL used to acknowledge a message. + + + + msg-consumer. This is a URL pointing back to the consumer or subscription + resource created for the client. + + + + +
+ Creating manually-acknowledged consumers or + subscriptions + + + Here is an example of creating an auto-acknowledged queue pull + consumer. + + + + + Find the pull-consumers URL by doing a HEAD or GET request + to the base queue resource. + + + +HEAD /queues/jms.queue.bar HTTP/1.1 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +msg-create: http://example.com/queues/jms.queue.bar/create +msg-pull-consumers: http://example.com/queues/jms.queue.bar/pull-consumers +msg-push-consumers: http://example.com/queues/jms.queue.bar/push-consumers + + + + Next do a POST to the URL returned in the + msg-pull-consumers + header passing in a + false + value to the + autoAck + form parameter . + + + +POST /queues/jms.queue.bar/pull-consumers HTTP/1.1 +Host: example.com +Content-Type: application/x-www-form-urlencoded + +autoAck=false + +--- response --- +HTTP/1.1 201 Created +Location: http://example.com/queues/jms.queue.bar/pull-consumers/acknowledged/333 +msg-acknowledge-next: http://example.com/queues/jms.queue.bar/pull-consumers/acknowledged/333/acknowledge-next-1 + + The + Location + header points to the JMS + consumer resource that was created on the server. It is good to + remember this URL, although, as you'll see later, it is + transmitted with each response just to remind you. + + + + + Creating an manually-acknowledged consumer for a topic is pretty + much the same. Here's an example of creating a durable + manually-acknowledged topic pull subscription. + + + + + Find the + pull-subscriptions + URL by doing + a HEAD or GET request to the base topic resource + + + +HEAD /topics/jms.topic.bar HTTP/1.1 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +msg-create: http://example.com/topics/jms.topic.foo/create +msg-pull-subscriptions: http://example.com/topics/jms.topic.foo/pull-subscriptions +msg-push-subscriptions: http://example.com/topics/jms.topic.foo/push-subscriptions + + + + Next do a POST to the URL returned in the + msg-pull-subscriptions + header passing in a true + value for the durable + form parameter and a false + value to the autoAck + form parameter. + + + +POST /topics/jms.topic.foo/pull-subscriptions HTTP/1.1 +Host: example.com +Content-Type: application/x-www-form-urlencoded + +durable=true&autoAck=false + +--- Response --- +HTTP/1.1 201 Created +Location: http://example.com/topics/jms.topic.foo/pull-subscriptions/acknowledged/222 +msg-acknowledge-next: +http://example.com/topics/jms.topic.foo/pull-subscriptions/acknowledged/222/consume-next-1 + + The + Location header points to the JMS + subscription resource that was created on the server. It is good + to remember this URL, although, as you'll see later, it is + transmitted with each response just to remind you. + + + +
+ +
+ Consuming and Acknowledging a Message + + After you have created a consumer resource, you are ready to + start pulling messages from the server. Notice that when you created + the consumer for either the queue or topic, the response contained a + msg-acknowledge-next response header. POST to the + URL contained within this header to consume the next message in the + queue or topic subscription. If there are no messages in the queue or + topic subscription, a 503 (Service Unavailable) HTTP code is returned. + A successful POST causes the server to extract a message from the + queue or topic subscription and return it to the consuming client. It + does not acknowledge the message though. The response will contain the + acknowledgement + header which you will use to + acknowledge the message. + + + Here's an example of pulling multiple messages from the consumer + resource. + + + + + Do a POST on the msg-acknowledge-next URL that was returned + with the consumer or subscription resource discussed + earlier. + + + +POST /queues/jms.queue.bar/pull-consumers/consume-next-1 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +Content-Type: application/xml +msg-acknowledgement: +http://example.com/queues/jms.queue.bar/pull-consumers/333/acknowledgement/2 +msg-consumer: http://example.com/queues/jms.queue.bar/pull-consumers/333 + +<order>...</order> + + The POST returns the message consumed from the queue. It + also returns amsg-acknowledgement link. You + will use this new link to acknowledge the message. Notice also a + msg-consumer response header is returned. This + is a URL that points back to the consumer or subscription + resource. You will need that to clean up your connection after you + are finished using the queue or topic. + + + + + Acknowledge or unacknowledge the message by doing a POST to + the URL contained in the msg-acknowledgement + header. You must pass an acknowledge + form parameter set to true + or false depending on whether you want to + acknowledge or unacknowledge the message on the server. + + + +POST /queues/jms.queue.bar/pull-consumers/acknowledgement/2 +Host: example.com +Content-Type: application/x-www-form-urlencoded + +acknowledge=true + +--- Response --- +Http/1.1 200 Ok +msg-acknowledge-next: +http://example.com/queues/jms.queue.bar/pull-consumers/333/acknowledge-next-2 + + Whether you acknowledge or unacknowledge the message, the + response will contain a new msg-acknowledge-next header that you + must use to obtain the next message. + + + +
+ +
+ Recovering From Network Failures + + If you experience a network failure and do not know if your post + to a + msg-acknowledge-next + or + msg-acknowledgement URL was successful or not, just + re-do your POST. A POST to one of these URLs is idempotent, meaning + that it will return the same result if you re-post. Behind the scenes, + the consumer resource keeps track of its current state. If the last + action was a call tomsg-acknowledge-next, it will + have the last message cached, so that if a re-post is done, it will + return the message again. Same goes with re-posting to + msg-acknowledgement. The server remembers its last + state and will return the same results. If you look at the URLs you'll + see that they contain information about the expected current state of + the server. This is how the server knows what the client is + expecting. + +
+ +
+ Recovering From Client or Server Crashes + + If the server crashes and while you are doing a POST to the + msg-acknowledge-next URL, just re-post. Everything + should reconnect all right. On the other hand, if the server crashes + while you are doing a POST tomsg-acknowledgement, + the server will return a 412 (Preconditions Failed) response code. + This is telling you that the URL you are using is out of sync with the + server and the message you are acknowledging was probably re-enqueued. + The response will contain a new msg-acknowledge-next + header to invoke on. + + + As long as you have "bookmarked" the consumer resource URL + (returned from Location header on a create, or the + msg-consumer header), you can recover from client + crashes by doing a GET or HEAD request on the consumer resource to + obtain what state you are in. If the consumer resource is expecting + you to acknowledge a message, it will return a + msg-acknowledgement header in the response. If the + consumer resource is expecting you to pull for the next message, the + msg-acknowledge-next header will be in the + response. With manual acknowledgement you are pretty much guaranteed + to avoid skipped messages. For topic subscriptions that were created + with a name parameter, you do not have to "bookmark" the returned URL. + Instead, you can re-create the consumer resource with the same exact + name. The response will contain the same information as if you did a + GET or HEAD request on the consumer resource. + +
+
+ +
+ Blocking Pulls with Accept-Wait + + Unless your queue or topic has a high rate of message flowing + though it, if you use the pull protocol, you're going to be receiving a + lot of 503 responses as you continuously pull the server for new + messages. To alleviate this problem, the HornetQ REST interface provides + the Accept-Wait header. This is a generic HTTP + request header that is a hint to the server for how long the client is + willing to wait for a response from the server. The value of this header + is the time in seconds the client is willing to block for. You would + send this request header with your pull requests. Here's an + example: + + + +POST /queues/jms.queue.bar/pull-consumers/consume-next-2 +Host: example.com +Accept-Wait: 30 + +--- Response --- +HTTP/1.1 200 Ok +Content-Type: application/xml +msg-consume-next: http://example.com/queues/jms.queue.bar/pull-consumers/333/consume-next-3 + +<order>...</order> + + In this example, we're posting to a msg-consume-next URL and + telling the server that we would be willing to block for 30 + seconds. + +
+ +
+ Clean Up Your Consumers! + + When the client is done with its consumer or topic subscription it + should do an HTTP DELETE call on the consumer URL passed back from the + Location header or the msg-consumer response header. The server will + time out a consumer with the value of + consumer-session-timeout-seconds configured from + REST configuration, so you + don't have to clean up if you don't want to, but if you are a good kid, + you will clean up your messes. A consumer timeout for durable + subscriptions will not delete the underlying durable JMS subscription + though, only the server-side consumer resource (and underlying JMS + session). + +
+
+ + +
+ Pushing Messages + + You can configure the HornetQ REST server to push messages to a + registered URL either remotely through the REST interface, or by creating + a pre-configured XML file for the HornetQ REST server to load at boot + time. + + +
+ The Queue Push Subscription XML + + Creating a push consumer for a queue first involves creating a + very simple XML document. This document tells the server if the push + subscription should survive server reboots (is it durable). It must + provide a URL to ship the forwarded message to. Finally, you have to + provide authentication information if the final endpoint requires + authentication. Here's a simple example: + + + +<push-registration> + <durable>false</durable> + <selector><![CDATA[ + SomeAttribute > 1 + ]]> + </selector> + <link rel="push" href="http://somewhere.com" type="application/json" method="PUT"/> + <maxRetries>5</maxRetries> + <retryWaitMillis>1000</retryWaitMillis> + <disableOnFailure>true</disableOnFailure> +</push-registration> + + The durable element specifies whether the + registration should be saved to disk so that if there is a server + restart, the push subscription will still work. This element is not + required. If left out it defaults tofalse. If + durable is set to true, an XML file for the push subscription will be + created within the directory specified by the + queue-push-store-dir config variable defined in + Chapter 2 (topic-push-store-dir for topics). + + + The selector element is optional and defines a + JMS message selector. You should enclose it within CDATA blocks as some + of the selector characters are illegal XML. + + + The maxRetries element specifies how many times + a the server will try to push a message to a URL if there is a + connection failure. + + + The retryWaitMillis element specifies how long + to wait before performing a retry. + + + The + disableOnFailure element, if set to true, + will disable the registration if all retries have failed. It will not + disable the connection on non-connection-failure issues (like a bad + request for instance). In these cases, the dead letter queue logic of + HornetQ will take over. + + + The link element specifies the basis of the + interaction. The href attribute contains the URL you + want to interact with. It is the only required attribute. The + type attribute specifies the content-type of what the + push URL is expecting. The method attribute defines + what HTTP method the server will use when it sends the message to the + server. If it is not provided it defaults to POST. The + rel attribute is very important and the value of it + triggers different behavior. Here's the values a rel attribute can + have: + + + + + destination. The href URL is assumed to be a queue or topic resource of + another HornetQ REST server. The push registration will initially + do a HEAD request to this URL to obtain a msg-create-with-id + header. It will use this header to push new messages to the + HornetQ REST endpoint reliably. Here's an example: + + + +<push-registration> + <link rel="destination" href="http://somewhere.com/queues/jms.queue.foo"/> +</push-registration> + + + template. In this case, the server is expecting the link element's + href attribute to be a URL expression. The URL expression must + have one and only one URL parameter within it. The server will use + a unique value to create the endpoint URL. Here's an + example: + + + +<push-registration> + <link rel="template" href="http://somewhere.com/resources/{id}/messages" method="PUT"/> +</push-registration> + + In this example, the {id} sub-string is the one and only one + URL parameter. + + + + user defined. If the rel attributes is not destination or template (or is + empty or missing), then the server will send an HTTP message to + the href URL using the HTTP method defined in the method + attribute. Here's an example: + + + +<push-registration> + <link href="http://somewhere.com" type="application/json" method="PUT"/> +</push-registration> + + +
+ +
+ The Topic Push Subscription XML + + The push XML for a topic is the same except the root element is + push-topic-registration. (Also remember the selector + element is optional). The rest of the document is the same. Here's an + example of a template registration: + + + +<push-topic-registration> + <durable>true</durable> + <selector><![CDATA[ + SomeAttribute > 1 + ]]> + </selector> + <link rel="template" href="http://somewhere.com/resources/{id}/messages" method="POST"/> +</push-topic registration> +
+ +
+ Creating a Push Subscription at Runtime + + Creating a push subscription at runtime involves getting the + factory resource URL from the msg-push-consumers header, if the + destination is a queue, or msg-push-subscriptions header, if the + destination is a topic. Here's an example of creating a push + registration for a queue: + + + + + First do a HEAD request to the queue resource: + + +HEAD /queues/jms.queue.bar HTTP/1.1 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +msg-create: http://example.com/queues/jms.queue.bar/create +msg-pull-consumers: http://example.com/queues/jms.queue.bar/pull-consumers +msg-push-consumers: http://example.com/queues/jms.queue.bar/push-consumers + + + + Next POST your subscription XML to the URL returned from + msg-push-consumers header + + + +POST /queues/jms.queue.bar/push-consumers +Host: example.com +Content-Type: application/xml + +<push-registration> + <link rel="destination" href="http://somewhere.com/queues/jms.queue.foo"/> +</push-registration> + +--- Response --- +HTTP/1.1 201 Created +Location: http://example.com/queues/jms.queue.bar/push-consumers/1-333-1212 + + The Location header contains the URL for the created resource. + If you want to unregister this, then do a HTTP DELETE on this + URL. + + + + + Here's an example of creating a push registration for a + topic: + + + + + First do a HEAD request to the topic resource: + + +HEAD /topics/jms.topic.bar HTTP/1.1 +Host: example.com + +--- Response --- +HTTP/1.1 200 Ok +msg-create: http://example.com/topics/jms.topic.bar/create +msg-pull-subscriptions: http://example.com/topics/jms.topic.bar/pull-subscriptions +msg-push-subscriptions: http://example.com/topics/jms.topic.bar/push-subscriptions + + + + Next POST your subscription XML to the URL returned from + msg-push-subscriptions header + + + +POST /topics/jms.topic.bar/push-subscriptions +Host: example.com +Content-Type: application/xml + +<push-registration> + <link rel="template" href="http://somewhere.com/resources/{id}"/> +</push-registration> + +--- Response --- +HTTP/1.1 201 Created +Location: http://example.com/topics/jms.topic.bar/push-subscriptions/1-333-1212 + + The Location header contains the URL for the created resource. + If you want to unregister this, then do a HTTP DELETE on this + URL. + + + +
+ +
+ Creating a Push Subscription by Hand + + You can create a push XML file yourself if you do not want to go + through the REST interface to create a push subscription. There is some + additional information you need to provide though. First, in the root + element, you must define a unique id attribute. You must also define a + destination element to specify the queue you should register a consumer + with. For a topic, the destination element is the name of the + subscription that will be created. For a topic, you must also specify the + topic name within the topic element. + + + Here's an example of a hand-created queue registration. This file + must go in the directory specified by the queue-push-store-dir config + variable defined in Chapter 2: + + + +<push-registration id="111"> + <destination>jms.queue.bar</destination> + <durable>true</durable> + <link rel="template" href="http://somewhere.com/resources/{id}/messages" method="PUT"/> +</push-registration> + + Here's an example of a hand-created topic registration. This file + must go in the directory specified by the topic-push-store-dir config + variable defined in Chapter 2: + + + +<push-topic-registration id="112"> + <destination>my-subscription-1</destination + <durable>true</durable> + <link rel="template" href="http://somewhere.com/resources/{id}/messages" method="PUT"/> + <topic>jms.topic.foo</topic> +</push-topic-registration> +
+ +
+ Pushing to Authenticated Servers + + Push subscriptions only support BASIC and DIGEST authentication + out of the box. Here is an example of adding BASIC + authentication: + + + +<push-topic-registration> + <durable>true</durable> + <link rel="template" href="http://somewhere.com/resources/{id}/messages" method="POST"/> + <authentication> + <basic-auth> + <username>guest</username> + <password>geheim</password> + </basic-auth> + </authentication> +</push-topic registration> + + For DIGEST, just replace basic-auth with digest-auth. + + For other authentication mechanisms, you can register headers you + want transmitted with each request. Use the header element with the name + attribute representing the name of the header. Here's what custom + headers might look like: + + + +<push-topic-registration> + <durable>true</durable> + <link rel="template" href="http://somewhere.com/resources/{id}/messages" method="POST"/> + <header name="secret-header">jfdiwe3321</header> +</push-topic registration> +
+
+ + +
+ Creating Destinations + + You can create a durable queue or topic through the REST interface. + Currently you cannot create a temporary queue or topic. To create a queue + you do a POST to the relative URL /queues with an XML representation of + the queue. The XML syntax is the same queue syntax that you would specify + in hornetq-jms.xml if you were creating a queue there. For example: + + + +POST /queues +Host: example.com +Content-Type: application/hornetq.jms.queue+xml + +<queue name="testQueue"> + <durable>true</durable> +</queue> + +--- Response --- +HTTP/1.1 201 Created +Location: http://example.com/queues/jms.queue.testQueue + + Notice that the Content-Type is application/hornetq.jms.queue+xml. + + Here's what creating a topic would look like: + + +POST /topics +Host: example.com +Content-Type: application/hornetq.jms.topic+xml + +<topic name="testTopic"> +</topic> + +--- Response --- +HTTP/1.1 201 Created +Location: http://example.com/topics/jms.topic.testTopic +
+ + +
+ Securing the HornetQ REST Interface + +
+ Within JBoss Application server + + Securing the HornetQ REST interface is very simple with the JBoss + Application Server. You turn on authentication for all URLs within your + WAR's web.xml, and let the user Principal to propagate to HornetQ. This + only works if you are using the JBossSecurityManager with HornetQ. See + the HornetQ documentation for more details. + +
+ +
+ Security in other environments + + To secure the HornetQ REST interface in other environments you + must role your own security by specifying security constraints with your + web.xml for every path of every queue and topic you have deployed. Here + is a list of URI patterns: + + + + + + + /queues + + secure the POST operation to secure queue creation + + + + /queues/{queue-name} + + secure the GET HEAD operation to getting information about the queue. + + + + /queues/{queue-name}/create/* + + secure this URL pattern for producing messages. + + + + /queues/{queue-name}/pull-consumers/* + + secure this URL pattern for pulling messages. + + + + /queues/{queue-name}/push-consumers/* + + secure this URL pattern for pushing messages. + + + + /topics + + secure the POST operation to secure topic creation + + + + /topics/{topic-name} + + secure the GET HEAD operation to getting information about the topic. + + + + /topics/{topic-name}/create/* + + secure this URL pattern for producing messages. + + + + /topics/{topic-name}/pull-subscriptions/* + + secure this URL pattern for pulling messages. + + + + /topics/{topic-name}/push-subscriptions/* + + secure this URL pattern for pushing messages. + + + +
+
+
+ + +
+ Mixing JMS and REST + + The HornetQ REST interface supports mixing JMS and REST producers + and consumers. You can send an ObjectMessage through a JMS Producer, and + have a REST client consume it. You can have a REST client POST a message + to a topic and have a JMS Consumer receive it. Some simple transformations + are supported if you have the correct RESTEasy providers installed. + + +
+ JMS Producers - REST Consumers + + If you have a JMS producer, the HornetQ REST interface only + supports ObjectMessage type. If the JMS producer is aware that there may + be REST consumers, it should set a JMS property to specify what + Content-Type the Java object should be translated into by REST clients. + The HornetQ REST server will use RESTEasy content handlers + (MessageBodyReader/Writers) to transform the Java object to the type + desired. Here's an example of a JMS producer setting the content type of + the message. + + + +ObjectMessage message = session.createObjectMessage(); +message.setStringProperty(org.hornetq.rest.HttpHeaderProperty.CONTENT_TYPE, "application/xml"); + + If the JMS producer does not set the content-type, then this + information must be obtained from the REST consumer. If it is a pull + consumer, then the REST client should send an Accept header with the + desired media types it wants to convert the Java object into. If the + REST client is a push registration, then the type attribute of the link + element of the push registration should be set to the desired + type. + +
+ +
+ REST Producers - JMS Consumers + + If you have a REST client producing messages and a JMS consumer, + HornetQ REST has a simple helper class for you to transform the HTTP + body to a Java object. Here's some example code: + + + +public void onMessage(Message message) +{ + MyType obj = org.hornetq.rest.Jms.getEntity(message, MyType.class); +} + + The way the getEntity() method works is that if + the message is an ObjectMessage, it will try to extract the desired type + from it like any other JMS message. If a REST producer sent the message, + then the method uses RESTEasy to convert the HTTP body to the Java + object you want. See the Javadoc of this class for more helper + methods. + +
+
+
diff --git a/docs/user-manual/en/scheduled-messages.xml b/docs/user-manual/en/scheduled-messages.xml new file mode 100644 index 0000000000..509904e9e4 --- /dev/null +++ b/docs/user-manual/en/scheduled-messages.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Scheduled Messages + Scheduled messages differ from normal messages in that they won't be delivered until a + specified time in the future, at the earliest. + To do this, a special property is set on the message before sending it. +
+ Scheduled Delivery Property + The property name used to identify a scheduled message is "_HQ_SCHED_DELIVERY" (or the constant Message.HDR_SCHEDULED_DELIVERY_TIME). + The specified value must be a positive long corresponding to the time the + message must be delivered (in milliseconds). An example of sending a scheduled message + using the JMS API is as follows. + +TextMessage message = session.createTextMessage("This is a scheduled message message which will be delivered in 5 sec."); +message.setLongProperty("_HQ_SCHED_DELIVERY", System.currentTimeMillis() + 5000); +producer.send(message); + +... + +// message will not be received immediately but 5 seconds later +TextMessage messageReceived = (TextMessage) consumer.receive(); + Scheduled messages can also be sent using the core API, by setting the same property on + the core message before sending. +
+
+ Example + See for an example which shows how + scheduled messages can be used with JMS. +
+
diff --git a/docs/user-manual/en/security.xml b/docs/user-manual/en/security.xml new file mode 100644 index 0000000000..91a832e9f0 --- /dev/null +++ b/docs/user-manual/en/security.xml @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Security + This chapter describes how security works with HornetQ and how you can configure it. To + disable security completely simply set the security-enabled property to + false in the hornetq-configuration.xml file. + For performance reasons security is cached and invalidated every so long. To change this + period set the property security-invalidation-interval, which is in + milliseconds. The default is 10000 ms. +
+ Role based security for addresses + HornetQ contains a flexible role-based security model for applying security to queues, + based on their addresses. + As explained in , HornetQ core consists mainly of sets of + queues bound to addresses. A message is sent to an address and the server looks up the + set of queues that are bound to that address, the server then routes the message to + those set of queues. + HornetQ allows sets of permissions to be defined against the queues based on their + address. An exact match on the address can be used or a wildcard match can be used using + the wildcard characters '#' and '*'. + Seven different permissions can be given to the set of queues which match the address. + Those permissions are: + + + createDurableQueue. This permission allows the user to + create a durable queue under matching addresses. + + + deleteDurableQueue. This permission allows the user to + delete a durable queue under matching addresses. + + + createNonDurableQueue. This permission allows the user to create + a non-durable queue under matching addresses. + + + deleteNonDurableQueue. This permission allows the user to delete + a non-durable queue under matching addresses. + + + send. This permission allows the user to send a message to + matching addresses. + + + consume. This permission allows the user to consume a + message from a queue bound to matching addresses. + + + manage. This permission allows the user to invoke + management operations by sending management messages to the management + address. + + + For each permission, a list of roles who are granted that permission is specified. If + the user has any of those roles, he/she will be granted that permission for that set of + addresses. + Let's take a simple example, here's a security block from hornetq-configuration.xml or hornetq-queues.xml + file: + +<security-setting match="globalqueues.europe.#"> + <permission type="createDurableQueue" roles="admin"/> + <permission type="deleteDurableQueue" roles="admin"/> + <permission type="createNonDurableQueue" roles="admin, guest, europe-users"/> + <permission type="deleteNonDurableQueue" roles="admin, guest, europe-users"/> + <permission type="send" roles="admin, europe-users"/> + <permission type="consume" roles="admin, europe-users"/> +</security-setting> + The '#' character signifies "any sequence of words". Words are + delimited by the '.' character. For a full description of the + wildcard syntax please see . The above security block + applies to any address that starts with the string "globalqueues.europe.": + Only users who have the admin role can create or delete durable + queues bound to an address that starts with the string "globalqueues.europe." + Any users with the roles admin, guest, or + europe-users can create or delete temporary queues bound to an + address that starts with the string "globalqueues.europe." + Any users with the roles admin or europe-users + can send messages to these addresses or consume messages from queues bound to an address + that starts with the string "globalqueues.europe." + The mapping between a user and what roles they have is handled by the security + manager. HornetQ ships with a user manager that reads user credentials from a file on + disk, and can also plug into JAAS or JBoss Application Server security. + For more information on configuring the security manager, please see . + There can be zero or more security-setting elements in each xml + file. Where more than one match applies to a set of addresses the more + specific match takes precedence. + Let's look at an example of that, here's another security-setting + block: + +<security-setting match="globalqueues.europe.orders.#"> + <permission type="send" roles="europe-users"/> + <permission type="consume" roles="europe-users"/> +</security-setting> + In this security-setting block the match + 'globalqueues.europe.orders.#' is more specific than the previous match + 'globalqueues.europe.#'. So any addresses which match 'globalqueues.europe.orders.#' + will take their security settings only from the latter + security-setting block. + Note that settings are not inherited from the former block. All the settings will be + taken from the more specific matching block, so for the address + 'globalqueues.europe.orders.plastics' the only permissions that exist are send and consume for the role europe-users. The + permissions createDurableQueue, deleteDurableQueue, createNonDurableQueue, deleteNonDurableQueue are not inherited from the other security-setting + block. + By not inheriting permissions, it allows you to effectively deny permissions in more + specific security-setting blocks by simply not specifying them. Otherwise it would not + be possible to deny permissions in sub-groups of addresses. +
+
+ Secure Sockets Layer (SSL) Transport + When messaging clients are connected to servers, or servers are connected to other + servers (e.g. via bridges) over an untrusted network then HornetQ allows that traffic to + be encrypted using the Secure Sockets Layer (SSL) transport. + For more information on configuring the SSL transport, please see . +
+
+ Basic user credentials + HornetQ ships with a security manager implementation that reads user credentials, i.e. + user names, passwords and role information from an xml file on the classpath called + hornetq-users.xml. This is the default security manager. + If you wish to use this security manager, then users, passwords and roles can easily + be added into this file. + Let's take a look at an example file: + +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq ../schemas/hornetq-users.xsd "> + + <defaultuser name="guest" password="guest"> + <role name="guest"/> + </defaultuser> + + <user name="tim" password="marmite"> + <role name="admin"/> + </user> + + <user name="andy" password="doner_kebab"> + <role name="admin"/> + <role name="guest"/> + </user> + + <user name="jeff" password="camembert"> + <role name="europe-users"/> + <role name="guest"/> + </user> + +</configuration> + The first thing to note is the element defaultuser. This defines + what user will be assumed when the client does not specify a username/password when + creating a session. In this case they will be the user guest and have + the role also called guest. Multiple roles can be specified for a + default user. + We then have three more users, the user tim has the role admin. The user andy has the roles admin and guest, and the user jeff + has the roles europe-users and guest. +
+
+ Changing the security manager + If you do not want to use the default security manager then you can specify a + different one by editing the file hornetq-beans.xml (or hornetq-jboss-beans.xml if you're running JBoss Application Server) and + changing the class for the HornetQSecurityManager bean. + Let's take a look at a snippet from the default beans file: + +<bean name="HornetQSecurityManager" class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl"> + <start ignored="true"/> + <stop ignored="true"/> +</bean> + The class org.hornetq.spi.core.security.HornetQSecurityManagerImpl + is the default security manager that is used by the standalone server. + HornetQ ships with two other security manager implementations you can use + off-the-shelf; one a JAAS security manager and another for integrating with JBoss + Application Sever security, alternatively you could write your own implementation by + implementing the org.hornetq.spi.core.security.HornetQSecurityManager + interface, and specifying the classname of your implementation in the file hornetq-beans.xml (or hornetq-jboss-beans.xml if + you're running JBoss Application Server). + These two implementations are discussed in the next two sections. +
+
+ JAAS Security Manager + JAAS stands for 'Java Authentication and Authorization Service' and is a standard part + of the Java platform. It provides a common API for security authentication and + authorization, allowing you to plugin your pre-built implementations. + To configure the JAAS security manager to work with your pre-built JAAS infrastructure + you need to specify the security manager as a JAASSecurityManager in + the beans file. Here's an example: + +<bean name="HornetQSecurityManager" class="org.hornetq.integration.jboss.security.JAASSecurityManager"> + <start ignored="true"/> + <stop ignored="true"/> + + <property name="ConfigurationName">org.hornetq.jms.example.ExampleLoginModule</property> + <property name="Configuration"> + <inject bean="ExampleConfiguration"/> + </property> + <property name="CallbackHandler"> + <inject bean="ExampleCallbackHandler"/> + </property> +</bean> + Note that you need to feed the JAAS security manager with three properties: + + + ConfigurationName: the name of the LoginModule + implementation that JAAS must use + + + Configuration: the Configuration implementation used by + JAAS + + + CallbackHandler: the CallbackHandler implementation to use + if user interaction are required + + +
+ Example + See for an example which shows how HornetQ can be + configured to use JAAS. +
+
+
+ JBoss AS Security Manager + The JBoss AS security manager is used when running HornetQ inside the JBoss + Application server. This allows tight integration with the JBoss Application Server's + security model. + The class name of this security manager is org.hornetq.integration.jboss.security.JBossASSecurityManager + Take a look at one of the default hornetq-jboss-beans.xml files for + JBoss Application Server that are bundled in the distribution for an example of how this + is configured. +
+ Configuring Client Login + JBoss can be configured to allow client login, basically this is when a JEE component such as a Servlet + or EJB sets security credentials on the current security context and these are used throughout the call. + If you would like these credentials to be used by HornetQ when sending or consuming messages then + set allowClientLogin to true. This will bypass HornetQ authentication and propagate the + provided Security Context. If you would like HornetQ to authenticate using the propagated security then set the + authoriseOnClientLogin to true also. + There is more info on using the JBoss client login module here + If messages are sent non blocking then there is a chance that these could arrive on the server after + the calling thread has completed meaning that the security context has been cleared. If this is the case then messages + will need to be sent blocking +
+
+ Changing the Security Domain + The name of the security domain used by the JBoss AS security manager defaults to java:/jaas/hornetq + . This can be changed by specifying securityDomainName (e.g. java:/jaas/myDomain). + +
+
+
+ Changing the username/password for clustering + In order for cluster connections to work correctly, each node in the cluster must make + connections to the other nodes. The username/password they use for this should always be + changed from the installation default to prevent a security risk. + Please see for instructions on how to do this. +
+
diff --git a/docs/user-manual/en/send-guarantees.xml b/docs/user-manual/en/send-guarantees.xml new file mode 100644 index 0000000000..40a0bc5430 --- /dev/null +++ b/docs/user-manual/en/send-guarantees.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Guarantees of sends and commits +
+ Guarantees of Transaction Completion + When committing or rolling back a transaction with HornetQ, the request to commit or + rollback is sent to the server, and the call will block on the client side until a + response has been received from the server that the commit or rollback was + executed. + When the commit or rollback is received on the server, it will be committed to the + journal, and depending on the value of the parameter journal-sync-transactional the server will ensure that the commit or + rollback is durably persisted to storage before sending the response back to the client. + If this parameter has the value false then commit or rollback may not + actually get persisted to storage until some time after the response has been sent to + the client. In event of server failure this may mean the commit or rollback never gets + persisted to storage. The default value of this parameter is true so + the client can be sure all transaction commits or rollbacks have been persisted to + storage by the time the call to commit or rollback returns. + Setting this parameter to false can improve performance at the + expense of some loss of transaction durability. + This parameter is set in hornetq-configuration.xml +
+
+ Guarantees of Non Transactional Message Sends + If you are sending messages to a server using a non transacted session, HornetQ can be + configured to block the call to send until the message has definitely reached the + server, and a response has been sent back to the client. This can be configured + individually for durable and non-durable messages, and is determined by the + following two parameters: + + + BlockOnDurableSend. If this is set to true then all calls to send for durable messages on non + transacted sessions will block until the message has reached the server, and a + response has been sent back. The default value is true. + + + + BlockOnNonDurableSend. If this is set to true then all calls to send for non-durable messages on non + transacted sessions will block until the message has reached the server, and a + response has been sent back. The default value is false. + + + Setting block on sends to true can reduce performance since each + send requires a network round trip before the next send can be performed. This means the + performance of sending messages will be limited by the network round trip time (RTT) of + your network, rather than the bandwidth of your network. For better performance we + recommend either batching many messages sends together in a transaction since with a + transactional session, only the commit / rollback blocks not every send, or, using + HornetQ's advanced asynchronous send acknowledgements feature + described in . + If you are using JMS and you're using the JMS service on the server to load your JMS + connection factory instances into JNDI then these parameters can be configured in + hornetq-jms.xml using the elements block-on-durable-send and block-on-non-durable-send. If you're using JMS but not using JNDI then + you can set these values directly on the HornetQConnectionFactory + instance using the appropriate setter methods. + If you're using core you can set these values directly on the ClientSessionFactory instance using the appropriate setter + methods. + When the server receives a message sent from a non transactional session, and that + message is durable and the message is routed to at least one durable queue, then the + server will persist the message in permanent storage. If the journal parameter journal-sync-non-transactional is set to true the + server will not send a response back to the client until the message has been persisted + and the server has a guarantee that the data has been persisted to disk. The default + value for this parameter is true. +
+
+ Guarantees of Non Transactional Acknowledgements + If you are acknowledging the delivery of a message at the client side using a non + transacted session, HornetQ can be configured to block the call to acknowledge until the + acknowledge has definitely reached the server, and a response has been sent back to the + client. This is configured with the parameter BlockOnAcknowledge. If + this is set to true then all calls to acknowledge on non transacted + sessions will block until the acknowledge has reached the server, and a response has + been sent back. You might want to set this to true if you want to + implement a strict at most once delivery policy. The default value + is false +
+
+ Asynchronous Send Acknowledgements + If you are using a non transacted session but want a guarantee that every message sent + to the server has reached it, then, as discussed in , you can configure HornetQ to block the call to + send until the server has received the message, persisted it and sent back a response. + This works well but has a severe performance penalty - each call to send needs to block + for at least the time of a network round trip (RTT) - the performance of sending is thus + limited by the latency of the network, not limited by the network + bandwidth. + Let's do a little bit of maths to see how severe that is. We'll consider a standard + 1Gib ethernet network with a network round trip between the server and the client of + 0.25 ms. + With a RTT of 0.25 ms, the client can send at most 1000/ 0.25 = + 4000 messages per second if it blocks on each message send. + If each message is < 1500 bytes and a standard 1500 bytes MTU size is used on the + network, then a 1GiB network has a theoretical upper limit of (1024 + * 1024 * 1024 / 8) / 1500 = 89478 messages per second if messages are sent without + blocking! These figures aren't an exact science but you can clearly see that being + limited by network RTT can have serious effect on performance. + To remedy this, HornetQ provides an advanced new feature called asynchronous + send acknowledgements. With this feature, HornetQ can be configured to + send messages without blocking in one direction and asynchronously getting + acknowledgement from the server that the messages were received in a separate stream. By + de-coupling the send from the acknowledgement of the send, the system is not limited by + the network RTT, but is limited by the network bandwidth. Consequently better throughput + can be achieved than is possible using a blocking approach, while at the same time + having absolute guarantees that messages have successfully reached the server. + The window size for send acknowledgements is determined by the confirmation-window-size parameter on + the connection factory or client session factory. Please see for more info on this. +
+ Asynchronous Send Acknowledgements + To use the feature using the core API, you implement the interface org.hornetq.api.core.client.SendAcknowledgementHandler and set a handler + instance on your ClientSession. + Then, you just send messages as normal using your ClientSession, and as messages reach the server, the server will send + back an acknowledgement of the send asynchronously, and some time later you are + informed at the client side by HornetQ calling your handler's sendAcknowledged(ClientMessage message) method, passing in a + reference to the message that was sent. + To enable asynchronous send acknowledgements you must make sure confirmation-window-size is set to a positive integer value, e.g. 10MiB + Please see for a full + working example. +
+
+
diff --git a/docs/user-manual/en/spring-integration.xml b/docs/user-manual/en/spring-integration.xml new file mode 100644 index 0000000000..730fa02597 --- /dev/null +++ b/docs/user-manual/en/spring-integration.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Spring Integration + + HornetQ provides a simple bootstrap class, + org.hornetq.integration.spring.SpringJmsBootstrap, for + integration with Spring. To use it, you configure HornetQ as you always + would, through its various configuration files like + hornetq-configuration.xml, + hornetq-jms.xml, and + hornetq-users.xml. The Spring helper class starts the + HornetQ server and adds any factories or destinations configured within + hornetq-jms.xml directly into the namespace of the Spring + context. Let's take this hornetq-jms.xml file for + instance: + +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd"> + <!--the connection factory used by the example--> + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="in-vm"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + </connection-factory> + + <!--the queue used by the example--> + <queue name="exampleQueue"> + <entry name="/queue/exampleQueue"/> + </queue> +</configuration> + Here we've specified a + javax.jms.ConnectionFactory we want bound to a + ConnectionFactory entry as well as a queue destination + bound to a /queue/exampleQueue entry. Using the + SpringJmsBootStrap bean will automatically populate the + Spring context with references to those beans so that you can use them. + Below is an example Spring JMS bean file taking advantage of this + feature: + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> + + <bean id="EmbeddedJms" class="org.hornetq.integration.spring.SpringJmsBootstrap" init-method="start"/> + + <bean id="listener" class="org.hornetq.tests.integration.spring.ExampleListener"/> + + <bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> + <property name="connectionFactory" ref="ConnectionFactory"/> + <property name="destination" ref="/queue/exampleQueue"/> + <property name="messageListener" ref="listener"/> + </bean> +</beans> + As you can see, the + listenerContainer bean references the components defined + in the hornetq-jms.xml file. The + SpringJmsBootstrap class extends the EmbeddedJMS class + talked about in and the same defaults and + configuration options apply. Also notice that an + init-method must be declared with a start value so that + the bean's lifecycle is executed. See the javadocs for more details on other + properties of the bean class. + diff --git a/docs/user-manual/en/thread-pooling.xml b/docs/user-manual/en/thread-pooling.xml new file mode 100644 index 0000000000..e78b1b01fe --- /dev/null +++ b/docs/user-manual/en/thread-pooling.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Thread management + This chapter describes how HornetQ uses and pools threads and how you can manage + them. + First we'll discuss how threads are managed and used on the server side, then we'll look + at the client side. +
+ Server-Side Thread Management + Each HornetQ Server maintains a single thread pool for general use, and a scheduled + thread pool for scheduled use. A Java scheduled thread pool cannot be configured to use + a standard thread pool, otherwise we could use a single thread pool for both scheduled + and non scheduled activity. + A separate thread pool is also used to service connections. HornetQ can use "old" + (blocking) IO or "new" (non-blocking) IO also called NIO. Both of these options use + a separate thread pool, but each of them behaves uniquely. + Since old IO requires a thread per connection its thread pool is unbounded. The thread + pool is created via + java.util.concurrent.Executors.newCachedThreadPool(ThreadFactory). As the + JavaDoc for this method states: + Creates a thread pool that creates new threads as needed, but will reuse previously + constructed threads when they are available, and uses the provided ThreadFactory to create + new threads when needed. + Threads from this pool which are idle for more than 60 seconds will time out and be + removed. If old IO connections were serviced from the standard pool the pool would + easily get exhausted if too many connections were made, resulting in the server "hanging" + since it has no remaining threads to do anything else. However, even an unbounded thread + pool can run into trouble if it becomes too large. If you require the server to handle + many concurrent connections you should use NIO, not old IO. + When using new IO (NIO), HornetQ will, by default, cap its thread pool at three times + the number of cores (or hyper-threads) as reported by + Runtime.getRuntime().availableProcessors() for processing incoming packets. + To override this value, you can set the number of threads by specifying the parameter + nio-remoting-threads in the transport configuration. See the + for more information on this. + There are also a small number of other places where threads are used directly, we'll + discuss each in turn. +
+ Server Scheduled Thread Pool + The server scheduled thread pool is used for most activities on the server side + that require running periodically or with delays. It maps internally to a java.util.concurrent.ScheduledThreadPoolExecutor instance. + The maximum number of thread used by this pool is configure in hornetq-configuration.xml with the scheduled-thread-pool-max-size parameter. The default value is + 5 threads. A small number of threads is usually sufficient + for this pool. +
+
+ General Purpose Server Thread Pool + This general purpose thread pool is used for most asynchronous actions on the + server side. It maps internally to a java.util.concurrent.ThreadPoolExecutor instance. + The maximum number of thread used by this pool is configure in hornetq-configuration.xml with the thread-pool-max-size parameter. + If a value of -1 is used this signifies that the thread pool + has no upper bound and new threads will be created on demand if there are not enough + threads available to satisfy a request. If activity later subsides then threads are + timed-out and closed. + If a value of n where nis a positive integer + greater than zero is used this signifies that the thread pool is bounded. If more + requests come in and there are no free threads in the pool and the pool is full then + requests will block until a thread becomes available. It is recommended that a + bounded thread pool is used with caution since it can lead to dead-lock situations + if the upper bound is chosen to be too low. + The default value for thread-pool-max-size is 30. + See the J2SE javadoc for more information on unbounded (cached), and bounded + (fixed) thread pools. +
+
+ Expiry Reaper Thread + A single thread is also used on the server side to scan for expired messages in + queues. We cannot use either of the thread pools for this since this thread needs to + run at its own configurable priority. + For more information on configuring the reaper, please see . +
+
+ Asynchronous IO + Asynchronous IO has a thread pool for receiving and dispatching events out of the + native layer. You will find it on a thread dump with the prefix + HornetQ-AIO-poller-pool. HornetQ uses one thread per opened file on the journal + (there is usually one). + There is also a single thread used to invoke writes on libaio. We do that to avoid + context switching on libaio that would cause performance issues. You will find this + thread on a thread dump with the prefix HornetQ-AIO-writer-pool. +
+
+
+ Client-Side Thread Management + On the client side, HornetQ maintains a single static scheduled thread pool and a + single static general thread pool for use by all clients using the same classloader in + that JVM instance. + The static scheduled thread pool has a maximum size of 5 threads, + and the general purpose thread pool has an unbounded maximum size. + If required HornetQ can also be configured so that each ClientSessionFactory instance does not use these static pools but instead + maintains its own scheduled and general purpose pool. Any sessions created from that + ClientSessionFactory will use those pools instead. + To configure a ClientSessionFactory instance to use its own pools, + simply use the appropriate setter methods immediately after creation, for + example: + +ServerLocator locator = HornetQClient.createServerLocatorWithoutHA(...) +ClientSessionFactory myFactory = locator.createClientSessionFactory(); +myFactory.setUseGlobalPools(false); +myFactory.setScheduledThreadPoolMaxSize(10); +myFactory.setThreadPoolMaxSize(-1); + If you're using the JMS API, you can set the same parameters on the + ClientSessionFactory and use it to create the ConnectionFactory + instance, for example: + +ConnectionFactory myConnectionFactory = HornetQJMSClient.createConnectionFactory(myFactory); + If you're using JNDI to instantiate HornetQConnectionFactory + instances, you can also set these parameters in the hornetq-jms.xml + file where you describe your connection factory, for example: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + <entry name="XAConnectionFactory"/> + </entries> + <use-global-pools>false</use-global-pools> + <scheduled-thread-pool-max-size>10</scheduled-thread-pool-max-size> + <thread-pool-max-size>-1</thread-pool-max-size> +</connection-factory> +
+
diff --git a/docs/user-manual/en/tools.xml b/docs/user-manual/en/tools.xml new file mode 100644 index 0000000000..12bf70e5ce --- /dev/null +++ b/docs/user-manual/en/tools.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + %BOOK_ENTITIES; + ]> + + Tools + + HornetQ ships with several helpful command line tools. All tools are available from the hornetq-tools-<version>-jar-with-dependencies.jar. + As the name suggests, this Java archive contains HornetQ along with all of its dependencies. This is done to + simplify the execution of the tools by eliminating the need so specify a classpath. These tools are: + + + print-data. Used for low-level inspection of the bindings and message journals. It + takes two parameters - bindings-directory and journal-directory. These + are the paths to the directories where the bindings and message journals are stored, respectively. For + example: + + java -jar hornetq-tools-<version>-jar-with-dependencies.jar print-data /home/user/hornetq/data/bindings /home/user/hornetq/data/journal + + + print-pages. Used for low-level inspection of paged message data. It takes two + parameters - paging-directory and journal-directory. These are the + paths to the directories where paged messages and the message journals are stored, respectively. For + example: + + java -jar hornetq-tools-<version>-jar-with-dependencies.jar print-pages /home/user/hornetq/data/paging-directory /home/user/hornetq/data/journal + + + export. Used for exporting all binding and message data (including paged and large + messages) as well as JMS destinations and connection factories (including JNDI bindings). The export is + structured as XML. This data can then be imported to another server even if the server is a different + version than the original. It takes 4 parameters: + + + + bindings-directory - the path to the bindings directory. + + + journal-directory - the path to the journal directory. + + + paging-directory - the path to the paging directory. + + + large-messages-directory - the path to the large-messages directory. + + + Here's an example: + java -jar hornetq-tools-<version>-jar-with-dependencies.jar export /home/user/hornetq/data/bindings-directory /home/user/hornetq/data/journal-directory /home/user/hornetq/data/paging-directory /home/user/hornetq/data/large-messages + This tool will export directly to standard out so if the data needs to be stored in a file please + redirect as appropriate for the operation system in use. Also, please note that the export + tool is single threaded so depending on the size of the journal it could take awhile to complete. + + + + import. Used for importing data from an XML document generated by the + export tool. The import tool reads the XML document and connects + to a HornetQ server via Netty to import all the data. It takes 5 parameters: + + + + input-file - the path to the XML file generated by the export + tool. + + + + host - the IP address or hostname of the server where the data should be + imported. + + + + port - the port where HornetQ is listening. + + + transactional - a boolean flag to indicate whether or not to + send all the message data in a single transaction. Valid values are true + or false. + + + + application-server-compatibility - a boolean flag to indicate + whether or not JNDI bindings need special treatment to account for the way JBoss AS7, Wildfly, and + JBoss EAP 6 handle JNDI for remote clients. Each of these application servers require a special JNDI + binding to allow access from remote clients. If this is true then every JNDI + binding in the XML will be duplicated in the "java:jboss/exported/" namespace thus allowing both local + and remote clients to use the same name when accessing resources via JNDI. Valid values are + true or false. + + + + Here's an example: + java -jar hornetq-tools-<version>-jar-with-dependencies.jar import /home/user/exportData.xml 127.0.0.1 5445 false false + Like the export tool the import tool is single threaded so + depending on the size of the XML file it may take awhile for the process to complete. + + + + diff --git a/docs/user-manual/en/transaction-config.xml b/docs/user-manual/en/transaction-config.xml new file mode 100644 index 0000000000..4f0905e3a8 --- /dev/null +++ b/docs/user-manual/en/transaction-config.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Resource Manager Configuration + HornetQ has its own Resource Manager for handling the lifespan of JTA transactions. When a + transaction is started the resource manager is notified and keeps a record of the + transaction and its current state. It is possible in some cases for a transaction to be + started but then forgotten about. Maybe the client died and never came back. If this happens + then the transaction will just sit there indefinitely. + To cope with this HornetQ can, if configured, scan for old transactions and rollback any + it finds. The default for this is 3000000 milliseconds (5 minutes), i.e. any transactions older + than 5 minutes are removed. This timeout can be changed by editing the transaction-timeout property in hornetq-configuration.xml (value must be in milliseconds). + The property transaction-timeout-scan-period configures how often, in + milliseconds, to scan for old transactions. + Please note that HornetQ will not unilaterally rollback any XA transactions in a prepared state - this must be heuristically rolled + back via the management API if you are sure they will never be resolved by the transaction manager. + diff --git a/docs/user-manual/en/undelivered-messages.xml b/docs/user-manual/en/undelivered-messages.xml new file mode 100644 index 0000000000..ec76c5d30f --- /dev/null +++ b/docs/user-manual/en/undelivered-messages.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Message Redelivery and Undelivered Messages + Messages can be delivered unsuccessfully (e.g. if the transacted session used to consume + them is rolled back). Such a message goes back to its queue ready to be redelivered. However, + this means it is possible for a message to be delivered again and again without any success + and remain in the queue, clogging the system. + There are 2 ways to deal with these undelivered messages: + + + Delayed redelivery. + It is possible to delay messages redelivery to let the client some time to recover + from transient failures and not overload its network or CPU resources + + + Dead Letter Address. + It is also possible to configure a dead letter address so that after a specified + number of unsuccessful deliveries, messages are removed from the queue and will not be + delivered again + + + Both options can be combined for maximum flexibility. +
+ Delayed Redelivery + Delaying redelivery can often be useful in the case that clients regularly fail or + rollback. Without a delayed redelivery, the system can get into a "thrashing" state, with + delivery being attempted, the client rolling back, and delivery being re-attempted ad + infinitum in quick succession, consuming valuable CPU and network resources. +
+ Configuring Delayed Redelivery + Delayed redelivery is defined in the address-setting configuration: + +<!-- delay redelivery of messages for 5s --> +<address-setting match="jms.queue.exampleQueue"> + <!-- default is 1.0 --> + <redelivery-delay-multiplier>1.5</redelivery-delay-multiplier> + <!-- default is 0 (no delay) --> + <redelivery-delay>5000</redelivery-delay> + <!-- default is redelivery-delay * 10 --> + <max-redelivery-delay>50000</max-redelivery-delay> + +</address-setting> + If a redelivery-delay is specified, HornetQ will wait this delay + before redelivering the messages. + By default, there is no redelivery delay (redelivery-delayis set + to 0). + Other subsequent messages will be delivery regularly, only the cancelled message + will be sent asynchronously back to the queue after the delay. + You can specify a multiplier that will take effect on top of the redelivery-delay + with a max-redelivery-delay to be taken into account. + The max-redelivery-delay is defaulted to redelivery-delay * 10 + Address wildcards can be used to configure redelivery delay for a set of addresses + (see ), so you don't have to specify redelivery delay + individually for each address. +
+
+ Example + See for an example which shows how + delayed redelivery is configured and used with JMS. +
+
+
+ Dead Letter Addresses + To prevent a client infinitely receiving the same undelivered message (regardless of + what is causing the unsuccessful deliveries), messaging systems define dead letter addresses: after a specified unsuccessful delivery + attempts, the message is removed from the queue and send instead to a dead letter address. + Any such messages can then be diverted to queue(s) where they can later be perused by + the system administrator for action to be taken. + HornetQ's addresses can be assigned a dead letter address. Once the messages have been + unsuccessfully delivered for a given number of attempts, they are removed from the queue + and sent to the dead letter address. These dead letter messages can + later be consumed for further inspection. +
+ Configuring Dead Letter Addresses + Dead letter address is defined in the address-setting configuration: + +<!-- undelivered messages in exampleQueue will be sent to the dead letter address + deadLetterQueue after 3 unsuccessful delivery attempts --> +<address-setting match="jms.queue.exampleQueue"> + <dead-letter-address>jms.queue.deadLetterQueue</dead-letter-address> + <max-delivery-attempts>3</max-delivery-attempts> +</address-setting> + If a dead-letter-address is not specified, messages will removed + after max-delivery-attempts unsuccessful attempts. + By default, messages are redelivered 10 times at the maximum. Set max-delivery-attempts to -1 for infinite redeliveries. + For example, a dead letter can be set globally for a set of matching addresses and + you can set max-delivery-attempts to -1 for a specific address + setting to allow infinite redeliveries only for this address. + Address wildcards can be used to configure dead letter settings for a set of + addresses (see ). +
+
+ Dead Letter Properties + Dead letter messages which are consumed from a dead letter address have the following + properties: + + + _HQ_ORIG_ADDRESS + a String property containing the original address of + the dead letter message + + + _HQ_ORIG_QUEUE + a String property containing the original queue of + the dead letter message + + +
+
+ Example + See for an example which shows how dead letter + is configured and used with JMS. +
+
+
+ Delivery Count Persistence + In normal use, HornetQ does not update delivery count persistently + until a message is rolled back (i.e. the delivery count is not updated + before the message is delivered to the consumer). In most messaging + use cases, the messages are consumed, acknowledged and forgotten as soon as they are + consumed. In these cases, updating the delivery count persistently before delivering the + message would add an extra persistent step for each message delivered, + implying a significant performance penalty. + However, if the delivery count is not updated persistently before the message delivery + happens, in the event of a server crash, messages might have been delivered but that will + not have been reflected in the delivery count. During the recovery phase, the server will + not have knowledge of that and will deliver the message with redelivered + set to false while it should be true. + As this behavior breaks strict JMS semantics, HornetQ allows to persist delivery count + before message delivery but disabled it by default for performance implications. + To enable it, set persist-delivery-count-before-delivery to true in hornetq-configuration.xml: + +<persist-delivery-count-before-delivery>true</persist-delivery-count-before-delivery> +
+
diff --git a/docs/user-manual/en/using-core.xml b/docs/user-manual/en/using-core.xml new file mode 100644 index 0000000000..eb72c79d3b --- /dev/null +++ b/docs/user-manual/en/using-core.xml @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + Using Core + HornetQ core is a completely JMS-agnostic messaging system with its own non-JMS API. We + call this the core API. + If you don't want to use JMS you can use the core API directly. The core API provides all + the functionality of JMS but without much of the complexity. It also provides features that + are not available using JMS. +
+ Core Messaging Concepts + Some of the core messaging concepts are similar to JMS concepts, but core messaging + concepts differ in some ways. In general the core messaging API is simpler than the JMS + API, since we remove distinctions between queues, topics and subscriptions. We'll + discuss each of the major core messaging concepts in turn, but to see the API in detail, + please consult the Javadoc. +
+ Message + + + A message is the unit of data which is sent between clients and + servers. + + + A message has a body which is a buffer containing convenient methods for + reading and writing data into it. + + + A message has a set of properties which are key-value pairs. Each property + key is a string and property values can be of type integer, long, short, + byte, byte[], String, double, float or boolean. + + + A message has an address it is being sent to. When + the message arrives on the server it is routed to any queues that are bound + to the address - if the queues are bound with any filter, the message will + only be routed to that queue if the filter matches. An address may have many + queues bound to it or even none. There may also be entities other than + queues, like diverts bound to + addresses. + + + Messages can be either durable or non durable. Durable messages in a + durable queue will survive a server crash or restart. Non durable messages + will never survive a server crash or restart. + + + Messages can be specified with a priority value between 0 and 9. 0 + represents the lowest priority and 9 represents the highest. HornetQ will + attempt to deliver higher priority messages before lower priority + ones. + + + Messages can be specified with an optional expiry time. HornetQ will not + deliver messages after its expiry time has been exceeded. + + + Messages also have an optional timestamp which represents the time the + message was sent. + + + HornetQ also supports the sending/consuming of very large messages - much + larger than can fit in available RAM at any one time. + + +
+
+ Address + A server maintains a mapping between an address and a set of queues. Zero or more + queues can be bound to a single address. Each queue can be bound with an optional + message filter. When a message is routed, it is routed to the set of queues bound to + the message's address. If any of the queues are bound with a filter expression, then + the message will only be routed to the subset of bound queues which match that + filter expression. + Other entities, such as diverts can also be + bound to an address and messages will also be routed there. + + In core, there is no concept of a Topic, Topic is a JMS only term. Instead, in + core, we just deal with addresses and + queues. + For example, a JMS topic would be implemented by a single address to which + many queues are bound. Each queue represents a subscription of the topic. A JMS + Queue would be implemented as a single address to which one queue is bound - + that queue represents the JMS queue. + +
+
+ Queue + Queues can be durable, meaning the messages they contain survive a server crash or + restart, as long as the messages in them are durable. Non durable queues do not + survive a server restart or crash even if the messages they contain are + durable. + Queues can also be temporary, meaning they are automatically deleted when the + client connection is closed, if they are not explicitly deleted before that. + Queues can be bound with an optional filter expression. If a filter expression is + supplied then the server will only route messages that match that filter expression + to any queues bound to the address. + Many queues can be bound to a single address. A particular queue is only bound to + a maximum of one address. +
+
+ ServerLocator + Clients use ServerLocator instances to create ClientSessionFactory instances. ServerLocator + instances are used to locate servers and create connections to them. + In JMS terms think of a ServerLocator in the same way you would + a JMS Connection Factory. + ServerLocator instances are created using the HornetQClient factory class. +
+
+ ClientSessionFactory + Clients use ClientSessionFactory instances to create ClientSession instances. ClientSessionFactory + instances are basically the connection to a server + In JMS terms think of them as JMS Connections. + ClientSessionFactory instances are created using the ServerLocator class. +
+
+ ClientSession + A client uses a ClientSession for consuming and producing messages and for + grouping them in transactions. ClientSession instances can support both + transactional and non transactional semantics and also provide an XAResource interface so messaging operations can be performed as part + of a JTA + transaction. + ClientSession instances group ClientConsumers and ClientProducers. + ClientSession instances can be registered with an optional SendAcknowledgementHandler. This allows your client code to be + notified asynchronously when sent messages have successfully reached the server. + This unique HornetQ feature, allows you to have full guarantees that sent messages + have reached the server without having to block on each message sent until a + response is received. Blocking on each messages sent is costly since it requires a + network round trip for each message sent. By not blocking and receiving send + acknowledgements asynchronously you can create true end to end asynchronous systems + which is not possible using the standard JMS API. For more information on this + advanced feature please see the section . +
+
+ ClientConsumer + Clients use ClientConsumer instances to consume messages from a + queue. Core Messaging supports both synchronous and asynchronous message consumption + semantics. ClientConsumer instances can be configured with an + optional filter expression and will only consume messages which match that + expression. +
+
+ ClientProducer + Clients create ClientProducer instances on ClientSession instances so they can send messages. ClientProducer + instances can specify an address to which all sent messages are routed, or they can + have no specified address, and the address is specified at send time for the + message. +
+ + Please note that ClientSession, ClientProducer and ClientConsumer instances are + designed to be re-used. + It's an anti-pattern to create new ClientSession, ClientProducer and + ClientConsumer instances for each message you produce or consume. If you do this, + your application will perform very poorly. This is discussed further in the section + on performance tuning . + +
+
+ A simple example of using Core + Here's a very simple program using the core messaging API to send and receive a + message: + +ServerLocator locator = HornetQClient.createServerLocatorWithoutHA(new TransportConfiguration( + InVMConnectorFactory.class.getName())); + +ClientSessionFactory factory = locator.createClientSessionFactory(); + +ClientSession session = factory.createSession(); + +session.createQueue("example", "example", true); + +ClientProducer producer = session.createProducer("example"); + +ClientMessage message = session.createMessage(true); + +message.getBodyBuffer().writeString("Hello"); + +producer.send(message); + +session.start(); + +ClientConsumer consumer = session.createConsumer("example"); + +ClientMessage msgReceived = consumer.receive(); + +System.out.println("message = " + msgReceived.getBodyBuffer().readString()); + +session.close(); +
+
diff --git a/docs/user-manual/en/using-jms.xml b/docs/user-manual/en/using-jms.xml new file mode 100644 index 0000000000..aaecf62594 --- /dev/null +++ b/docs/user-manual/en/using-jms.xml @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Using JMS + Although HornetQ provides a JMS agnostic messaging API, many users will be more + comfortable using JMS. + JMS is a very popular API standard for messaging, and most messaging systems provide a JMS + API. If you are completely new to JMS we suggest you follow the Sun + JMS tutorial - a full JMS tutorial is out of scope for this guide. + HornetQ also ships with a wide range of examples, many of which demonstrate JMS API usage. + A good place to start would be to play around with the simple JMS Queue and Topic example, + but we also provide examples for many other parts of the JMS API. A full description of the + examples is available in . + In this section we'll go through the main steps in configuring the server for JMS and + creating a simple JMS program. We'll also show how to configure and use JNDI, and also how + to use JMS with HornetQ without using any JNDI. +
+ A simple ordering system + For this chapter we're going to use a very simple ordering system as our example. It is + a somewhat contrived example because of its extreme simplicity, but it serves to + demonstrate the very basics of setting up and using JMS. + We will have a single JMS Queue called OrderQueue, and we will have + a single MessageProducer sending an order message to the queue and a + single MessageConsumer consuming the order message from the + queue. + The queue will be a durable queue, i.e. it will survive a server + restart or crash. We also want to pre-deploy the queue, i.e. specify the queue in the + server JMS configuration so it is created automatically without us having to explicitly + create it from the client. +
+
+ JMS Server Configuration + The file hornetq-jms.xml on the server classpath contains any JMS + Queue, Topic and ConnectionFactory instances that we wish to create and make available + to lookup via the JNDI. + A JMS ConnectionFactory object is used by the client to make connections to the + server. It knows the location of the server it is connecting to, as well as many other + configuration parameters. In most cases the defaults will be acceptable. + We'll deploy a single JMS Queue and a single JMS Connection Factory instance on the + server for this example but there are no limits to the number of Queues, Topics and + Connection Factory instances you can deploy from the file. Here's our + configuration: + +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq ../schemas/hornetq-jms.xsd "> + + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + </connection-factory> + + <queue name="OrderQueue"> + <entry name="queues/OrderQueue"/> + </queue> +</configuration> + We deploy one ConnectionFactory called ConnectionFactory and bind + it in just one place in JNDI as given by the entry element. + ConnectionFactory instances can be bound in many places in JNDI if you require. + + The JMS connection factory references a connector called + netty. This is a reference to a connector object deployed in + the main core configuration file hornetq-configuration.xml which + defines the transport and parameters used to actually connect to the server. + +
+
+ Connection Factory Types + The JMS API doc provides several connection factories for applications. HornetQ JMS users + can choose to configure the types for their connection factories. Each connection factory + has a signature attribute and a xa parameter, the + combination of which determines the type of the factory. Attribute signature + has three possible string values, i.e. generic, + queue and topic; xa is a boolean + type parameter. The following table gives their configuration values for different + connection factory interfaces. + + Configuration for Connection Factory Types + + + + + + + signature + xa + Connection Factory Type + + + + + generic (default) + false (default) + javax.jms.ConnectionFactory + + + generic + true + javax.jms.XAConnectionFactory + + + queue + false + javax.jms.QueueConnectionFactory + + + queue + true + javax.jms.XAQueueConnectionFactory + + + topic + false + javax.jms.TopicConnectionFactory + + + topic + true + javax.jms.XATopicConnectionFactory + + + +
+ As an example, the following configures an XAQueueConnectionFactory: + +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq ../schemas/hornetq-jms.xsd "> + + <connection-factory name="ConnectionFactory" signature="queue"> + <xa>true</xa> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + </connection-factory> +</configuration> + +
+
+ JNDI configuration + When using JNDI from the client side you need to specify a set of JNDI properties + which tell the JNDI client where to locate the JNDI server, amongst other things. These + are often specified in a file called jndi.properties on the client + classpath, or you can specify them directly when creating the JNDI initial context. A + full JNDI tutorial is outside the scope of this document, please see the Sun JNDI tutorial + for more information on how to use JNDI. + For talking to the JBoss JNDI Server, the jndi properties will look something like + this: + +java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.provider.url=jnp://myhost:1099 +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces + Where myhost is the hostname or IP address of the JNDI server. 1099 + is the port used by the JNDI server and may vary depending on how you have configured + your JNDI server. + In the default standalone configuration, JNDI server ports are configured in the file + hornetq-beans.xml by setting properties on the JNDIServer bean: + +<bean name="StandaloneServer" class="org.hornetq.jms.server.impl.StandaloneNamingServer"> + <constructor> + <parameter> + <inject bean="HornetQServer"/> + </parameter> + </constructor> + <property name="port">${jnp.port:1099}</property> + <property name="bindAddress">${jnp.host:localhost}</property> + <property name="rmiPort">${jnp.rmiPort:1098}</property> + <property name="rmiBindAddress">${jnp.host:localhost}</property> +</bean> + + If you want your JNDI server to be available to non local clients make sure you + change its bind address to something other than localhost! + + + The JNDIServer bean must be defined only when HornetQ is running in + stand-alone mode. When HornetQ is integrated to JBoss Application + Server, JBoss AS will provide a ready-to-use JNDI server without any additional + configuration. + +
+
+ The code + Here's the code for the example: + First we'll create a JNDI initial context from which to lookup our JMS objects: + InitialContext ic = new InitialContext(); + Now we'll look up the connection factory: + ConnectionFactory cf = (ConnectionFactory)ic.lookup("/ConnectionFactory"); + And look up the Queue: + Queue orderQueue = (Queue)ic.lookup("/queues/OrderQueue"); + Next we create a JMS connection using the connection factory: + Connection connection = cf.createConnection(); + And we create a non transacted JMS Session, with AUTO_ACKNOWLEDGE acknowledge + mode: + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + We create a MessageProducer that will send orders to the queue: + MessageProducer producer = session.createProducer(orderQueue); + And we create a MessageConsumer which will consume orders from the queue: + MessageConsumer consumer = session.createConsumer(orderQueue); + We make sure we start the connection, or delivery won't occur on it: + connection.start(); + We create a simple TextMessage and send it: + TextMessage message = session.createTextMessage("This is an order"); +producer.send(message); + And we consume the message: + TextMessage receivedMessage = (TextMessage)consumer.receive(); +System.out.println("Got order: " + receivedMessage.getText()); + It is as simple as that. For a wide range of working JMS examples please see the + examples directory in the distribution. + + Please note that JMS connections, sessions, producers and consumers are + designed to be re-used. + It is an anti-pattern to create new connections, sessions, producers and consumers + for each message you produce or consume. If you do this, your application will + perform very poorly. This is discussed further in the section on performance tuning + . + +
+
+ Directly instantiating JMS Resources without using JNDI + Although it is a very common JMS usage pattern to lookup JMS Administered + Objects (that's JMS Queue, Topic and ConnectionFactory instances) from + JNDI, in some cases a JNDI server is not available and you still want to use JMS, or you + just think "Why do I need JNDI? Why can't I just instantiate these objects + directly?" + With HornetQ you can do exactly that. HornetQ supports the direct instantiation of JMS + Queue, Topic and ConnectionFactory instances, so you don't have to use JNDI at + all. + For a full working example of direct instantiation please see the JMS examples in + . + Here's our simple example, rewritten to not use JNDI at all: + We create the JMS ConnectionFactory object via the HornetQJMSClient Utility class, + note we need to provide connection parameters and specify which transport we are using, + for more information on connectors please see . + +TransportConfiguration transportConfiguration = new TransportConfiguration(NettyConnectorFactory.class.getName()); +ConnectionFactory cf = HornetQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF,transportConfiguration); + We also create the JMS Queue object via the HornetQJMSClient Utility class: + Queue orderQueue = HornetQJMSClient.createQueue("OrderQueue"); + Next we create a JMS connection using the connection factory: + Connection connection = cf.createConnection(); + And we create a non transacted JMS Session, with AUTO_ACKNOWLEDGE acknowledge + mode: + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + We create a MessageProducer that will send orders to the queue: + MessageProducer producer = session.createProducer(orderQueue); + And we create a MessageConsumer which will consume orders from the queue: + MessageConsumer consumer = session.createConsumer(orderQueue); + We make sure we start the connection, or delivery won't occur on it: + connection.start(); + We create a simple TextMessage and send it: + TextMessage message = session.createTextMessage("This is an order"); +producer.send(message); + And we consume the message: + TextMessage receivedMessage = (TextMessage)consumer.receive(); +System.out.println("Got order: " + receivedMessage.getText()); +
+
+ Setting The Client ID + This represents the client id for a JMS client and is needed for creating durable + subscriptions. It is possible to configure this on the connection factory and can be set + via the client-id element. Any connection created by this connection + factory will have this set as its client id. +
+
+ Setting The Batch Size for DUPS_OK + When the JMS acknowledge mode is set to DUPS_OK it is possible to + configure the consumer so that it sends acknowledgements in batches rather that one at a + time, saving valuable bandwidth. This can be configured via the connection factory via + the dups-ok-batch-size element and is set in bytes. The default is + 1024 * 1024 bytes = 1 MiB. +
+
+ Setting The Transaction Batch Size + When receiving messages in a transaction it is possible to configure the consumer to + send acknowledgements in batches rather than individually saving valuable bandwidth. + This can be configured on the connection factory via the transaction-batch-size element and is set in bytes. The default is 1024 * + 1024. +
+
diff --git a/docs/user-manual/en/using-server.xml b/docs/user-manual/en/using-server.xml new file mode 100644 index 0000000000..c5f12657f7 --- /dev/null +++ b/docs/user-manual/en/using-server.xml @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + Using the Server + This chapter will familiarise you with how to use the HornetQ server. + We'll show where it is, how to start and stop it, and we'll describe the directory layout + and what all the files are and what they do. + For the remainder of this chapter when we talk about the HornetQ server we mean the + HornetQ standalone server, in its default configuration with a JMS Service and JNDI service + enabled. + When running embedded in JBoss Application Server the layout may be slightly different but + by-and-large will be the same. +
+ Starting and Stopping the standalone server + In the distribution you will find a directory called bin. + cd into that directory and you will find a Unix/Linux script called + run.sh and a windows batch file called run.bat + To run on Unix/Linux type ./run.sh + To run on Windows type run.bat + These scripts are very simple and basically just set-up the classpath and some JVM + parameters and start the JBoss Microcontainer. The Microcontainer is a light weight + container used to deploy the HornetQ POJO's + To stop the server you will also find a Unix/Linux script stop.sh and + a windows batch file stop.bat + To run on Unix/Linux type ./stop.sh + To run on Windows type stop.bat + Please note that HornetQ requires a Java 6 or later runtime to run. + Both the run and the stop scripts use the config under config/stand-alone/non-clustered by default. The configuration can be + changed by running ./run.sh ../config/stand-alone/clustered or + another config of your choosing. This is the same for the stop script and the windows + bat files. +
+
+ Server JVM settings + The run scripts run.sh and run.bat set some JVM + settings for tuning running on Java 6 and choosing the garbage collection policy. We + recommend using a parallel garbage collection algorithm to smooth out latency and + minimise large GC pauses. + By default HornetQ runs in a maximum of 1GiB of RAM. To increase the memory settings + change the -Xms and -Xmx memory settings as you + would for any Java program. + If you wish to add any more JVM arguments or tune the existing ones, the run scripts + are the place to do it. +
+
+ Server classpath + HornetQ looks for its configuration files on the Java classpath. + The scripts run.sh and run.bat specify the + classpath when calling Java to run the server. + In the distribution, the run scripts will add the non clustered configuration + directory to the classpath. This is a directory which contains a set of configuration + files for running the HornetQ server in a basic non-clustered configuration. In the + distribution this directory is config/stand-alone/non-clustered/ from + the root of the distribution. + The distribution contains several standard configuration sets for running: + + + Non clustered stand-alone. + + + Clustered stand-alone + + + Non clustered in JBoss Application Server + + + Clustered in JBoss Application Server + + + You can of course create your own configuration and specify any configuration + directory when running the run script. + Just make sure the directory is on the classpath and HornetQ will search there when + starting up. +
+
+ Library Path + If you're using the Asynchronous IO Journal on + Linux, you need to specify java.library.path as a property on your + Java options. This is done automatically in the run.sh script. + If you don't specify java.library.path at your Java options then + the JVM will use the environment variable LD_LIBRARY_PATH. +
+
+ System properties + HornetQ can take a system property on the command line for configuring logging. + For more information on configuring logging, please see . +
+
+ Configuration files + The configuration directory is specified on the classpath in the run scripts run.sh and run.bat This directory can contain the + following files. + + + hornetq-beans.xml (or hornetq-jboss-beans.xml if you're running inside JBoss + Application Server). This is the JBoss Microcontainer beans file which defines + what beans the Microcontainer should create and what dependencies to enforce + between them. Remember that HornetQ is just a set of POJOs. In the stand-alone + server, it's the JBoss Microcontainer which instantiates these POJOs and + enforces dependencies between them and other beans. + + + hornetq-configuration.xml. This is the main HornetQ + configuration file. All the parameters in this file are described in . Please see for more information on this file. + + + hornetq-queues.xml. This file contains predefined queues, + queue settings and security settings. The file is optional - all this + configuration can also live in hornetq-configuration.xml. In + fact, the default configuration sets do not have a hornetq-queues.xml file. The purpose of allowing queues to be + configured in these files is to allow you to manage your queue configuration + over many files instead of being forced to maintain it in a single file. There + can be many hornetq-queues.xml files on the classpath. All + will be loaded if found. + + + hornetq-users.xml HornetQ ships with a basic security + manager implementation which obtains user credentials from the hornetq-users.xml file. This file contains user, password and + role information. For more information on security, please see . + + + hornetq-jms.xml The distro configuration by default + includes a server side JMS service which mainly deploys JMS Queues, Topics and + ConnectionFactorys from this file into JNDI. If you're not using JMS, or you + don't need to deploy JMS objects on the server side, then you don't need this + file. For more information on using JMS, please see . + + + logging.properties This is used to configure the logging + handlers used by the Java logger. For more information on configuring logging, + please see . + + + + The property file-deployment-enabled in the hornetq-configuration.xml configuration when set to false means that + the other configuration files are not loaded. This is true by default. + + It is also possible to use system property substitution in all the configuration + files. by replacing a value with the name of a system property. Here is an example of + this with a connector configuration: + +<connector name="netty"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class> + <param key="host" value="${hornetq.remoting.netty.host:localhost}"/> + <param key="port" value="${hornetq.remoting.netty.port:5445}"/> +</connector> + Here you can see we have replaced 2 values with system properties hornetq.remoting.netty.host and hornetq.remoting.netty.port. These values will be replaced by the value + found in the system property if there is one, if not they default back to localhost or + 5445 respectively. It is also possible to not supply a default. i.e. ${hornetq.remoting.netty.host}, however the system property + must be supplied in that case. +
+
+ JBoss Microcontainer Beans File + The stand-alone server is basically a set of POJOs which are instantiated by the light + weight JBoss Microcontainer + engine. + + A beans file is also needed when the server is deployed in the JBoss Application + Server but this will deploy a slightly different set of objects since the + Application Server will already have things like security etc deployed. + + Let's take a look at an example beans file from the stand-alone server: + + +<?xml version="1.0" encoding="UTF-8"?> + +<deployment xmlns="urn:jboss:bean-deployer:2.0"> + + <!-- MBean server --> + <bean name="MBeanServer" class="javax.management.MBeanServer"> + <constructor factoryClass="java.lang.management.ManagementFactory" + factoryMethod="getPlatformMBeanServer"/> + </bean> + + <!-- The core configuration --> + <bean name="Configuration" class="org.hornetq.core.config.impl.FileConfiguration"> + </bean> + + <!-- The security manager --> + <bean name="HornetQSecurityManager" class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl"> + <start ignored="true"/> + <stop ignored="true"/> + </bean> + + <!-- The core server --> + <bean name="HornetQServer" class="org.hornetq.core.server.impl.HornetQServerImpl"> + <constructor> + <parameter> + <inject bean="Configuration"/> + </parameter> + <parameter> + <inject bean="MBeanServer"/> + </parameter> + <parameter> + <inject bean="HornetQSecurityManager"/> + </parameter> + </constructor> + <start ignored="true"/> + <stop ignored="true"/> + </bean> + + <!-- The Stand alone server that controls the jndi server--> + <bean name="StandaloneServer" class="org.hornetq.jms.server.impl.StandaloneNamingServer"> + <constructor> + <parameter> + <inject bean="HornetQServer"/> + </parameter> + </constructor> + <property name="port">${jnp.port:1099}</property> + <property name="bindAddress">${jnp.host:localhost}</property> + <property name="rmiPort">${jnp.rmiPort:1098}</property> + <property name="rmiBindAddress">${jnp.host:localhost}</property> + </bean> + + <!-- The JMS server --> + <bean name="JMSServerManager" class="org.hornetq.jms.server.impl.JMSServerManagerImpl"> + <constructor> + <parameter> + <inject bean="HornetQServer"/> + </parameter> + </constructor> + </bean> + + +</deployment> + + We can see that, as well as the core HornetQ server, the stand-alone server + instantiates various different POJOs, let's look at them in turn: + + + MBeanServer + In order to provide a JMX management interface a JMS MBean server is necessary + in which to register the management objects. Normally this is just the default + platform MBean server available in the JVM instance. If you don't want to + provide a JMX management interface this can be commented out or removed. + + + Configuration + The HornetQ server is configured with a Configuration object. In the default + stand-alone set-up it uses a FileConfiguration object which knows to read + configuration information from the file system. In different configurations such + as embedded you might want to provide configuration information from somewhere + else. + + + Security Manager. The security manager used by the messaging server is + pluggable. The default one used just reads user-role information from the + hornetq-users.xml file on disk. However it can be + replaced by a JAAS security manager, or when running inside JBoss Application + Server it can be configured to use the JBoss AS security manager for tight + integration with JBoss AS security. If you've disabled security altogether you + can remove this too. + + + HornetQServer + This is the core server. It's where 99% of the magic happens + + + StandaloneServer + Many clients like to look up JMS Objects from JNDI so we provide a JNDI server + for them to do that. This class is a wrapper around the JBoss naming server. + If you don't need JNDI this can be commented out or removed. + + + JMSServerManager + This deploys any JMS Objects such as JMS Queues, Topics and ConnectionFactory + instances from hornetq-jms.xml files on the disk. It also + provides a simple management API for manipulating JMS Objects. On the whole it + just translates and delegates its work to the core server. If you don't need to + deploy JMS Queues, Topics and ConnectionFactorys from server side configuration + and don't require the JMS management interface this can be disabled. + + +
+
+ JBoss AS4 MBean Service. + + The section is only to configure HornetQ on JBoss AS4. The service functionality is + similar to Microcontainer Beans + + + +<?xml version="1.0" encoding="UTF-8"?> +<server> + <mbean code="org.hornetq.service.HornetQFileConfigurationService" + name="org.hornetq:service=HornetQFileConfigurationService"> + </mbean> + + <mbean code="org.hornetq.service.JBossASSecurityManagerService" + name="org.hornetq:service=JBossASSecurityManagerService"> + </mbean> + + <mbean code="org.hornetq.service.HornetQStarterService" + name="org.hornetq:service=HornetQStarterService"> + <!--let's let the JMS Server start us--> + <attribute name="Start">false</attribute> + + <depends optional-attribute-name="SecurityManagerService" + proxy-type="attribute">org.hornetq:service=JBossASSecurityManagerService</depends> + <depends optional-attribute-name="ConfigurationService" + proxy-type="attribute">org.hornetq:service=HornetQFileConfigurationService</depends> + </mbean> + + <mbean code="org.hornetq.service.HornetQJMSStarterService" + name="org.hornetq:service=HornetQJMSStarterService"> + <depends optional-attribute-name="HornetQServer" + proxy-type="attribute">org.hornetq:service=HornetQStarterService</depends> + </mbean> +</server> + + This jboss-service.xml configuration file is included inside the hornetq-service.sar + on AS4 with embedded HornetQ. As you can see, on this configuration file we are starting + various services: + + + HornetQFileConfigurationService + This is an MBean Service that takes care of the life cycle of the FileConfiguration POJO + + + JBossASSecurityManagerService + This is an MBean Service that takes care of the lifecycle of the JBossASSecurityManager POJO + + + HornetQStarterService + This is an MBean Service that controls the main HornetQServer POJO. + this has a dependency on JBossASSecurityManagerService and HornetQFileConfigurationService MBeans + + + HornetQJMSStarterService + This is an MBean Service that controls the JMSServerManagerImpl POJO. + If you aren't using jms this can be removed. + + + JMSServerManager + Has the responsibility to start the JMSServerManager and the same behaviour that JMSServerManager Bean + + +
+
+ The main configuration file. + The configuration for the HornetQ core server is contained in hornetq-configuration.xml. This is what the FileConfiguration bean uses + to configure the messaging server. + There are many attributes which you can configure HornetQ. In most cases the defaults + will do fine, in fact every attribute can be defaulted which means a file with a single + empty configuration element is a valid configuration file. The + different configuration will be explained throughout the manual or you can refer to the + configuration reference here. +
+
diff --git a/docs/user-manual/en/vertx-integration.xml b/docs/user-manual/en/vertx-integration.xml new file mode 100644 index 0000000000..71bb11023a --- /dev/null +++ b/docs/user-manual/en/vertx-integration.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + %BOOK_ENTITIES; + ]> + + Vert.x Integration + Vert.x is a lightweight, high performance application platform for the + JVM that's designed for modern mobile, web, and enterprise applications. Vert.x provides a distributed event bus that + allows messages to be sent across vert.x instances and clients. You can now redirect and persist any vert.x messages + to HornetQ and route those messages to a specified vertx address by configuring HornetQ vertx incoming and outgoing + vertx connector services. + + +
+ Configuring a Vertx Incoming Connector Service + Vertx Incoming Connector services receive messages from vertx event bus and route them to a HornetQ queue. + Such a service can be configured as follows: + + <connector-service name="vertx-incoming-connector"> + <factory-class>org.hornetq.integration.vertx.VertxIncomingConnectorServiceFactory</factory-class> + <param key="host" value="127.0.0.1"/> + <param key="port" value="0"/> + <param key="queue" value="jms.queue.vertxQueue"/> + <param key="vertx-address" value="vertx.in.eventaddress"/> + </connector-service> + + Shown are the required params for the connector service: + + + queue. The name of the HornetQ queue to send message to. + + + As well as these required paramaters there are the following optional parameters + + + host. The host name on which the vertx target container is running. Default is localhost. + + + port. The port number to which the target vertx listens. Default is zero. + + + quorum-size. The quorum size of the target vertx instance. + + + ha-group. The name of the ha-group of target vertx instance. Default is hornetq. + + + vertx-address. The vertx address to listen to. default is org.hornetq. + + +
+ +
+ Configuring a Vertx Outgoing Connector Service + Vertx Outgoing Connector services fetch vertx messages from a HornetQ queue and put them to vertx event bus. + Such a service can be configured as follows: + + <connector-service name="vertx-outgoing-connector"> + <factory-class>org.hornetq.integration.vertx.VertxOutgoingConnectorServiceFactory</factory-class> + <param key="host" value="127.0.0.1"/> + <param key="port" value="0"/> + <param key="queue" value="jms.queue.vertxQueue"/> + <param key="vertx-address" value="vertx.out.eventaddress"/> + <param key="publish" value="true"/> + </connector-service> + + Shown are the required params for the connector service: + + + queue. The name of the HornetQ queue to fetch message from. + + + As well as these required paramaters there are the following optional parameters + + + host. The host name on which the vertx target container is running. Default is localhost. + + + port. The port number to which the target vertx listens. Default is zero. + + + quorum-size. The quorum size of the target vertx instance. + + + ha-group. The name of the ha-group of target vertx instance. Default is hornetq. + + + vertx-address. The vertx address to put messages to. default is org.hornetq. + + + publish. How messages is sent to vertx event bus. "true" means using publish style. + "false" means using send style. Default is false. + + +
+
diff --git a/docs/user-manual/en/wildcard-routing.xml b/docs/user-manual/en/wildcard-routing.xml new file mode 100644 index 0000000000..44f0f75953 --- /dev/null +++ b/docs/user-manual/en/wildcard-routing.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + + Routing Messages With Wild Cards + HornetQ allows the routing of messages via wildcard addresses. + If a queue is created with an address of say queue.news.# then it + will receive any messages sent to addresses that match this, for instance queue.news.europe or queue.news.usa or queue.news.usa.sport. If you create a consumer on this queue, this allows a consumer to consume messages which are + sent to a hierarchy of addresses. + + In JMS terminology this allows "topic hierarchies" to be created. + + To enable this functionality set the property wild-card-routing-enabled + in the hornetq-configuration.xml file to true. This is + true by default. + For more information on the wild card syntax take a look at chapter, also see . + diff --git a/docs/user-manual/en/wildcard-syntax.xml b/docs/user-manual/en/wildcard-syntax.xml new file mode 100644 index 0000000000..b121eb5531 --- /dev/null +++ b/docs/user-manual/en/wildcard-syntax.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + +%BOOK_ENTITIES; +]> + + + Understanding the HornetQ Wildcard Syntax + HornetQ uses a specific syntax for representing wildcards in security settings, + address settings and when creating consumers. + The syntax is similar to that used by AMQP. + A HornetQ wildcard expression contains words delimited by the character '.' (full stop). + The special characters '#' and '*' also have special + meaning and can take the place of a word. + The character '#' means 'match any sequence of zero or more + words'. + The character '*' means 'match a single word'. + So the wildcard 'news.europe.#' would match 'news.europe', 'news.europe.sport', + 'news.europe.politics', and 'news.europe.politics.regional' but would not match 'news.usa', + 'news.usa.sport' nor 'entertainment'. + The wildcard 'news.*' would match 'news.europe', but not 'news.europe.sport'. + The wildcard 'news.*.sport' would match 'news.europe.sport' and also 'news.usa.sport', but + not 'news.europe.politics'. + diff --git a/docs/user-manual/pom.xml b/docs/user-manual/pom.xml new file mode 100644 index 0000000000..549f6487f3 --- /dev/null +++ b/docs/user-manual/pom.xml @@ -0,0 +1,361 @@ + + + + + + 4.0.0 + + + org.hornetq.docs + hornetq-docs + 2.5.0-SNAPSHOT + + + org.hornetq.docs + user-manual + 1.0 + jdocbook + user-manual + + + en + HornetQ_User_Manual + HornetQ User Manual + + + + + jboss-public-repository-group + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + default + + true + never + + + true + never + + + + + + jboss-public-repository-group + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + default + + true + + + true + + + + + + + + + all + + true + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.3.5 + true + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${docname}.pdf + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + html_single + classpath:/xslt/org/jboss/xhtml-single.xsl + index.html + + + + + + + + + + + html + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + + + + + + + + + html-single + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + + + + + pdf + + false + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${docname}.pdf + + + + + + + + + + + + + + org.jboss.maven.plugins + maven-jdocbook-plugin + 2.2.1 + true + + + org.jboss.pressgang + pressgang-xslt + 2.0.2 + + + org.jboss + jbossorg-jdocbook-style + 1.1.1 + jdocbook-style + + + + ${project.basedir} + ${docname}.xml + en + + ${project.basedir}/en + + images/*.png + images/*.jpg + + + + + pdf + classpath:/xslt/org/jboss/pdf.xsl + ${pdf.name} + + + html + classpath:/xslt/org/jboss/xhtml.xsl + index.html + + + html_single + classpath:/xslt/org/jboss/xhtml-single.xsl + index.html + + + + true + saxon + 1.72.0 + - + false + + + javax.xml.parsers.DocumentBuilderFactory + org.apache.xerces.jaxp.DocumentBuilderFactoryImpl + + + javax.xml.parsers.SAXParserFactory + org.apache.xerces.jaxp.SAXParserFactoryImpl + + + + + + + + + + org.codehaus.mojo + xml-maven-plugin + + + + transform + + + + + net.sf.saxon.TransformerFactoryImpl + + + ../../hornetq-server/src/main/resources/schema + ./src/main/resources/schemaToTable.xsl + + hornetq-configuration.xsd + + + + .xml + + + + + ../../hornetq-jms-server/src/main/resources/schema + ./src/main/resources/schemaToTable.xsl + + hornetq-jms.xsd + + + + .xml + + + + + + + + net.sf.saxon + saxon + 8.7 + + + + + + + + diff --git a/docs/user-manual/publican.cfg b/docs/user-manual/publican.cfg new file mode 100644 index 0000000000..821b3484ee --- /dev/null +++ b/docs/user-manual/publican.cfg @@ -0,0 +1,7 @@ +# Config::Simple 4.59 +# Tue Mar 29 06:11:07 2011 + +xml_lang: en +type: Book +brand: common + diff --git a/docs/user-manual/src/main/resources/schemaToTable.xsl b/docs/user-manual/src/main/resources/schemaToTable.xsl new file mode 100644 index 0000000000..1f5dedabaa --- /dev/null +++ b/docs/user-manual/src/main/resources/schemaToTable.xsl @@ -0,0 +1,374 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + THIS IS A GENERATED FILE. DO NOT EDIT IT DIRECTLY! + + HornetQ options reference table generated from: + + + ======================================================================= + + XSLT Version = + XSLT Vendor = + XSLT Vendor URL = + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + VALUE OF COMPLEX TYPE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Complex element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ( + + required + + attribute) + + + + + + + + + + + + + + + ELEMENT TEMPLATE name= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + E.NAME-ref name= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ELEMENT TYPE-ref TEMPLATE CHILDREN + + + + + + + + + + + + ELEMENT REF TEMPLATE ref= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/user-manual/user-manual.xpr b/docs/user-manual/user-manual.xpr new file mode 100644 index 0000000000..2f3e5ddfbd --- /dev/null +++ b/docs/user-manual/user-manual.xpr @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/user-manual/zh/appserver-integration.xml b/docs/user-manual/zh/appserver-integration.xml new file mode 100644 index 0000000000..a77e810be8 --- /dev/null +++ b/docs/user-manual/zh/appserver-integration.xml @@ -0,0 +1,1001 @@ + + + + + + + + + + + + + + + + + + + + Java EE和应用服务器的集成 + HornetQ可以容易地安装到JBoss 4应用服务器及其以上版本。有关安装的详细说明请参阅快速指南。 + HornetQ提供了一个JCA适配器,使得它还可以与其它JEE兼容的应用服务器集成。请参阅其它应用服务器的 + 有关JCA适配器集成的说明来操作。 + JCA适配器的作用是控制消息流入到消息Bean(MDB),并控制消息从各种JEE模块中发出(如EJB和Servlet)。 + 本章讲述这些JEE模块配置HornetQ的基本信息。 +
+ 配置消息Bean + 使用HornetQ向MDB传递消息,需要在文件ra.xml中配置JCA适配器。该文件在 + jms-ra.rar文件中。默认配置下HornetQ服务使用InVm连接器接收消息。在本章 + 后面列出了可配置的选项。 + 所有MDB都需要有目标类型和目标的相关配置。下面就是一个使用annotation配置MDB的例子: + @MessageDriven(name = "MDBExample", + activationConfig = + { + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue") + }) +@ResourceAdapter("hornetq-ra.rar") +public class MDBExample implements MessageListener +{ + public void onMessage(Message message)... +} + 上例中配置了MDB从一个队列中接收消息,它的JNDI绑定名为queue/testQueue。 + 这个队列必须事先在HornetQ服务器配置文件中配置并部署好的。 + ResourceAdapter annotation用来指出使用哪个适配器。要使用它必须要引入 + org.jboss.ejb3.annotation.ResourceAdapter (JBoss AS 5.x或以上)。 + 这个类在 + jboss-ejb3-ext-api.jar文件中。该文件可以在JBoss的repository中找到。 + 另外一个方法是使用部署描述文件(deployment descriptor),即在文件jboss.xml中加入类似以下的内容: +<message-driven> + <ejb-name>ExampleMDB</ejb-name> + <resource-adapter-name>hornetq-ra.rar</resource-adapter-name> +</message-driven> +你还可以将hornetq-ra.rar改名为jms-ra.rar而不需要任何annotation或额外的部署描述信息。但是你需要 + 编辑jms-ds.xml文件,将其中的rar-name项改成相应的值。 + + HornetQ是JBoss AS 6默认的JMS提供者。从这个版本开始HornetQ的资源适配器名字是 + jms-ra.rar,并且你不需要在MDB的annotation中指定它。 + + HornetQ发布包中的所有例子都使用annotation方法。 +
+ 使用容器管理事务(CMT) + 当MDB使用容器管理事务时,消息的传递被包含在一个JTA事务中。事务的提交与回滚是由容器来控制的。如果事务 + 被回滚,消息传递会进行相应的处理(默认是重新传递消息,如果重新传递次数超过10次,消息就被发往DLQ)。使用 + annotation配置如下: + @MessageDriven(name = "MDB_CMP_TxRequiredExample", + activationConfig = + { + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue") + }) +@TransactionManagement(value= TransactionManagementType.CONTAINER) +@TransactionAttribute(value= TransactionAttributeType.REQUIRED) +@ResourceAdapter("hornetq-ra.rar") +public class MDB_CMP_TxRequiredExample implements MessageListener +{ + public void onMessage(Message message)... +} + TransactionManagement 表示这个MDB使用容器管理持久性。 + TransactionAttribute 表示这个MDB要求JTA事务。注意这个annotation的 + 另外唯一的合法值是TransactionAttributeType.NOT_SUPPORTED,它表示 + MDB不需要JTA事务支持。 + 如果要回滚事务,可以调用MessageDrivenContext的 + setRollbackOnly方法。如下面的代码所示: + @Resource + MessageDrivenContextContext ctx; + + public void onMessage(Message message) + { + try + { + //something here fails + } + catch (Exception e) + { + ctx.setRollbackOnly(); + } + } + 如果你不需要使用XA事务,你可以用一相本地的事务来代替(比如你只有一个JMS资源)。 + 如下所示: + @MessageDriven(name = "MDB_CMP_TxLocalExample", + activationConfig = + { + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"), + @ActivationConfigProperty(propertyName = "useLocalTx", propertyValue = "true") + }) +@TransactionManagement(value = TransactionManagementType.CONTAINER) +@TransactionAttribute(value = TransactionAttributeType.NOT_SUPPORTED) +@ResourceAdapter("hornetq-ra.rar") +public class MDB_CMP_TxLocalExample implements MessageListener +{ + public void onMessage(Message message)... +} +
+
+ 使用Bean管理事务(BMT) + 消息Bean可以通过配置使用Bean管理的事务(BMT)。在种情况下会创建一个用户事务 + (User Transaction)。如下所示: + @MessageDriven(name = "MDB_BMPExample", + activationConfig = + { + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"), + @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Dups-ok-acknowledge") + }) +@TransactionManagement(value= TransactionManagementType.BEAN) +@ResourceAdapter("hornetq-ra.rar") +public class MDB_BMPExample implements MessageListener +{ + public void onMessage(Message message) +} + 使用BMT时,消息的传递在用户事务的范围之外,它的通知模式由acknowledgeMode参数决定。 + 该参数有两个合法的值,即Auto-acknowledgeDups-ok-acknowledge。请注意,由于消息的传递在事务之外,在MDB中如果发生错误消息 + 是不会重新传递的。 + 用户可以像如下所示控制事务的生命周期: + @Resource + MessageDrivenContext ctx; + + public void onMessage(Message message) + { + UserTransaction tx; + try + { + TextMessage textMessage = (TextMessage)message; + + String text = textMessage.getText(); + + UserTransaction tx = ctx.getUserTransaction(); + + tx.begin(); + + //do some stuff within the transaction + + tx.commit(); + + } + catch (Exception e) + { + tx.rollback(); + } + } +
+
+ 在MDB中使用选择器 + MDB可以配置消息选择器。如下所示: + @MessageDriven(name = "MDBMessageSelectorExample", + activationConfig = + { + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"), + @ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "color = 'RED'") + }) +@TransactionManagement(value= TransactionManagementType.CONTAINER) +@TransactionAttribute(value= TransactionAttributeType.REQUIRED) +@ResourceAdapter("hornetq-ra.rar") +public class MDBMessageSelectorExample implements MessageListener +{ + public void onMessage(Message message).... +} +
+
+
+ 在JEE模块内发送消息 + JCA适配器支持发送消息。连接工厂的默认配置在jms-ds.xml文件中,对应的JNDI名字是 + java:/JmsXA。在JEE中使用它发送消息将作为JTA事务的一部分来对待。 + 如果消息发送失败,整个事务将回滚,消息会被重新发送。下面是一个MDB发送消息的例子: + @MessageDriven(name = "MDBMessageSendTxExample", + activationConfig = + { + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue") + }) +@TransactionManagement(value= TransactionManagementType.CONTAINER) +@TransactionAttribute(value= TransactionAttributeType.REQUIRED) +@ResourceAdapter("hornetq-ra.rar") +public class MDBMessageSendTxExample implements MessageListener +{ + @Resource(mappedName = "java:/JmsXA") + ConnectionFactory connectionFactory; + + @Resource(mappedName = "queue/replyQueue") + Queue replyQueue; + + public void onMessage(Message message) + { + Connection conn = null; + try + { + //Step 9. We know the client is sending a text message so we cast + TextMessage textMessage = (TextMessage)message; + + //Step 10. get the text from the message. + String text = textMessage.getText(); + + System.out.println("message " + text); + + conn = connectionFactory.createConnection(); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + MessageProducer producer = sess.createProducer(replyQueue); + + producer.send(sess.createTextMessage("this is a reply")); + + } + catch (Exception e) + { + e.printStackTrace(); + } + finally + { + if(conn != null) + { + try + { + conn.close(); + } + catch (JMSException e) + { + } + } + } + } + } + 在JBoss应用服务器的EJB(包括会话Bean, 实体Bean和消息Bean)、Servlet(包括jsp)我定制的MBean中 + 都可以使用JMS的JCA适配器来发送消息。 +
+
+ MDB与接收池的大小 + 包括JBoss在内的绝大多数应用服务器允许用户定义一个池中的MDB数量。在JBoss中这个参数名是MaxPoolSize,它在文件 + ejb3-interceptors-aop.xml中配置。这个参数不影响实际创建的会话/接收者的数量。资源适配器不知道MDB的具体实现。所以即使你设置MDB池在大小 + 为1,仍然会有15个会话/接收者被创建(默认值)。如果你想改变会话/接收者创建的数量,你可以通过设置资源适配器的参数 + maxSession实现。也可以通过设置MDB的激活配置参数来完成: + @MessageDriven(name = "MDBMessageSendTxExample", + activationConfig = + { + @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), + @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"), + @ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1") + }) +@TransactionManagement(value= TransactionManagementType.CONTAINER) +@TransactionAttribute(value= TransactionAttributeType.REQUIRED) +@ResourceAdapter("hornetq-ra.rar") +public class MyMDB implements MessageListener +{ ....} + +
+
+ 配置JCA适配器 + 通过JCA适配器可以将HornetQ集成到JEE兼容的模块中,如MDB和EJB。它的配置决定了这些模块如何接收和发送消息。 + HornetQ的JCA适配器是通过jms-ra.rar部署的。它的配置文件中其中的 + META-INF/ra.xml + 下面是它的具体配置内容: + <resourceadapter> + <resourceadapter-class>org.hornetq.ra.HornetQResourceAdapter</resourceadapter-class> + <config-property> + <description>The transport type</description> + <config-property-name>ConnectorClassName</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>org.hornetq.core.remoting.impl.invm.InVMConnectorF + actory</config-property-value> + </config-property> + <config-property> + <description>The transport configuration. These values must be in the form of key=val;key=val;</description> + <config-property-name>ConnectionParameters</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>server-id=0</config-property-value> + </config-property> + + <outbound-resourceadapter> + <connection-definition> + <managedconnectionfactory-class>org.hornetq.ra.HornetQRAManagedConnection + Factory</managedconnectionfactory-class> + + <config-property> + <description>The default session type</description> + <config-property-name>SessionDefaultType</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>javax.jms.Queue</config-property-value> + </config-property> + <config-property> + <description>Try to obtain a lock within specified number of seconds; less + than or equal to 0 disable this functionality</description> + <config-property-name>UseTryLock</config-property-name> + <config-property-type>java.lang.Integer</config-property-type> + <config-property-value>0</config-property-value> + </config-property> + + <connectionfactory-interface>org.hornetq.ra.HornetQRAConnectionFactory + </connectionfactory-interface> + <connectionfactororg.hornetq.ra.HornetQConnectionFactoryImplonFactoryImpl + </connectionfactory-impl-class> + <connection-interface>javax.jms.Session</connection-interface> + <connection-impl-class>org.hornetq.ra.HornetQRASession + </connection-impl-class> + </connection-definition> + <transaction-support>XATransaction</transaction-support> + <authentication-mechanism> + <authentication-mechanism-type>BasicPassword + </authentication-mechanism-type> + <credential-interface>javax.resource.spi.security.PasswordCredential + </credential-interface> + </authentication-mechanism> + <reauthentication-support>false</reauthentication-support> + </outbound-resourceadapter> + + <inbound-resourceadapter> + <messageadapter> + <messagelistener> + <messagelistener-type>javax.jms.MessageListener</messagelistener-type> + <activationspec> + <activationspec-class>org.hornetq.ra.inflow.HornetQActivationSpec + </activationspec-class> + <required-config-property> + <config-property-name>destination</config-property-name> + </required-config-property> + </activationspec> + </messagelistener> + </messageadapter> + </inbound-resourceadapter> + + </resourceadapter> + 整个配置可以分为三个主要部分 + + + 适配器的全局参数 + + + 适配器外部(outbound)配置。用于在JEE环境中创建JMS资源。 + + + 适配器内部(inbound)配置。用于控制MDB的消息接收。 + + +
+ 适配器的全局参数 + 首先看到的第一个参数是resourceadapter-class。这是HornetQ + 的适配器类。此参数不可更改。 + 在此之后是可配置的参数。前两个配置适配器所使用的传输。其余的用来配置连接工厂。 + 所有连接工厂的参数在没有定义时使用默认值。参数reconnectAttempts + 的默认值取-1,表示如果连接失败,HornetQ会不停地尝试重新连接。这个参数只适用于创建远程 + 连接的情况。如果是InVm连接器,则永远不可能发生连接故障。 + 下面给出了每个参数的说明: + + 全局配置参数 + + + + + + + 参数名 + 参数类型 + 参数说明 + + + + + ConnectorClassName + String + 连接器的类名,参见 + + + ConnectionParameters + String + 传输配置参数。它的值必须是采用 + key1=val1;key2=val2;的形式。不同连接器有不同的参数。 + + + useLocalTx + boolean + 设为True,则进行本地事务优化。 + + + UserName + String + 用于创建连接时使用的用户名 + + + Password + String + 用于创建连接时使用的用户密码 + + + BackupConnectorClassName + String + 发生故障是使用的备份传输 + + + BackupConnectionParameters + String + 备份传输的配置参数 + + + DiscoveryAddress + String + 服务器自动检测所使用的发现组(discovery group)地址 + + + DiscoveryPort + Integer + 检测所使用的端口号 + + + DiscoveryRefreshTimeout + Long + 刷新的时间(timeout)。单位为毫秒 + + + + + DiscoveryInitialWaitTimeout + + + Long + 检测之前所需等待的时间 + + + + + ConnectionLoadBalancingPolicyClassName + + String + 负载均衡策略使用的类 + + + + + DiscoveryInitialWaitTimeout + + + Long + 向服务器发送ping的周期,单位毫秒 + + + + ConnectionTTL + + Long + 连接的存活时间(TTL) + + + + CallTimeout + + Long + 每个数据包的调用超时。单位毫秒 + + + + DupsOKBatchSize + + Integer + Dups OK的情况下消息批量的大小。 + + + + TransactionBatchSize + + Integer + 在事务中发送消息的批量大小 + + + + ConsumerWindowSize + + Integer + 接收者内部缓存的窗口大小 + + + +
+ 接上页.. + + + + + + + + + ConsumerMaxRate + + Integer + 接收者接收消息的最大速度 + + + + ConfirmationWindowSize + + Integer + 用于确认的窗口大小 + + + + ProducerMaxRate + + Integer + 发送者发送消息的最大速度 + + + + MinLargeMessageSize + + Integer + 大消息的最小数值,单位字节。 + + + + BlockOnAcknowledge + + Boolean + 如果为true,表示以阻塞方法发送消息通知。 + + + + BlockOnNonDurableSend + + Boolean + 如果为true,表示以阻塞方式发送非持久消息 + + + + BlockOnDurableSend + + Boolean + 如果为true,表示以阻塞方式发送持久消息 + + + + AutoGroup + + Boolean + 如果为true,表示自动消息分组 + + + + PreAcknowledge + + Boolean + 决定是否进行消息的预先通知(pre-acknowledge)。 + + + + ReconnectAttempts + + Integer + 连接重试的次数,默认为 -1 + + + + RetryInterval + + Long + 每次连接重试前等待的时间,单位毫秒。 + + + + RetryIntervalMultiplier + + Double + 用于计算重试间隔 + + + + FailoverOnServerShutdown + + Boolean + 如果设为true表示尝试连接其它的服务器 + + + + ClientID + + String + 连接的客户端ID + + + + ClientFailureCheckPeriod + + Long + 客户端如果在这个时间内没有收到服务器数据包,将认为连接出现故障。 + + + + UseGlobalPools + + Boolean + 是否使用全局线程池 + + + + ScheduledThreadPoolMaxSize + + Integer + 可计划线程池的最大线程数 + + + + ThreadPoolMaxSize + + Integer + 线程池的大小 + + + SetupAttempts + Integer + 尝试建立JMS连接的次数(默认值是10。-1表示无限次进行尝试)。有时MDB在部署时相关的JMS资源还没有准备好,这时通过多次的 +                   尝试直到JMS资源连接上为止。只适用于内部(Inbound)连接的情况。 + + + SetupInterval + Long + 每两次相邻尝试之间的时间间隔,以毫秒为单位(默认值为2000毫秒)。只适用于内部(Inbound)连接的情况。 + + + + +
+
+ 适配器外部(outbound)配置 + 外部配置参数应该保持不变。这是因为它所定义的连接工厂要被Java EE的模块所使用。这些连接工厂 + 可以定义在名字样式为*-ds.xml的配置文件中。在JBoss的部署目录 + hornetq.sar下有一个默认的配置文件jms-ds.xml。 + 在这个文件中的连接工厂的配置从主要的配置文件ra.xml中继承, + 但是可以在这里重新定义。下面的例子中给出了重新定义的方法。 + + 请注意这里的配置只适用于在JBoss应用服务器中安装的HornetQ。如果要在其它JEE应用服务器中 + 使用并配置HornetQ,请参照相应的应用服务器手册。 + + <tx-connection-factory> + <jndi-name>RemoteJmsXA</jndi-name> + <xa-transaction/> + <rar-name>jms-ra.rar</rar-name> + <connection-definition>org.hornetq.ra.HornetQRAConnectionFactory +</connection-definition> + <config-property name="SessionDefaultType" type="String">javax.jms.Topic + </config-property> + <config-property name="ConnectorClassName" type="String"> + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + </config-property> + <config-property name="ConnectionParameters" type="String"> + port=5445</config-property> + <max-pool-size>20</max-pool-size> +</tx-connection-factory> + 上面的例子中的连接工厂绑定到JNDI名字RemoteJmsXA。EJB和MDB可以用 + 下面的方法来得到它: + @Resource(mappedName="java:RemoteJmsXA") +private ConnectionFactory connectionFactory; + config-property覆盖了ra.xml文件中的配置。 + 以此类推,其它有关连接工厂的参数也可以在此覆盖。 + 除了全局的配置参数外,外部的配置还定义了其它一些参数。 + + + 外部配置参数 + + + + + + + 参数名 + 参数类型 + 说明 + + + + + SessionDefaultType + String + 默认的会话类型 + + + UseTryLock + Integer + 在规定的秒数内获得锁。如果不想使用这个功能,将它设为0或负数 + + + +
+
+
+ 适配器内部(inbound)配置 + 内部配置参数也应该保持不变。它们控制向MDB转发消息的各种属性。通过在MDB上添加相应的激活配置 + (activation configuration)可以覆盖这些参数的值。它可以用来配置一个MDB从另外一个服务器 + 接收消息。 + 除了全局的配置参数外,内部的配置还定义了其它一些参数。 + + + Inbound Configuration Properties + + + + + + + 参数名 + 参数类型 + 说明 + + + + + Destination + String + 目标的JNDI名字 + + + DestinationType + String + 目标的类型,javax.jms.Queue或者javax.jms.Topic + (默认是javax.jms.Queue) + + + AcknowledgeMode + String + 通知模式,Auto-acknowledgeDups-ok-acknowledge + (默认值是Auto-acknowledge). AUTO_ACKNOWLEDGEDUPS_OK_ACKNOWLEDGE也是有效值 + + + MaxSession + Integer + 内部配置创建的最大会话数(默认是5) + + + MessageSelector + String + 接收者的消息选择器 + + + SubscriptionDurability + String + 订阅的类型,Durable或者NonDurable + + + SubscriptionName + String + 订阅的名字 + + + TransactionTimeout + Long + 事务超时(毫秒,默认是0,表示事务不会超时) + + + UseJNDI + Boolean + 是否使用JNDI来查找目标(默认是true) + + + +
+
+
+ 配置适配器访问单独的HornetQ服务器 + 在有的情况下,消息服务器与应用服务器运行在不同的机器上。这时客户端只需要安装HornetQ的客户端的库文件。本节给出了具体的配置和所需要的jar文件。 +
+ 你需要配置两个配置文件。一个是MDB所用的内部适配器,另一个是可以创建外部连接的外部适配器。 +
+ 配置内部适配器 + 首先在deploy目录下创建一个以.rar为结尾的文件夹。 + 在这里我们将其命名为hornetq-ra.rar。主注意这一点很重要,因为MDB和外部配置都需要引用 + 该文件夹的名字。 + + + 在JBoss中该文件夹的默认名为jms-ra.rar。你可以直接使用这个名字。但是你可能需要避免 + 与其它的通用适配器相冲突。 + + + 在文件夹 + hornetq-ra.rar + 下创建名为 + META-INF + 的文件夹,然后在些文件夹内创建一个 + ra.xml配置文件。在HornetQ发布包中 + 有一个ra.xml模板文件供你使用。 + + 要配置MDB接收远程HornetQ服务器的消息,你需要修改deploy/hornet-ra.rar/META-INF下面的 + ra.xml文件,将传输层改为netty连接器(不要使用invm连接器)及其相应的参数。下面 + 是一个配置的例子: + + + + <resourceadapter-class>org.hornetq.ra.HornetQResourceAdapter</resourceadapter-class> + <config-property> + <description>The transport type</description> + <config-property-name>ConnectorClassName</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property-value> + </config-property> + <config-property> + <description>The transport configuration. These values must be in the form of key=val;key=val;</description> + <config-property-name>ConnectionParameters</config-property-name> + <config-property-type>java.lang.String</config-property-type> + <config-property-value>host=127.0.0.1;port=5446</config-property-value> + </config-property> + + 上面的配置中,适配器连接到一个运行在本机上端口为5446的服务器。 +
+ +
+ 配置外部适配器 + 你还需要创建一个hornetq-ds.xml文件来配置外部连接。该文件需要放置在deploy + 下的任意一个文件夹中。在一相标准的安装中这个文件夹是horneq 或者 hornetq.sar。 + 当然你可以选择其它文件夹。该文件的名字只要是以-ds.xml即可。在HornetQ的发布包中包含有一个模板文件, + 它的名字是jms-ds.xml,位置就在config文件夹下。 + + 下面是一个配置的例子。 + + <tx-connection-factory> + <jndi-name>RemoteJmsXA</jndi-name> + <xa-transaction/> + <rar-name>hornetq-ra.rar</rar-name> + <connection-definition>org.hornetq.ra.HornetQRAConnectionFactory</connection-definition> + <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property> + <config-property name="ConnectorClassName" type="java.lang.String">org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property> + <config-property name="ConnectionParameters" type="java.lang.String">host=127.0.0.1;port=5446</config-property> + <max-pool-size>20</max-pool-size> + </tx-connection-factory> + + 这个配置同样是连接到运行在本机上的端口为5446的HornetQ服务器。JEE模块可以通过JNDI查找 + java:/RemoteJmsXA(由jndi-name参数定义)。如上节所述, + 资源适配器根据文件夹下的配置来创建外部连接。 +
+ 依赖的jar文件 + 下面列出了HornetQ所需要的第三方jar文件 + + Jar文件 + + + + + + + Jar文件名 + 说明 + 位置 + + + + + hornetq-ra.jar + HornetQ资源适配器文件 + deploy/hornetq-ra.rar或相应的位置 + + + hornetq-core-client.jar + HornetQ核心客户类库 + 在JBoss的default/lib下或者是$JBOSS_HOME/common/lib下。 + + + hornetq-jms-client.jar + HornetQ的JMS类 + 同上 + + + netty.jar + Netty类库 + 同上 + + + +
+
+
+
+
+
+ 高可获得性JNDI (HA-JNDI) + 采用JNDI来查找JMS对象时(队列,话题及连接工厂),使用HA-JNDI可以增加容错的能力。即当你正在使用 + 的JNDI服务器发生故障时,客户端可以使用集群中的其它JNDI服务器继续工作。 + HA-JNDI是JBoss应用服务器的一项服务,它为客户端提供JNDI服务,客户端无需知道JNDI具体服务器的连接 + 细节。这个服务只有在集群的JBoss应用服务器上才可使用。 + 要使用HA-JNDI,需要使用下面的JNDI参数。 + Hashtable<String, String> jndiParameters = new Hashtable<String, String>(); +jndiParameters.put("java.naming.factory.initial", + "org.jnp.interfaces.NamingContextFactory"); +jndiParameters.put("java.naming.factory.url.pkgs=", + "org.jboss.naming:org.jnp.interfaces"); + +initialContext = new InitialContext(jndiParameters); + 有关HA-JNDI更多的信息请参见JBoss应用服务器集群文档 +
+
+ XA恢复 + XA恢复解决的是事务在系统或应用出现故障时的处理。它可以保证在应用进程或主机出现故障 + 或网络崩溃等情况下,事务内所有资源的状态的一致性。有关XA恢复的更多信息请见 JBoss + 事务 + 当HornetQ与JBoss应用服务器集成时,它可以利用JBoss的事务处理来对消息资源进行恢复。如果消息处理包括 + 在一个XA事务中,如果服务器出现故障并重启时,恢复管理器将负责恢复事务,这样其中的消息要么被提交,要么被回滚(取 + 决于事务的处理决定)。 +
+ XA恢复的配置 + 要想HornetQ具有XA恢复功能,则必须配置恢复管理器连接到HornetQ并恢复其资源。下面的参数必须要加到 + conf/jbossts-properties.xml文件中的jta部分: + +<properties depends="arjuna" name="jta"> + ... + + <property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HornetQ1" + value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;[连接配置]"/> +</properties> + + 其中[连接配置]包括连接HornetQ节点所必需的信息。 + 它的格式是[连接工厂类名],[用户名], [密码], [连接参数] + + + [连接工厂类名]指的是ConnectorFactory + 的类名,用来连接HornetQ服务器。其值可以是org.hornetq.core.remoting.impl.invm.InVMConnectorFactory 或 + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + + + [用户名]是用于创建客户会话的用户名。是可选项。 + + + [密码]是创建客户会话时所用的密码。只有在用户名存在时需要。 + + + [连接参数] 是用逗号分隔的一串键-值对。它们会传递给连接器工厂 + (参见 )。 + + + + HornetQ必须有一个与conf/jbossts-properties.xml中定义的连接器相对应的接受器(acceptor)。 + +
+ 配置参数 + 如果HornetQ配置了一个默认的in-vm接受器: + +<acceptor name="in-vm"> + <factory-class>org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory</factory-class> +</acceptor> + + 相应地在 conf/jbossts-properties.xml文件中: + +<property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HORNETQ1" + value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;org.hornetq.core.remoting.impl.invm.InVMConnectorFactory"/> + + 如果配置了一个netty接受器,并且端口不是默认的: + +<acceptor name="netty"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class> + <param key="port" value="8888"/> +</acceptor> + + 相应的在 conf/jbossts-properties.xml文件中: + +<property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HORNETQ1" + value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;org.hornetq.core.remoting.impl.netty.NettyConnectorFactory, , , port=8888"/> + + + 注意在没有用户名和密码时,逗号是不能省略的。 + + 如果恢复必须要求是admin, adminpass,则其配置 + 应为如下所示: + + <property name="com.arjuna.ats.jta.recovery.XAResourceRecovery.HORNETQ1" + value="org.hornetq.jms.server.recovery.HornetQXAResourceRecovery;org.hornetq.core.remoting.impl.netty.NettyConnectorFactory, admin, adminpass, port=8888"/> + + 推荐在XA恢复中,将HornetQ配置一个invm接受器,并配置恢复管理器使用invm连接器。 +
+
+
+ 例子 + 参见。这个例子展示了如何来配置XA恢复以便在服务器崩溃后恢复消息。 +
+
+
+
diff --git a/docs/user-manual/zh/architecture.xml b/docs/user-manual/zh/architecture.xml new file mode 100644 index 0000000000..d8d12a2b66 --- /dev/null +++ b/docs/user-manual/zh/architecture.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + 总体架构 + 本章对HornetQ的总体技术架构进行了概括描述。 +
+ 核心架构 + HornetQ的核心是由一组简单Java对象(POJO)构成的。同时在设计HornetQ时将对外部jar包的依赖降到最低限度。 + 实际上HornetQ的核心部分只有一个外部依赖,就是netty.jar。HornetQ使用了其中的用于缓冲的一些类。 + 我们相信这样的理念应该受到用户的欢迎。 + 由于依赖性很小,HornetQ可以非常容易地嵌入到其它应用中,或者加入到一些依赖注入式的框架中, + 如JBoss Microcontainer,Spring或Google Guice。 + 每个HornetQ服务器都有自己的超高性能的持久日志(journal)用于消息和其它信息的持久化。 + 采用这种独特的高效日志要比采用普通数据库作为持久层的系统拥有更高的性能。 + 通常情况下分布在不同物理机器上的客户端同时访问HornetQ服务器。目前HornetQ提供了两套API供客户端使用: + + + + 核心API。这是一组普通的Java接口,用它可以访问HornetQ的全部功能。 + + + JMS客户端API。这是标准的JMS API。 + + + + 实际上JMS API是在核心API的外部加上一层简单的封装。 + 在HornetQ内核是没有JMS的,这样设计的目的是为了支持多个协议。 + 当客户端通过JMS接口访问HornetQ时,所有JMS的操作都被转换成相应的核心API,然后将请求以HornetQ格式发向服务器。 + HornetQ服务器只接收核心API的访问。 + 图3.1描述了这些操作。 + + + + 在图3.1中示出了两个用户访问HornetQ服务器。用户1使用JMS API,用户2使用的是核心API。 + 图中清楚的展示出了JMS是如何通过封装(facade)转化为核心API的。 +
+
+ 将HornetQ嵌入到你的应用程序中 + 如果你的应用程序内部需要消息服务,但同时你又不想将消息服务暴露为单独的HornetQ服务器,你可以在应用中直接将HornetQ实例化。 + 有关嵌入式HornetQ的详细信息请参阅 +
+
+ 将HornetQ与JEE应用服务器集成 + HornetQ提供了标准的JCA适配器,利用它可以将HornetQ轻松地集成到任何一个符合JEE规范的应用服务器或servlet容器中。 + JEE应用服务品提供了消息Bean(MDB)用于处理来自外部的消息,比如来自JMS系统或邮件系统的消息。 + 最常见的应用应该是用MDB来接收来自JMS系统中的消息了。在JEE规范中规定了JEE应用服务器使用JCA adaptor与JMS消息系统集成, + MDB通过这个adaptor来接收消息。 + JCA adaptor不仅可以用来接收消息,还可以用来从EJB或servlet中向外部的JMS发送消息。在JEE应用服务器中应该用JCA adaptor与JMS系统进行交互。 + 实际上JEE规范中不允许在JEE服务器中不通过JCA而直接访问JMS系统。 + 在EJB中使用消息往往需要连接池或交易,而JCA可以提供这方面的服务,无需额外的开发任务。当然直接访问JMS系统是可能的, + 但是你将不能利用JCA所提供的这些有用的功能,因此我们不建议使用直接访问的方式。 + 图3.2给出了HornetQ通过JCA adaptor与JEE应用服务器集成的示意图。图中可以看出所有的交互都通过JCA adaptor。 + 图中带有禁止符号的箭头表明的是从EJB会话Bean直接访问HornetQ的情况。由于不通过JCA,这种方法往往造成每次EJB访问HornetQ都要新建一个连接和会话, + 使效率大降低。这被视为反设计模式(anti-pattern)。 + + + + 对如何使用JCA给出了更加详细的描述。 +
+
+ HornetQ作为独立的服务(standalone) + HornetQ可以部署成为独立的服务器。它可运行于任何JEE应用服务器之外,作为一个独立的服务运行。 + 作为独立服务器运行时,HornetQ消息服务器包括一个核心服务器,一个JMS服务以及一个JNDI服务。 + JMS服务用来部署服务器端hornetq-jms.xml配置文件中的JMS Queue,Topic和ConnectionFactory实例。 + 此外它还提供一组简单的管理接口,通过这些接口可以创建、消毁(destroy)Queue,Topic和ConnectionFactory实例。 + 用于可以通过JMX或连接使用这些接口。JMS服务是单独的服务,它不是HornetQ核心服务。HornetQ的核心不包含JMS相关的服务。 + 如果你不需要通过服务器端的xml配置文件部署任何JMS对象,也不需要JMS的管理接口,你可以选择不启动该服务。 + 启动JNDI服务的目的是因为JMS需要通过JNDI来获得Queue,Topic以及ConnectionFactory。如果不需要,也可以选择不启动该服务。 + HornetQ允许在客户端程序中通过编程来直接创建各种JMS对象和核心对象来代替JNDI查找,所以JNDI不是必需的。 + HornetQ采用JBoss Microcontainer来引导并实例化服务,并保证模块之间的依赖关系。JBoss Microcontainer是一个轻量级的POJO引导器(bootstrapper)。 + 图3.3给出了HornetQ独立服务器的架构。 + + + + 相关配置的相关信息可以在第找到。$ +
+
diff --git a/docs/user-manual/zh/client-classpath.xml b/docs/user-manual/zh/client-classpath.xml new file mode 100644 index 0000000000..9a82ce36d9 --- /dev/null +++ b/docs/user-manual/zh/client-classpath.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + 客户端的Classpath + HornetQ的客户端Classpath需要有几个jar文件。具体是哪几个要根据客户端 + 是需要内核API、JMS和JNDI中的哪些服务来确定。 + + 本章所提及的所有jar文件全部在HorneQ发布包的 lib目录下。在使用中一定 + 要确保所有的jar文件属于同一个发布版本。将不同版本的jar混在一起使用可能造成一些难以发现的错误。 + +
+ 使用HornetQ内核的客户端 + 如果客户端只使用HornetQ内核(非JMS客户端),需要将 hornetq-core-client.jar和 + netty.jar 放到classpath中。 +
+
+ JMS客户端 + 如果客户端使用JMS,需要在classpath上增加两个jar文件: hornetq-jms-client.jarjboss-jms-api.jar + + jboss-jms-api.jar中包含的只是 javax.jms.* 包中的接口类。 + 如果这些类已经在你的classpath中,则你就不需要这个jar文件。 + +
+
+ 需要JNDI的JMS客户端 + 如果你的JMS客户端使用JNDI来查找HornetQ单独服务器上的对象,你需要将 jnp-client.jar 增加 + 到你的classpath中。 +
+
diff --git a/docs/user-manual/zh/client-reconnection.xml b/docs/user-manual/zh/client-reconnection.xml new file mode 100644 index 0000000000..70ea03371a --- /dev/null +++ b/docs/user-manual/zh/client-reconnection.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + 客户端重新连接与会话恢复 + 通过配置,HornetQ的客户端在与服务器的连接出现故障时,可以自动地重新建立连接并恢复与服务器的通迅。 +
+ 100%透明的会话恢复(re-attachment) + 如果网络出现暂时性连接故障,并且服务器没有重启的情况下,当前的会话还会存在服务器中,其状态如同客户端 + 没有断开超过连接TTL时间。 + 在这种情况下,当客户端重新连接上服务器后,HornetQ自动将客户端和会话与服务器端的会话重新连接起来。整个过程 + 对于客户端是完全透明的,在客户端就好像什么都没有发生一样。 + 具体工作原理如下: + 客户端再向服务器发送命令时,它将每个命令保存到内存的一块缓存中。当连接出现故障时客户端会尝试与该服务 + 器恢复会话。做为恢复协议的一部分,服务器在会话恢复时通知客户端最后一个成功接收的命令id。 + 根据这个命令id,客户端可以判断它的缓存中是否有命令还未被服务器成功接收。如果有,客户端可以重新发送 + 这些命令。 + 缓存的大小由ConfirmationWindowSize参数决定。当服务器成功接收了 + ConfirmationWindowSize字节的命令时,会向客户端发送一个命令确认,以使客户端 + 及时清除缓存。 + 如果使用JMS服务,并且JMS的连接工厂是注册到JNDI的话,相应的参数是hornetq-jms.xml文件中的confirmation-window-size项。如果你并不将JMS连接工厂注册到JNDI,则你需要在 + HornetQConnectionFactory上使用相应的方法直接设置该参数。 + 如果使用核心服务,你可以直接在ClientSessionFactory实例上直接设置该参数。 + 参数的单位是字节。 + 如果该参数是值设为-1,则关闭缓存,即关闭了重新恢复功能,迫使进行重新连接。默认 + 值是-1(表示没有自动恢复)。 +
+
+ 会话重新连接 + 有时服务器发生故障后进行了重启。这时服务器将丢失所有当前的会话,上面所述的会话恢复就不能做到完全透明了。 + 在这种情况下,HornetQ自动地重新建立连接并重新创建会话 + 和接收者。这一过程与向备份服务器进行失效备援(failover)完全一样。 + 客户重新连接的功能还用在其它一些模块上,如核心桥,以使它们能够重新连接到目标服务器上。 + 要全面理解事务性会话和非事务性会话在失效备援/重连接情况下的细节,以及如何保证 + 一次并且只有一次的消息传递,请参见的有关内容。 +
+
+ 重新连接/会话恢复的配置参数 + 下面是客户端用于重新连接的参数: + + + retry-interval。可选参数。它决定了两次重新连接尝试间隔的时间。单位 + 是毫秒。默认值是2000毫秒。 + + + retry-interval-multiplier。可选参数。它表示下一次重试时间间隔的 + 系数。即下一次重试的时间间隔是本次时间间隔乘以该参数。 + 这样可以实现重试间隔的指数延迟(exponential backoff) + 让我们看一个例子: + 假设retry-interval1000 ms,并且我们 + 将retry-interval-multiplier设为2.0,如果 + 第一次尝试失败,则等待1000毫秒后进行第二次重试,如果再失败,则每三次重 + 试要在2000毫秒后进行,第四次要等待4000毫秒, + 以此类推。 + 默认值是1.0,表示每次重试间隔相同的时间。 + + + max-retry-interval。可选参数。它决定了重试间的最大时间间隔。 + 使用retry-interval-multiplier可以使重试的时间间隔以指数级增加。 + 有可能造成时间间隔增加到一个非常大的数值。通过设置一个最大值可对其增长进行限制。默认 + 值是2000毫秒。 + + + reconnect-attempts。可选参数。它表示要进行多少重试后才放弃 + 并退出。-1表示进行无限次重试。默认值是0 + + + 如果使用JMS并且将JMS的连接工厂绑定到JNDI服务中,则需要在hornetq-jms.xml + 文件中对这些参数进行配置,如下例所示: + +<connection-factory name="ConnectionFactory"> +<connectors> + <connector-ref connector-name="netty"/> +</connectors> +<entries> + <entry name="ConnectionFactory"/> + <entry name="XAConnectionFactory"/> +</entries> +<retry-interval>1000</retry-interval> +<retry-interval-multiplier>1.5</retry-interval-multiplier> +<max-retry-interval>60000</max-retry-interval> +<reconnect-attempts>1000</reconnect-attempts> +</connection-factory> + + 如果使用JMS但是直接实例化JMS连接工厂,你可以使用适当的方法在 HornetQConnectionFactory 对象上直接设置这些参数。 + 如果使用核心接口直接创建 ClientSessionFactory实例,则用它的适当的方法可以设置这些参数。 + 如果客户端重新连接后发现会话已经丢失(如服务器重启或超时),则无法完成恢复。如果在连接上或会话上注册了 + ExceptionListenerFailureListener, + 它们将会被通知。 +
+
+ ExceptionListeners and SessionFailureListeners + 请注意当客户端进行重新连接或恢复会话时,注册的JMS ExceptionListener 或核心接口的 SessionFailureListener + 将会被调用。 +
+
diff --git a/docs/user-manual/zh/clusters.xml b/docs/user-manual/zh/clusters.xml new file mode 100644 index 0000000000..a6cb59169d --- /dev/null +++ b/docs/user-manual/zh/clusters.xml @@ -0,0 +1,551 @@ + + + + + + + + + + + + + + + + + + + + 集群 +
+ 集群概述 + HornetQ集群是由一组HornetQ服务器组成的集合,它们协同合作进行消息处理。集群中每个主节点就是一个 + HornetQ服务器,它管理自己的连接并处理自己的消息。要将一个HornetQ服务器配置为集群服务器,需要将配置 + 文件hornetq-configuration.xmlclustered的值设 + 为true。默认值是false + 要组成一个集群,每个节点都要在其核心配置文件hornetq-configuration.xml + 中声明集群连接,用来建立与集群中其它节点的通迅。每两个节点间都是通过内部的一个 + 核心桥(参见)连接的。这些连接的建立是 + 透明的--你不需要为每个连接显式地声明一个桥。集群连接的作用是在集群的各个节点间进行负载平衡。 + HornetQ可以采用不同的拓扑结构来组成集群。本章后面将讲述几种常用的拓扑结构。 + 我们还将讨论客户端的负载均衡--客户端如何均衡其与集群各节点的连接,以及消息的再分配--在节点间合理 + 的分配消息以避免消息匮乏(starvation)。 + 本章还涉及集群的另一个重要方面--服务器发现,即服务器通过广播的方式将 + 自己的连接信息告诉客户端或其它服务器,以使它们能与其建立连接,不需要额外的配置。 +
+
+ 服务器发现 + 服务器发现是指服务器通过广播的方式将自己的连接设置发送到网络上的机制,它有两个目的: + + + 被消息客户端发现。客户端接到广播后可以知道集群中有哪些服务器处于工作状态以及如何与它们 + 建立连接。虽然客户端可以可以在初始化时接受一个集群服务器的列表, + 但是这样做与广播方式相比不够灵活。比如集群中有服务器离开或新加入时,列表的方式不能及时更新这些信息。 + + + 被其它服务器发现。通过广播,服务器之间可以自动建立彼此间的连接,不需要事先知道集群中其它 + 服务器的信息。 + + + 服务器发现使用UDP协议来广播连接设置。如果网络中UDP被关闭,则不能使用服务器发现功能。只有用显式 + 地指定服务器的方法来设置集群或集群的客户端。 +
+ 广播组 + 服务器以广播组的方式来广播它的连接器信息。连接器定义了如何与该服务器建立连接的信息。关于连接器更多的 + 解释,请参见 + 广播组包括了一系列的连接器对。每个连接器对由主服务器的连接器和备份(可选)服务器连接器信息组成。 + 广播组还定义了所使用的UDP的在址和端口信息。 + 广播组的配置中服务器配置文件hornetq-configuration.xml中。一个HornetQ服务器可以有多个广播组。所有的广播组 + 必需定义在broadcast-groups内。 + 让我们来看一个hornetq-configuration.xml文件中广播组的例子: + <broadcast-groups> + <broadcast-group name="my-broadcast-group"> + <local-bind-address>172.16.9.3</local-bind-address> + <local-bind-port>54321</local-bind-port> + <group-address>231.7.7.7</group-address> + <group-port>9876</group-port> + <broadcast-period>2000</broadcast-period> + <connector-ref connector-name="netty-connector" + backup-connector="backup-connector"/> + </broadcast-group> +</broadcast-groups> + 有些广播组的参数是可选的,通常情况下可以使用默认值。在上面例子中我们为了说明目的给出了这些参数。 + 下面是这些参数的说明: + + + name。每个广播组需要有一个唯一的名字。 + + + local-bind-address。这个参数是套接字的本地绑定地址。如果在服务器 + 中有多个网络接口卡时,必须要指定使用的是哪个接口。如果这个参数没有指定,那么将使用系统内核 + 所选定的IP地址。 + + + local-bind-port。这个参数指定了套接字的本地绑定端口。通常情况下 + 可以使用其默认值-1,表示使用随机的端口。这个参数总是和 + local-bind-address一起定义。 + + + group-address。这个参数指定的是广播地址。它是一个D类的IP地址, + 取值范围是224.0.0.0239.255.255.255。 + 地址224.0.0.0是保留地址,所以不能使用。这个参数是必需指定。 + + + group-port。这个参数设定广播的UDP端口。 + 是一个必需指定的参数。 + + + broadcast-period。指定两次广播之间的时间间隔,单位毫秒。 + 这是一个可选参数,它的默认值是1000毫秒。 + + + connector-ref。这个参数指定了要广播的连接器以及可选的备份连接器。 + (参见)。 + connector-name属性的值是连接器的名字, + backup-connector属性是备份连接器的名字,是可选属性。 + + +
+
+ 发现组 + 广播组规定了如何广播连接器的信息,发现组则定义的如何接收连接器的信息。 + 一个发现组包括了一系列的连接器对--每个连接器对代表一个不同的服务器广播的连接器信息。每当接收一次广播, + 这个连接对的列表就被更新一次。 + 如果在一定时间内没有收到某个服务器的广播,则其相应的连接器对将从列表中删除。 + 发现组在HornetQ中有两处应用: + + + 在创建集群连接时用来判断集群中哪些服务器是可以连接的。 + + + 客户端用来发现哪些服务器可以连接。 + + +
+
+ 在服务器端定义发现组。 + 服务器端的发现组定义在hornetq-configuration.xml配置文件中。所有的发现组都必须 + 在discovery-groups内定义。发现组可以定义多个。请看下面的例子: + <discovery-groups> + <discovery-group name="my-discovery-group"> + <local-bind-address>172.16.9.7</local-bind-address> + <group-address>231.7.7.7</group-address> + <group-port>9876</group-port> + <refresh-timeout>10000</refresh-timeout> + </discovery-group> +</discovery-groups> + 下面是对每个参数的解释: + + + name属性。每个发现组都必须有一个唯一的名字。 + + + local-bind-address。如果你的主机有多个网络接口,你可能希望发现组只监听一个指定的 + 网络接口。这个参数就可以用于这个目的。它是一个可选参数。 + + + group-address。需要监听的广播地址。它需要与广播组的 + group-address一致才可以收到广播组的信息。这是一个必要参数。 + + + group-port。需要监听的UDP端口。它需要与广播组的 + group-port值相同才可以收到广播组的信息。这是一个必要参数。 + + + refresh-timeout。这个参数决定了在收到某个服务器的广播后,需要等待 + 多长时间下一次广播必须收到,否则将该服务器的连接器对从列表中删除。通常这个参数的值应该远大于 + 广播组的broadcast-period,否则会使服务器信息由于小的时间差异而丢失。 + 这个参数是可选的,它的默认值是10000毫秒(10秒)。 + + +
+
+ 客户端的发现组 + 现在讨论如何配置HornetQ客户端来发现可以连接的服务器列表。使用JMS时所用的方法与使用核心接口时所用的 + 方法有所不同。 +
+ 使用JMS时客户端发现的配置方法 + 如果使用JMS,并且在服务器端的JMS连接工厂是注册到JNDI的情况下,你可以在服务器端的配置文件 + hornetq-jms.xml中指定连接工厂所用的发现组。如下面所示: + <connection-factory name="ConnectionFactory"> + <discovery-group-ref discovery-group-name="my-discovery-group"/> + <entries> + <entry name="ConnectionFactory"/> + </entries> +</connection-factory> + 其中discovery-group-ref的值是定义在 + hornetq-configuration.xml文件中的一个发现组。 + 当连接工厂从JNDI下载到客户端时,使用它创建连接就会在列表中的服务器间进行负载均衡。 + 客户端通过监听发现组中的广播地址可以不断更新这个服务器列表。 + 如果使用JMS但是不用JNDI,而是直接实例化JMS的连接工厂的话,可以用适当的方法来设置发现组的各个 + 参数。如下所示:final String groupAddress = "231.7.7.7"; + +final int groupPort = 9876; + +ConnectionFactory jmsConnectionFactory = + HornetQJMSClient.createConnectionFactory(groupAddress, groupPort); + +Connection jmsConnection1 = jmsConnectionFactory.createConnection(); + +Connection jmsConnection2 = jmsConnectionFactory.createConnection(); + refresh-timeout参数可以直接在连接工厂上使用 + setDiscoveryRefreshTimeout()方法设置。 + 连接工厂还有一个方法setDiscoveryInitialWaitTimeout()。它可以设置连接工厂的 + 初始等待时间。当一个连接工厂被创建后立即进行用于创建连接的话,连接工厂可能没有足够的时间来接收各 + 个服务器发出的广播信息,也就无法建立完整的服务器列表。有了这个参数,连接工厂会在首次创建连接时 + 等待一定的时间,以接收广播。默认值是10000毫秒。 +
+
+ 使用核心API的客户端的配置 + 如果使用核心接口直接创建ClientSessionFactory的实例,可以使用相应的方法 + 直接进行参数的设置,如: + + final String groupAddress = "231.7.7.7"; + final int groupPort = 9876; + SessionFactory factory = HornetQClient.createClientSessionFactory(groupAddress, groupPort); + ClientSession session1 = factory.createClientSession(...); ClientSession + session2 = factory.createClientSession(...); + + + + 方法setDiscoveryRefreshTimeout()可以用来直接设置参数 + refresh-timeout + 会话工厂还有一个方法setDiscoveryInitialWaitTimeout()。它可以设置会话工厂的 + 初始等待时间。当一个会话工厂被创建后立即进行用于创建连接的话,该会话工厂可能没有足够的时间来接收各 + 个服务器发出的广播信息,也就无法建立完整的服务器列表。有了这个参数,会话工厂会在首次创建连接时 + 等待一定的时间,以接收广播。默认值是10000毫秒。 +
+
+
+
+ 服务器端消息的负载均衡 + 如果集群和各节点间定义了集群连接,HornetQ可以对到达一个节点的消息进行负载均衡。 + 举一个简单的例子。一个集群有4个节点,分别称为节点A、B、C和节点D。它们组成了一个 + 对称式集群(有关对称式集群参见)。 + 在每个节点上部署了一个名为OrderQueue的队列。 + 一个客户端Ca连接到节点A并向其发送订单消息。客户端Pa、Pb、Pc和Pd分别连接到节点A、B、C和D并接收处理 + 这些订单消息。如果在节点A中没有定义集群连接,那么订单消息都发送到节点A中的队列OrderQueue + 中。因此只有连接到节点A的客户端Pa才能接收到订单消息。 + 如果在节点A定义了集群连接的话,发送到节点A的消息被轮流(round-robin)从节点A分配到各个节点上的 + OrderQueue队列中。这种消息分配完全在服务器端完成,客户端只向节点A发送消息。 + 例如到达节点A的消息可能以下列顺序进行分配:B、D、C、A、B、D、C、A、B、D。具体的顺序取决于节点启动的 + 先后,但是其算法是不变的(即round-robin)。 + HornetQ集群连接在进行消息负载均衡时,可以配置成统一负载均衡模式,即不管各个节点上有无合适的接收者,一律在 + 所有节点间进行消息的分配。也可以配置成为智能负载均衡模式,即只将消息分配到有合适接收者的节点上。这两种模式我们 + 都将举例说明。首先我们先介绍一般的集群连接配置。 +
+ 配置集群连接 + 集群连接将一组服务器连接成为一个集群,消息可以在集群的节点之间进行负载均衡。集群连接的配置在 + hornetq-configuration.xml文件中的 + cluster-connection内。一个HornetQ服务器可以有零个或多个集群连接。 + 下面是一个典型的例子: + +<cluster-connections> + <cluster-connection name="my-cluster"> + <address>jms</address> + <retry-interval>500</retry-interval> + <use-duplicate-detection>true</use-duplicate-detection> + <forward-when-no-consumers>false</forward-when-no-consumers> + <max-hops>1</max-hops> + <discovery-group-ref discovery-group-name="my-discovery-group"/> + </cluster-connection> +</cluster-connections> + + 上面给出了集群连接的所有可配置参数。在实际应用中有些你可以使用默认值,不必全部给出。 + + + address。每个集群连接只服务于发送到以这个参数的值为开始的 + 地址的消息。 + 本例中的集群连接只对发往以jms为开始的地址的消息进行负载均衡的 + 处理。这个集群连接实际上能够处理所有JMS队列和话题的订阅中的消息,这是国为所有JMS的队列 + 或订阅都映射到内核中以“jms“开头的队列。 + 这个地址可以为任何值,而且可以配置多个集群连接,每个连接的地址值可以不同。这样HornetQ + 可以同时对不同地址同时进行消息的负载均衡。有的地址甚至可能在其它集群的节点中。这也就意谓着 + 一个HornetQ服务器可以同时参与到多个集群中。 + 要注意别造成多个集群连接的地址互相重复。比如,地址“europe“和”europe.news“就互相重复, + 就会造成同一个消息会被多个集群连接进行分配,这样有可能发生重复传递。 + 本参数是必须指定的。 + + + retry-interval。如前所述,一个集群连接实际上在内部是用桥将两 + 个节点连接起来。如果集群连接已经创建但是目的节点还未启动,或正在重启,这时集群连接就会不断 + 重试与这个节点的连接,直到节点启动完毕连接成功为止。 + 这个参数决定了两次重试之间的时间间隔,单位是毫秒。它与桥的参数retry-interval + 的含义相同(参见)。 + 这个参数是可选的,默认值是500毫秒。 + + + use-duplicate-detection。集群连接使用桥来连接各节点,而桥可以 + 通过配置向每个转发的消息添加一个重复id的属性。如果目的节点崩溃并重启,消息可以被重新发送。 + 重复检测的功能就是在这种情况下将重复发送的消息进行过滤并丢弃。 + 这个参数与桥的参数use-duplicate-detection相同。关于重复检测的更多信息,请参见 + + 这参数是可选的,默认值是true + + + forward-when-no-consumers。这个参数决定了是否向没有合适接收者 + 的节点分配消息。即不管有没有合适的接收者,消息在所有的节点间轮流分配。 + 如果这个参数设为true,则消息就会轮流在每个节点间分配,不管是否 + 节点上有没有相应的接收者(或者有接收者但是具有不匹配的选择器)。注意,如果其它节点中没有 + 与本节点同名的队列,HornetQ不会将消息转发到那些节点中去,不受本参数的限制。 + 如果参数设为false, HornetQ中将消息转发到集群中那些有着适合接收者 + 的节点中。如果接收者有选择器,则至少有一个选择器与所转发的消息匹配才可,否则不转发。 + 本参数是可选的,默认值是false + + + max-hops。当一个集群连接在确定进行消息负载均衡的节点组时,这些 + 节点不一定是与本节点直接相连的节点。HornetQ可以通过其它HornetQ节点作为中介向那些非直接相 + 连的节点转发消息。 + 这样可以使HornetQ组成更加复杂的拓扑结构并且仍可提供消息的负载均衡。在本章的后面我们还要作 + 进一步的讨论。 + 本参数是可选参数,它的默认值是 1,表示消息只向直接相连的节点进行负载均衡。 + + + discovery-group-ref。这个参数决定了使用哪个发现组来获得集群服务器的列表。 + 集群连接与列表中的服务器建立连接。 + + +
+
+ 集群用户的安全信息 + + 当集群中两个节点建立连接时,HornetQ使用一个集群用户和集群密码。它们定义在 + hornetq-configuration.xml文件中: + + <cluster-user>HORNETQ.CLUSTER.ADMIN.USER</cluster-user> + <cluster-password>CHANGE ME!!</cluster-password> + + 强烈建议在实际应用中不要使用默认的值,否则任意远程客户端会使用这些默认值连接到服务器上。当使用默认值时, + HornetQ会检测到并在每次启动的时候给出警告。 +
+
+
+ 客户端负载均衡 + HornetQ的客户端负载均衡使同一个会话工厂每次创建一个会话时,都连接到集群不同的节点上。这样可以使所的有会话 + 均匀分布在集群的各个节点上,而不会‘拥挤’到某一个节点上。 + 客户端负载均衡的策略是可配置的。HornetQ提供两种现成的负载均衡策略。你也可以实现自己的策略。 + 两种现成的策略是: + + + 轮流策略(Round Robin)。这个策略是先随机选择一个节点作为第一个节点,然后依次选择各个节点。 + 例如一个顺序可能是 B, C, D, A, B, C, D, A, B,另一个也可能是 D, + A, B, C, D,A, B, C, D, A 或者 C, D, A, B, C, D, A, B, C, D, A等等。 + + + 随机策略。每次都是随机选择一个节点来建立会话。 + + + 你可以实现自己的策略。只需要实现接口org.hornetq.api.core.client.loadbalance.ConnectionLoadBalancingPolicy即可。 + 根据你使用的是JMS还是核心接口,指定负载均衡的方法是有所不同的。如果你不指定策略,默认的策略是org.hornetq.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy. + 如果使用的是JMS,并且JMS连接工厂注册到JNDI,则你需要在hornetq-jms.xml文件中定义策略,如: + +<connection-factory name="ConnectionFactory"> + <discovery-group-ref discovery-group-name="my-discovery-group"/> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <connection-load-balancing-policy-class-name> + org.hornetq.api.core.client.loadbalance.RandomConnectionLoadBalancingPolicy + </connection-load-balancing-policy-class-name> +</connection-factory> + 上面的配置将部署一个连接工厂,它的连接负载均衡策略是随机策略。 + 如果使用JMS,但是你在客户端是直接创建连接工厂的实例,那么你需要用相应的方法在HornetQConnectionFactory上直接设置: + +ConnectionFactory jmsConnectionFactory = HornetQJMSClient.createConnectionFactory(...); +jmsConnectionFactory.setLoadBalancingPolicyClassName("com.acme.MyLoadBalancingPolicy"); + + 如果你使用核心接口的话,你要直接在ClientSessionFactory上设置策略: + +ClientSessionFactory factory = HornetQClient.createClientSessionFactory(...); +factory.setLoadBalancingPolicyClassName("com.acme.MyLoadBalancingPolicy"); + + 连接工厂进行负载均衡的服务器组可以有两种方法来确定: + + + 显式指定服务器 + + + 使用发现组功能 + + +
+
+ 显式指定集群服务器 + 有的网络并不开放UDP,所以就不能使用服务器发现功能来获取服务器列表。 + 在这种情况下,可以显式地在每个节点或客户端指定服务器的列表。下面介绍如何做: +
+ 在客户端指定服务器列表 + 根据使用的是JMS还是核心接口,所用的方法也不同。 +
+ 使用JMS时指定服务器列表 + 如果使用JMS,并且JMS连接工厂是注册到JNDI的话,你需要在服务器端的配置文件 + hornetq-jms.xml中来指定,如下面的例子: + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="my-connector1" + backup-connector-name="my-backup-connector1"/> + <connector-ref connector-name="my-connector2" + backup-connector-name="my-backup-connector2"/> + <connector-ref connector-name="my-connector3" + backup-connector-name="my-backup-connector3"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> +</connection-factory> + 其中的connection-factory内可以包含零或多个 + connector-ref。每个connector-ref + 都拥有connector-name属性和一个可选的backup-connector-name属性。connector-name 属性指向的是一个在hornetq-configuration.xml + 文件中定义的连接器。而backup-connector-name属性也是指向在 + hornetq-configuration.xml文件中定义的一个连接器。 + 有关连接器更多的信息参见 + 连接工厂这样就保存有一组[连接器, 备份连接器]对,用于客户端在创建连接时的负载均衡。 + 如果你使用JMS,但不使用JNDI,你可以直接创建HornetQConnectionFactory + 的实例,然后用相应的方法来设定连接器对列表,如下例:List<Pair<TransportConfiguration, TransportConfiguration>> serverList = + new ArrayList<Pair<TransportConfiguration, TransportConfiguration>>(); + +serverList.add(new Pair<TransportConfiguration, + TransportConfiguration>(liveTC0, backupTC0)); +serverList.add(new Pair<TransportConfiguration, + TransportConfiguration>(liveTC1, backupTC1)); +serverList.add(new Pair<TransportConfiguration, + TransportConfiguration>(liveTC2, backupTC2)); + +ConnectionFactory jmsConnectionFactory = HornetQJMSClient.createConnectionFactory(serverList); + +Connection jmsConnection1 = jmsConnectionFactory.createConnection(); + +Connection jmsConnection2 = jmsConnectionFactory.createConnection(); + 上面的代码中我们创建了一组TransportConfiguration对象。每个 + TransportConfiguration对象包括了如何连接某个特定服务器的信息。 + 然后,使用这个服务器列表创建了一个HornetQConnectionFactory实例。 + 这样通过这个工厂创建的连接就可以使用这个列表,由所用的客户连接负载均衡策略来进行连接的负载均衡。 +
+
+ 使用核心接口指定服务器列表 + 如果使用核心接口,你可以直接在ClientSessionFactory实例上设置服务器列表。 + 如下例: + List<Pair<TransportConfiguration, TransportConfiguration>> serverList = + new ArrayList<Pair<TransportConfiguration, TransportConfiguration>>(); + +serverList.add(new Pair<TransportConfiguration, + TransportConfiguration>(liveTC0, backupTC0)); +serverList.add(new Pair<TransportConfiguration, + TransportConfiguration>(liveTC1, backupTC1)); +serverList.add(new Pair<TransportConfiguration, + TransportConfiguration>(liveTC2, backupTC2)); + +ClientSessionFactory factory = HornetQClient.createClientSessionFactory(serverList); + +ClientSession sesison1 = factory.createClientSession(...); + +ClientSession session2 = factory.createClientSession(...); + 在上面的代码中我们创建了一组ClientSessionFactoryImpl对象。每个 + TransportConfiguration对象包括了如何连接某个特定服务器的信息。 + 有关信息请参见 + 然后,使用这个服务器列表创建了一个HornetQConnectionFactory实例。 + 这样通过这个工厂创建的会话就可以使用这个列表,由所用的客户连接负载均衡策略来进行连接的负载均衡。 +
+
+
+ 指定服务器列表以组成集群 + 下面我们考虑一个对称集群的例子,我们配置了每个集群连接,但是不使用发现功能来获得服务器信息。我们 + 采用配置的方法来显式指定集群的所有成员。 + 下面就是一个集群连接的配置: + <cluster-connections> + <cluster-connection name="my-explicit-cluster"> + <address>jms</address> + <connector-ref connector-name="my-connector1" + backup-connector-name="my-backup-connector1"/> + <connector-ref connector-name="my-connector2" + backup-connector-name="my-backup-connector2"/> + <connector-ref connector-name="my-connector3" + backup-connector-name="my-backup-connector3"/> + </cluster-connection> +</cluster-connections> + cluster-connection中可以包括零或多个connector-ref, + 每个connector-ref都有一个connector-name属性和 + 一个可选的backup-connector-name属性。connector-name属性指向一个在hornetq-configuration.xml文件中定义的一个连接器,它是主连接器。可选的 + backup-connector-name指向的也是在 + hornetq-configuration.xml文件中定义的一个连接器。 + 有关连接器的详细信息参见 + + 由于HornetQ 2.0.0的限制,使用静态节点列表的集群不支持失效备援(failover)。要想支持失效备援, + 就必须使用发现组。 + +
+
+
+ 消息再分配 + 集群的另一个重要功能是消息的再分配。前面我们知道在服务器端可以对消息大集群节点间进行轮流方式的负载均衡。如果 + forward-when-no-consumers参数为false,消息将不会转发到那些没有相应接收者的节点中。 + 这样可以有效避免了消息被送到一个不可能被接收的节点上。但仍然有一个问题无法解决:就是如果在消息发到一个节点后, + 它的接收者被关闭,那么这些消息仍然不能被接收了,造成了一种消息匮乏情形。 + 这种情况下如何处理? + 这里就需要消息再分配功能。通过配置,HornetQ可以将没有接收者的队列中的消息再次分配 + 到有接收者的节点上去。 + 通过配置,消息可以在队列最后一个接收者关闭时立即进行,也可以配置成等待一段时间再进行。默认消息再分配功能是 + 关闭的。 + 消息再分配功能可以基于地址进行配置,即在地址设置中指定再分配的延时。关于地址设置的更多信息,请参见 + + 下面是从hornetq-configuration.xml文件中提取的消息再分配的配置: + <address-settings> + <address-setting match="jms.#"> + <redistribution-delay>0</redistribution-delay> + </address-setting> + </address-settings> + 上面address-settings中设置的redistribution-delay值为0。它适用于所有以“jms“开头的 + 地址。由于所有JMS队列与话题订阅都绑定到以”jms“为开头的地址,所以上述配置的立即方式(没有延迟)消息 + 再分配适用于所有的JMS队列和话题订阅。 + match属性可以是精确匹配,也可以使用通配符。通配符要符合HornetQ的通配符 + 语法(在中描述)。 + redistribution-delay定义了队列最后一个接收者关闭后在进行消息再分配前所等待的 + 时间,单位毫秒。如果其值是0,表示立即进行消息再分配。-1表示不会进行消息再分配。 + 默认值是-1 + 通常为消息分配定义一个延迟是有实际意义的。很多时候当一个接收者被关闭时,很快就会有一个新的接收者被创建。 + 在这种情况下加一延迟可以使消息继续在本地进行接收,而不会将消息转发到别处。 +
+
+ 集群拓扑结构 + HornetQ集群可以有多种拓扑结构。我们来看两个最常见的结构。 +
+ 对称式集群 + 对称式集群可能是最常见的集群方式了。如果你接触过JBoss应用服务器的集群,你就对这种方式很熟悉。 + 在一个对称集群中,每一个节点都与集群中其它任一节点相连。换句话说,集群中任意两个节点的连接都 + 只有一跳(hop)。 + 要组成一个对称式的集群,每个节点在定义集群连接时要将属性max-hops + 设为1。通常集群连接将使用服务器发现的功能来获得集群中其它服务器的连接 + 信息。当然在UDP不可用的时候,也可以通过显式方式为集群连接指定服务器。 + 在对称集群中,每个服务器都知道集群中其它服务器中的所有队列信息,以及它们的接收者信息。利用这些 + 信息它可以决定如何进行消息的负载均衡及消息再分配。 +
+
+ 链式集群 + 在链式集群中,并不是每个节点都与其它任何节点直接相连,而是由两个节点组成头和尾,其余节点在中间连接 + 成为一个链的结构。 + 比如有三个节点A、B和C。节点A在一个网络中,它有许多消息的发送者向它发送订单消息。由于公司的政策,订单 + 的接收者需要在另一个网络中接收消息,并且这个网络需要经过其它第三个网络才可以访问。这种情况下我们将节点 + B部署到第三个网络中,作为节点A与节点C的中间节点将两个节点连接起来。当消息到达节点A时,被转发到节点B, + 然后又被转发到节点C上,这样消息就被C上的接收者所接收。节点A不需要直接与节点C连接,但是所有三个节点仍然 + 组成了一个集群。 + 要想组成一个这样的集群,节点A的集群连接要指向节点B,节点B的集群连接要指向C。本例我们只想组成一个单向 + 的链式集群,即我们只将消息按节点A->B->C的方向流动,而不要向 C->B->A方向流动。 + 对于这种集群拓扑,我们需要将max-hops设为2. 这个值可以使节点C上队列的信息传送到节点B,再传送到节点A。因此节点A就知道消息到达时即将 + 其转发给节点B。尽管节点B可能没有接收者,可它知道再经过一跳就可以将消息转到节点C,那里就有接收者了。 +
+
+
diff --git a/docs/user-manual/zh/configuration-index.xml b/docs/user-manual/zh/configuration-index.xml new file mode 100644 index 0000000000..6ac0f998b5 --- /dev/null +++ b/docs/user-manual/zh/configuration-index.xml @@ -0,0 +1,1284 @@ + + + + + + + + + + + + + + + + + + + + 配置参数索引 + 本章给出了HornetQ配置参数的索引,以便查阅。点击任意一个配置参数可以转到其所属的章节。 +
+ 服务器配置 +
+ hornetq-configuration.xml + HornetQ主要核心服务器配置文件 + + 服务器配置 + + + + + + + + 名称 + 类型 + 说明 + 默认值 + + + + + backup + Boolean + true表示本服务器是集群中另一个服务器的备份服务器 + false + + + backup-connector-ref + String + 用于连接备份服务器的连接器 + + + + bindings-directory + String + 保存持久绑定的目录the directory to store the persisted bindings to + data/bindings + + + clustered + Boolean + true表示服务器是集群中的节点 + false + + + connection-ttl-override + Long + 表示在接收到一个ping之前连接保持有效的时间(单位毫秒) + -1 + + + create-bindings-dir + Boolean + true表示服务器在启动时创建绑定的目录 + true + + + create-journal-dir + Boolean + true表示创建日志目录 + true + + + file-deployment-enabled + Boolean + true表示服务器从配置文件中读取配置 + true + + + id-cache-size + Integer + 预先生成的消息id的缓存大小 + 2000 + + + journal-buffer-size + Long + 日志内部缓存的大小 + 128 KiB + + + journal-buffer-timeout + Long + T将日志缓冲数据刷新的等待时间(纳秒) + 20000 + + + journal-compact-min-files + Integer + 开始整理数据的最小数据文件数。 + 10 + + + journal-compact-percentage + Integer + 开始压缩日志时的有效数据百分比。 + 30 + + + journal-directory + String + 日志文件所在的位置 + data/journal + + + journal-file-size + Long + 每个日志文件的大小(字节) + 128 * 1024 + + + journal-max-io + Integer + 某一时刻保存在AIO队列中的最大写请求数 + 500 + + + journal-min-files + Integer + 预先创建的日志文件数 + 2 + + + journal-sync-transactional + Boolean + 如果是true,等事务数据同步到日志后再向客户端返回 + true + + + journal-sync-non-transactional + Boolean + 如果是true,等非事务数据到日志后再向客户端返回 + true + + + journal-type + ASYNCIO|NIO + 日志存取的方式 + ASYNCIO + + + jmx-management-enabled + Boolean + true表示通过JMX可以使用管理接口 + true + + + jmx-domain + String + 用于HornetQ MBean注册到MBeanServer的JMX域名 + org.hornetq + + + large-messages-directory + String + 存放大消息的目录 + data/largemessages + + + management-address + String + 管理消息发送的地址 + jms.queue.hornetq.management + + + cluster-user + String + 集群连接的用户名 + HORNETQ.CLUSTER.ADMIN.USER + + + cluster-password + String + 集群连接的用户密码 + CHANGE ME!! + + + management-notification-address + String + 用于接收管理通知的地址 + hornetq.notifications + + + message-counter-enabled + Boolean + true表示使用消息计数器 + false + + + message-counter-max-day-history + Integer + 消息计数器历史保存的天数 + 10 + + + message-counter-sample-period + Long + 消息计数器取样的间隔(毫秒) + 10000 + + + message-expiry-scan-period + Long + 过期消息扫描周期(毫秒) + 30000 + + + message-expiry-thread-priority + Integer + 过期消息线程的优先级 + 3 + + + paging-directory + String + 分页转存消息的保存目录 + data/paging + + + + persist-delivery-count-before-delivery + Boolean + true表示传递计数在传递之前保存。false表示只有当消息被取消时才保存。 + false + + + persistence-enabled + Boolean + true表示服务器使用基于文件的日志做持久化 + true + + + persist-id-cache + Boolean + true表示id被保存到日志中 + true + + + scheduled-thread-pool-max-size + Integer + 可计划线程池的线程数。 + 5 + + + security-enabled + Boolean + true表示使用安全功能 + true + + + security-invalidation-interval + Long + 安全缓存的有效时间(毫秒) + 10000 + + + thread-pool-max-size + Integer + 主线程池的线程数。-1表示数量不限 + -1 + + + async-connection-execution-enabled + Boolean + 接收的数据包是否由线程池的线程来处理 + true + + + transaction-timeout + Long + 事务在建立后经过多长时间后可以从资源管理器(resource manager)删除(毫秒) + 60000 + + + transaction-timeout-scan-period + Long + 扫描超时事务的间隔(毫秒) + 1000 + + + wild-card-routing-enabled + Boolean + true表示服务器支持通配符路由 + true + + + memory-measure-interval + Long + 采样JVM内存的周期(毫秒,-1表示不采样) + -1 + + + memory-warning-threshold + Integer + 可用内存达到这个百分比时,给出警告信息 + 25 + + + connectors + Connector + 连接器的配置 + + + + + connector.name (attribute) + String + 连接器的名字-必需指定的参数 + + + + + connector.factory-class + String + 连接工厂的实现类名-必需指定的参数 + + + + + connector.param + 连接器的配置参数 + 一个键-值对,表示一个连接器的参数配置。一个连接器可以有多个这样的参数 + + + + + connector.param.key (属性) + String + 参数的键 - 必需指定的参数 + + + + + connector.param.value (attribute) + String + 参数的值 - 必需指定的参数 + + + + + acceptors + Acceptor + 一组接收器 + + + + + acceptor.name (属性) + String + 接收器的名字 - 可选 + + + + + acceptor.factory-class + String + 接收器工厂实现类名 - 必需指定的参数 + + + + + acceptor.param + 一个接收器的配置参数 + 用来配置接收器的键-值对。一个接收器可以有多个参数。 + + + + + acceptor.param.key (属性) + String + 参数的键 - 必需指定的参数 + + + + + acceptor.param.value (attribute) + String + 参数的值 - 必需指定的参数 + + + + broadcast-groups + BroadcastGroup + 一组广播组 + + + + + broadcast-group.name (attribute) + + String + 广播组的名字(必需是唯一的)- 必需指定的参数 + + + + + broadcast-group.local-bind-address + + String + 数据报文套接字的本地绑定地址 + 内系统内核选择的IP地址 + + + + broadcast-group.local-bind-port + + Integer + 数据报文套接字的本地绑定端口 + -1 (匿名端口) + + + + broadcast-group.group-address + + String + 广播地址 - 必需指定的参数 + + + + + broadcast-group.group-port + + Integer + 广播使用的UDP端口 - 必需指定的参数 + + + + + broadcast-group.broadcast-period + + Long + 广播的时间间隔(毫秒) + 2000 + + + + broadcast-group.connector-ref + + 一个连接器对 + 广播的一个连接器和一个可选的备份连接器。一个广播组可以有多个这样的连接器对 + + + + + broadcast-group.connector-ref.connector-name (attribute) + + String + 主连接器名 - 必需指定的参数 + + + + + broadcast-group.connector-ref.backup-connector-name (attribute) + + String + 备份连接器名 - 可选的参数 + + + + discovery-groups + DiscoveryGroup + 一组发现组 + + + + discovery-group.name (属性) + String + 发现组的名字(具有唯一性) - 必需指定的参数 + + + + + discovery-group.local-bind-address + + String + 发现组所绑定的本地地址 + + + + + discovery-group.group-address + + String + 发现组监听的广播IP地址 - 必需指定的参数 + + + + + discovery-group.group-port + + Integer + 广播组监听的UDP端口 - 必需指定的参数 + + + + + discovery-group.refresh-timeout + + Integer + 发现组等待更新的时间。如果某个服务器上次广播到达后经过这个时间后还没有收到下次广播,那么 + 该服务器的连接器对将从列表中删除 + 5000 (毫秒) + + + diverts + Divert + 一组转发器 + + + + divert.name (attribute) + String + 转发器的名字(必需是唯一的) - 必需指定的参数 + + + + divert.routing-name + String + 转发器的路由名称 - 必需指定的参数 + + + + divert.address + String + 转发器的源地址 - 必需指定的参数 + + + + divert.forwarding-address + String + 转发器的转发地址 - 必需指定的参数 + + + + divert.exclusive + Boolean + 转发器是否是唯一的 + false + + + divert.filter + String + 可选的核心过滤器表达式 + null + + + divert.transformer-class-name + String + 可选的转换器的名字 + + + + queues + Queue + 一组预先配置的队列 + + + + queues.name + (属性) + String + 队列独特的名字 + + + + queues.address + String + 队列的地址 - 必需指定的参数 + + + + queues.filter + String + 队列可选的核心过滤器表达式 + null + + + queues.durable + Boolean + 是否持久队列 + true + + + bridges + Bridge + 一组桥 + + + + bridges.name + (属性) + String + 桥的独特名字 + + + + bridges.queue-name + String + 桥接收消息的源队列名 - 必需指定的参数 + + + + bridges.forwarding-address + String + 桥要转发的地址。如果没有指定则使用原始的地址 + null + + + bridges.filter + String + 可选的核心过滤器表达式 + null + + + bridges.transformer-class-name + String + 可选的转换器类名 + null + + + bridges.retry-interval + Long + 重试的时间间隔(毫秒) + 2000 ms + + + bridges.retry-interval-multiplier + Double + 重试间隔的递增系数 + 1.0 + + + bridges.reconnect-attempts + Integer + 最大重试次数,-1代表无限次 + -1 + + + bridges.failover-on-server-shutdown + Boolean + 如果目标服务器正常关机是否仍进行失效备援 + false + + + bridges.use-duplicate-detection + Boolean + 是否在转发的消息中添加重复检测的头 + true + + + bridges.discovery-group-ref + String + 桥使用的发现组名 + null + + + bridges.connector-ref.connector-name + (属性) + String + 主连接的连接器名 + + + + bridges.connector-ref.backup-connector-name + (属性) + String + 备份连接的连接器名(可选) + null + + + cluster-connections + ClusterConnection + 一组集群连接 + + + + cluster-connections.name (attribute) + String + 集群连接的独特名字 + + + + cluster-connections.address + String + 集群连接的地址名 + + + + cluster-connections.forward-when-no-consumers + Boolean + 如果目标没有合适的接收者,是否仍然向它分配消息? + false + + + cluster-connections.max-hops + Integer + 集群拓扑中的最大跳数(hops) + 1 + + + cluster-connections.retry-interval + Long + 集群连接重试的间隔(毫秒) + 2000 + + + cluster-connections.use-duplicate-detection + Boolean + 是否在转发的消息中添加重复检测的消息头 + true + + + cluster-connections.discovery-group-ref + String + 桥所使用的发现组的名字 + null + + + cluster-connections.connector-ref.connector-name + (属性) + String + 主连接的连接器名字 + + + + cluster-connections.connector-ref.backup-connector-name + (属性) + String + 可选的备份连接所使用的连接器名字 + null + + + security-settings + SecuritySetting + 一组安全设置 + + + + security-settings.match + (属性) + String + 安全所应用的地址匹配字符串 + + + + security-settings.permission + 安全许可 + 地址的一个许可 + + + + security-settings.permission.type (attribute) + 许可类型 + 许可的类型 + + + + security-settings.permission.roles (attribute) + Roles + 以逗号分隔的一组角色,这些角色将拥有相应的许可 + + + + address-settings + AddressSetting + 一组地址设置 + + + + address-settings.dead-letter-address + String + 死消息所发往的地址 + + + + address-settings.max-delivery-attempts + Integer + 发往死信地址之前所尝试的传递次数 + 10 + + + address-settings.expiry-address + String + 过期消息所发往的地址 + + + + address-settings.redelivery-delay + Long + 重新传递一个取消的消息前所等待的时间(毫秒) + 0 + + + address-settings.last-value-queue + boolean + 队列是否是一个最新值队列 + false + + + address-settings.page-size-bytes + Long + 一个地址的分页的大小(字节) + 10 * 1024 * 1024 + + + address-settings.max-size-bytes + Long + 地址的分页转存的最大值(字节) + -1 + + + address-settings.redistribution-delay + Long + 队列最后一个接收者关闭后需要等待多长时间再将消息重新分配(毫秒) + -1 + + + +
+
+
+ hornetq-jms.xml + 该文件是服务器端JMS服务所使用的,用来装载JMS队列,话题和连接工厂。 + + JMS服务器配置 + + + + + + + + 名称 + 类型 + 说明 + 默认值 + + + + + + connection-factory + + ConnectionFactory + 一组注册到JNDI的连接工厂 + + + + + connection-factory.signature (属性) + + String + 连接工厂的类型 + generic + + + + connection-factory.xa + + Boolean + 是否是XA类型的连接工厂 + false + + + + connection-factory.auto-group + + Boolean + 是否自动使用消息组 + false + + + connection-factory.connectors + + String + 一组供连接工厂使用的连接器 + + + + connection-factory.connectors.connector-ref.connector-name (属性) + + String + 连接主服务器的连接器名 + + + + connection-factory.connectors.connector-ref.backup-connector-name (attribute) + + String + 连接备份服务器的连接器名 + + + + connection-factory.discovery-group-ref.discovery-group-name (属性) + + String + 连接工厂的发现组名 + + + + + connection-factory.discovery-initial-wait-timeout + + Long + 发现组首次等待广播的时间 + 10000 + + + + connection-factory.block-on-acknowledge + + Boolean + 消息是否以同步方式通知 + false + + + + connection-factory.block-on-non-durable-send + + Boolean + 是否以同步方式发送非持久消息 + false + + + + connection-factory.block-on-durable-send + + Boolean + 是否以同步方式发送持久消息 + true + + + connection-factory.call-timeout + Long + 远程调用超时时间(毫秒) + 30000 + + + + connection-factory.client-failure-check-period + + Long + 客户端如果在这个时间内没有收到服务器数据包,将认为连接出现故障。 + 5000 + + + + connection-factory.client-id + + String + 连接工厂预先配置的客户ID + null + + + + + connection-factory.connection-load-balancing-policy-class-name + + String + 负载均衡类名 + org.hornetq.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy + + + + connection-factory.connection-ttl + + Long + 连接的存活时间(毫秒) + 1 * 60000 + + + + connection-factory.consumer-max-rate + Integer + 接收者每秒钟接收消息的最快速度 + -1 + + + + connection-factory.consumer-window-size + Integer + 接收者流控制容器大小(字节) + 1024 * 1024 + + + + connection-factory.dups-ok-batch-size + Integer + 在DUPS_OK_ACKNOWLEDGE模式下批量通知的大小(字节) + 1024 * 1024 + + + connection-factory.failover-on-initial-connection + Boolean + 如果首次连接主服务器失败是否失效备援连接到备份服务器 + false + + + + connection-factory.failover-on-server-shutdown + Boolean + 在服务器停机时是否进行失效备援 + false + + + + connection-factory.min-large-message-size + Integer + 大消息的最小值,大小超过该值的按大消息处理 + 100 * 1024 + + + connection-factory.cache-large-message-client + Boolean + true表示这个连接工厂会将大消息保存在临时文件中 + false + + + + connection-factory.pre-acknowledge + Boolean + 是否在消息发送之前提前通知 + false + + + + connection-factory.producer-max-rate + Integer + 发送消息的最大速度 + -1 + + + connection-factory.producer-window-size + Integer + 发送者发送消息的窗口大小 + 1024 * 1024 + + + + connection-factory.confirmation-window-size + + Integer + 会话恢复的确认窗口大小(字节) + 1024 * 1024 + + + + connection-factory.reconnect-attempts + + Integer + 重试的最大次数, -1 表示无限次 + 0 + + + + connection-factory.retry-interval + + Long + 每次重试的时间间隔(毫秒) + 2000 + + + + connection-factory.retry-interval-multiplier + + Double + 重试间隔时间的递增系数 + 1.0 + + + connection-factory.max-retry-interval + Integer + 最大重试间隔。 + 2000 + + + + connection-factory.scheduled-thread-pool-max-size + + Integer + 可计划线程池的大小 + 5 + + + + connection-factory.thread-pool-max-size + + Integer + 线程池大小 + -1 + + + + + connection-factory.transaction-batch-size + + Integer + 使用事务性会话时发送通知的批量大小(字节) + 1024 * 1024 + + + + connection-factory.use-global-pools + + Boolean + 是否使用全局线程池 + true + + + queue + Queue + 创建并注册到JNDI的队列 + + + + queue.name + (属性) + String + 队列的唯一名字 + + + + queue.entry + String + 队列的JNDI的上下文(context)。一个队列可以有多个JNDI的上下文 + + + + queue.durable + Boolean + 是否持久队列 + true + + + queue.filter + String + 可选的队列过滤器表达式 + + + + topic + Topic + 创建并注册到JNDI的话题 + + + + topic.name + (属性) + String + 话题的唯一名 + + + + topic.entry + String + 话题的JNDI上下文(context)。一个话题可以有多个上下文。 + + + + +
+
+
+
diff --git a/docs/user-manual/zh/configuring-transports.xml b/docs/user-manual/zh/configuring-transports.xml new file mode 100644 index 0000000000..123051a569 --- /dev/null +++ b/docs/user-manual/zh/configuring-transports.xml @@ -0,0 +1,376 @@ + + + + + + + + + + + + + + + + + + + + 传输层的配置 + HornetQ的传输层是“可插拔的”。通过灵活的配置和一套服务提供接口(SPI),HornetQ可以很容易地更换其传输层。 + 在本章中我们将对HornetQ的传输相关的概念作出解释,并说明它的配置方法。 +
+ 接收器(Acceptor) + 接收器(acceptor)是 HornetQ 的传输层中最为重要的概念之一。首先 + 介绍一下在文件hornetq-configuration.xml中是怎样定义一个接收器的: + +<acceptors> + <acceptor name="netty"> + <factory-class> +org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + </factory-class> + <param key="port" value="5446"/> + </acceptor> +</acceptors> + + 所有接收器都在 acceptors单元(element)内定义。在acceptors + 内可以有零个或多个接收器的定义。每个服务器所拥有的接收器的数量是没有限制的。 + 每个接收器都要定义其与HornetQ服务器连接的方式。 + 以上的例子中我们定义了一个Netty接收器。它在端口5446监听连接请求。 + acceptor单元内有一个子单元factory-class。这个单元是用来 + 定义创建连接器的工厂类。一个连接器工厂类必须要实现AcceptorFactory接口。上例中我们定义 + 的连接器工厂是类NettyAcceptorFactory使用Netty来建立连接。有个这个类定义,HornetQ就知道了用什么传输来建立连接了。 + acceptor中还可以配置零或多个参数param。在每个param + 中定义的是键-值对(key-value)。这些参数用来配置某个传输实现。不同传输有不同的配置参数。 + 像IP地址、端口号等都是传输配置参数的例子。 +
+
+ 连接器(Connectors) + 接收器定义的是如何在服务器端接收连接,而连接器则是定义客户端如何连接到服务器。 + 以下是hornetq-configuration.xml文件中一个连接器配置的例子。 + +<connectors> + <connector name="netty"> + <factory-class> + org.hornetq.core.remoting.impl.netty.NettyConnectorFactory + </factory-class> + <param key="port" value="5446"/> + </connector> +</connectors> + + 连接器的配置在connectors单元中。可以定义一个或多个连接器。每个服务器配置的连接器 + 数量是没有限制的。 + 你可能注意到了,既然连接器是定义客户端如何连接服务器的,那么为什么要定义在 + 服务器端呢?原因如下: + + + 服务器有时也需要做为客户端去连接其它的服务器,比如当一个服务器通过桥连接到另一个服务器,或者是集群 + 中服务器之间的互相通迅。在这种情况下服务器就要知道如何与另一台服务器建立连接。因此需要在 + connectors下定义连接器。 + + + 如果你使用JMS服务,需要创建连接工厂的实例并绑定到JNDI。在HornetQ创建 + HornetQConnectionFactory时需要连接器的必要信息,以便这个连接工厂 + 能知道它如何与HornetQ服务器相连接。 + 这一信息被定义在配置文件hornetq-jms.xml中的connector-ref单元下。下面这段配置 + 就是从该配置文件中提取的相关部分,它展示了JMS的连接工厂是如何引用定义在配置文件hornetq-configuration.xml中的连接器的: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + <entry name="XAConnectionFactory"/> + </entries> +</connection-factory> + + + +
+
+ 在客户端直接配置传输层 + 怎样配置一个内核ClientSessionFactory以让它知道如何连接服务器的信息呢? + 在直接配置内核ClientSessionFactory的时候,可以间接地使用连接器。当然在这种情况 + 下在服务器端定义连接器是没有意义的。我们通过将必要参数传给ClientSessionFactory的 + 方法来告诉使用什么样的连接器工厂。 + 在下面的例子中,我们创建了一个ClientSessionFactory,它可以直接连接到我们先前定 + 义的接收器上。它使用的是标准的Netty TCP传输层,连接主机是localhost(默认),端口5446: + +Map<String, Object> connectionParams = new HashMap<String, Object>(); + +connectionParams.put(org.hornetq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, + 5446); + +TransportConfiguration transportConfiguration = + new TransportConfiguration( + "org.hornetq.core.remoting.impl.netty.NettyConnectorFactory", + connectionParams); + +ClientSessionFactory sessionFactory = HornetQClient.createClientSessionFactory(transportConfiguration); + +ClientSession session = sessionFactory.createSession(...); + +etc + + 如果在客户端直接使用JMS的连接工厂的话,也可以用类似的方法而不需要在服务器端定义连接器或在 + hornetq-jms.xml配置文件中创建连接工厂: + +Map<String, Object> connectionParams = new HashMap<String, Object>(); + +connectionParams.put(org.hornetq.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, 5446); + +TransportConfiguration transportConfiguration = + new TransportConfiguration( + "org.hornetq.core.remoting.impl.netty.NettyConnectorFactory", + connectionParams); + +ConnectionFactory connectionFactory = HornetQJMSClient.createConnectionFactory(transportConfiguration); + +Connection jmsConnection = connectionFactory.createConnection(); + +etc + +
+
+ 配置 Netty 传输层 + HornetQ当前使用Netty作为其默认的连接层。Netty是一个高性能的底层网络库. + Netty传输的配置有几种不同的方法。它可以使用传统的Java IO(阻塞方式)、NIO(非阻塞)或直接使用 + TCP socket及SSL。或者使用HTTP或HTTPS协议。同时还可能使用servlet进行传输。 + 采用Netty应该能满足绝大部分的传输要求。 +
+ 配置 Netty TCP + Netty TCP 是简单的非加密的基于TCP socket的传输。它可以使用阻塞式的Java IO或非阻塞式的Java NIO。 + 我们建议在服务器端采用非阻塞式的NIO以获得良好的并发处理能力。当并发能力并不是很重要时,可以使用阻塞式 + 的方式以增加响应的速度。 + 如果你的应用是运行在不信任的网络上,你应该选择使用SSL或HTTPS。 + Netty TCP的所有连接都是从客户端发起的。服务器端不向客户端发起任何连接。在有防火墙的环境中,这种方式 + 是比较适合的。因为防火墙只允许单方向的连接。 + org.hornetq.core.remoting.impl.netty.TransportConstants类中定义了所 + 有的配置参数的名称(key)。它们当中绝大多娄既用于配置接收器也用于配置连接器,有一些只适用于接收器。 + 下面列出的参数用以配置一个简单的Netty TCP: + + + use-nio。如果设为true则使用非阻塞的Java + NIO。如果false则使用传统的阻塞方式的Java IO。 + 我们建议使用Java NIO处理并行连接。因为Java NIO不是为每一个连接分配一个线程,所以它要比传统的阻塞式 + Java IO具有更强的并发连接的处理能力。如果你不需要处理并发连接,那么使用旧的阻塞式的IO性能会好一些。这个参 + 数的默认值在服务器端是false,在客户端是false。 + + + + host。主机名或IP地址。对于接收器来说,它是服务器接收连接的地址。 + 对于连接器端,它是客户端连接的目标地址。默认值是localhost。 + 在配置接收器时可以指定多个主机名或IP地址,中间用逗号隔开。如果指定的主机是0.0.0.0, + 则接收器将从主机上所有的网络接口中接受连接请求。连接器不允许指定多个主机地址,它只能与一个 + 地址建立连接。 + + 一定不要忘记指定一个主机名或IP地址!一个服务器要想接受来自其它节点的连接就必需有一个 + 主机名或IP地址来绑定及监听外部的连接请求。默认的主机名localhost是不能接受外部的 + 连接请求的! + + + + port。连接的端口。用于配置连接器或接收器。连接器用此端口来建立 + 连接。接收器在些端口上监听连接请求。默认值是5445 + + + tcp-no-delay。将它设为true就会使用 + Nagle + 算法.默认值是true + + + tcp-send-buffer-size。这个参数指定了TCP的发送缓冲大小,单位是字节。 + 默认值是32768字节(32KiB)。 + 这个参数要根据你的网络的带宽与时延的情况而调整。 + 这个链接对此有很好的论述。 + 简言之,TCP的发送/接收缓冲的大小可以用下面公式来计算: + + 缓冲大小 = 带宽 * RTT + + 其中带宽的单位是 每秒字节数,RTT(网络往返程时间)的单位是秒。 + 使用ping工具可以方便地测量出RTT。 + 对于快速网络可以适当加大缓冲的大小。 + + + tcp-receive-buffer-size。这个参数指定了TCP接收缓冲的大小,单位是字节。 + 默认值是32768字节(32KiB)。 + + + batch-delay。HornetQ可以通过配置该参数,在数据包写入传输层之前有一个 + 最大延时(毫秒),达到批量写入的目的。这样可以提高小消息的发送效率。但这样做会增加单个消息的平均发送 + 延迟。默认值为0毫秒。 + + + direct-deliver。消息到达服务器后,默认是由一个不同的线程来将消息传递 + 到接收者。这样可以使服务的呑吐量和可扩展性达到最佳,特别是在多核的系统上效果更为明显。但是线程切换 + 会带来一些传递的延迟。如果你希望延迟最小,并不在意呑吐量的话,可以将参数direct-deliver设为true。默认值是true。如果你更希望有 + 较大的呑吐量的话,将它设为false + + + nio-remoting-threads。如果使用NIO,默认情况下HornetQ会使用系统中处理 + 器内核(或超线程)数量三倍的线程来处理接收的数据包。内核的数量是通过调用Runtime.getRuntime().availableProcessors()来得到的。如果你想改变这个数量, + 你可以设定本参数。默认的值是-1,表示线程数为Runtime.getRuntime().availableProcessors() * 3。 + + +
+
+ 配置Netty SSL + Netty SSL的配置与Netty TCP相似。它采用了安全套接字层(SSL)来提供加密的TCP连接。 + 我们提供了一个Netty SSL的例子来演示其配置和应用。 + Netty SSL拥有Netty TCP一样的参数,另外还有下列的附加参数: + + + ssl-enabled。必须设为true以使用SSL。 + + + key-store-path。存放SSL密钥的路径(key store)。这是存放客户端证书的地方。 + + + key-store-password。用于访问key store的密码。 + + + trust-store-path。服务器端存放可信任客户证书的路径。 + + + trust-store-password。用于访问可信任客户证书(trust store)的密码。 + + +
+
+ 配置Netty HTTP + Netty HTTP 通过HTTP通道传送数据包。在有些用户环境中防火墙只允许有HTTP通信,这时采用Netty HTTP作为HornetQ + 的传输层就能解决问题。 + 我们提供了一个Netty HTTP的例子来演示其配置和应用。 + Netty HTTP具有和Netty TCP同样的配置参数,另外它还有以下参数: + + + http-enabled。如果要使用HTTP,这个参数必须设为true + + + http-client-idle-time。客户端空闲时间。如果客户端的空闲时间超过 + 这个值,Netty就会发送一个空的HTTP请求以保持连接不被关闭。 + + + http-client-idle-scan-period。扫描空闲客户端的间隔时间。单位是毫秒。 + + + http-response-time。服务器端向客户端发送空的http响应前的最大等待时间。 + + + http-server-scan-period。服务器扫描需要响应的客户端的时间间隔。单位是毫秒。 + + + http-requires-session-id。如果设为true,客户端在第一次请求后将等待 + 接收一个会话ID。http 连接器用它来连接servlet接收器(不建议这样使用)。 + + +
+
+ 配置Netty Servlet + HornetQ可以使用Netty servlet来传输消息。使用servlet可以将HornetQ的数据通过HTTP传送到一个 + 运行的servlet,再由servlet转发给HornetQ服务器。 + servlet与HTTP的不同之处在于,当用HTTP传输时,HornetQ如同一个web服务器,它监听在某个端口上的HTTP + 请求并返回响应。比如80端口或8080端口。而当使用servlet时,HornetQ的传输数据是通过运行在某一servlet容器 + 中的一个特定的servlet来转发的。而这个sevlet容器中同时还可能运行其他的应用,如web服务。当一个公司有多个应用 + 但只允许一个http端口可以访问时,servlet传输可以很好的解决HornetQ的传输问题。 + 请参见HornetQ所提供的servlet例子来了解详细的配置方法。 + 要在HornetQ中使用Netty servlet传输方式,需要以下步骤: + + + 部署servlet。下面是一个web.xml例子: + <?xml version="1.0" encoding="UTF-8"?> +<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" + version="2.4"> + <servlet> + <servlet-name>HornetQServlet</servlet-name> + <servlet-class>org.jboss.netty.channel.socket.http.HttpTunnelingServlet</servlet-class> + <init-param> + <param-name>endpoint</param-name> + <param-value>local:org.hornetq</param-value> + </init-param> + <load-on-startup>1</load-on-startup> + </servlet> + + <servlet-mapping> + <servlet-name>HornetQServlet</servlet-name> + <url-pattern>/HornetQServlet</url-pattern> + </servlet-mapping> +</web-app> + + + + + 我们还需要在服务器端加上一个特殊的Netty invm 接收器。 + 下面是从hornetq-configuration.xml配置文件中摘取的定义接收器的配置部分: + +<acceptors> + + <acceptor name="netty-invm"> + <factory-class> + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + </factory-class> + <param key="use-invm" value="true"/> + <param key="host" value="org.hornetq"/> + </acceptor> + +</acceptors> + + + + 最后我们需要在客户端配置连接器,也是在hornetq-configuration.xml文件中来做。如下所示: + <connectors> + + <connector name="netty-servlet"> + <factory-class> + org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory + </factory-class> + <param key="host" value="localhost"/> + <param key="port" value="8080"/> + <param key="use-servlet" value="true"/> + <param key="servlet-path" value="/messaging/HornetQServlet"/> + </connector> + + </connectors> + + + 下面列出了初始化参数以及它们的用途: + + + endpoint - Netty接收器的名字。servlet将向它转发数据包。它与host参数的值是对应的。 + + + web.xml中定义的servlet的URL形式与在连接器配置文件中定义的 + servlet-path值应该相匹配。 + servlet可以与SSL一起使用。只需要在连接器配置中加上下面的配置即可: <connector name="netty-servlet"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + <param key="host" value="localhost"/> + <param key="port" value="8443"/> + <param key="use-servlet" value="true"/> + <param key="servlet-path" value="/messaging/HornetQServlet"/> + <param key="ssl-enabled" value="true"/> + <param key="key-store-path" value="path to a keystoree"/> + <param key="key-store-password" value="keystore password"/> + </connector> + + 另外你还需要为服务器指定一个KeyStore。打开server/default/deploy/jbossweb.sar + 下的server.xml文件,按照下面的内容编辑其中的SSL/TLS连接器配置:<Connector protocol="HTTP/1.1" SSLEnabled="true" + port="8443" address="${jboss.bind.address}" + scheme="https" secure="true" clientAuth="false" + keystoreFile="path to a keystore" + keystorePass="keystore password" sslProtocol = "TLS" /> + +SSL需要keystore和访问密码。参见servlet ssl例子以了解更多的有关信息。 +
+
+
diff --git a/docs/user-manual/zh/connection-ttl.xml b/docs/user-manual/zh/connection-ttl.xml new file mode 100644 index 0000000000..c9ff36f8d3 --- /dev/null +++ b/docs/user-manual/zh/connection-ttl.xml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + 失效连接的检测 + 本章将讨论连接的生存时间(TTL)以及HornetQ如何处理出现故障的客户端或者异常退出的客户端(即客户端在 + 退出时没有合理的关闭相关资源)。 +
+ 服务器端对失效连接的清除 + 当客户端的应用程序退出时,应该关闭所使用的资源。在finally进行资源的关闭 + 是一个很好的方法。 + 下面的例子中,一个Hornet客户端在finally中关闭了它的会话(session)和会话工厂(session factory): + +ClientSessionFactory sf = null; +ClientSession session = null; + +try +{ + sf = HornetQClient.createClientSessionFactory(...); + + session = sf.createSession(...); + + ... do some stuff with the session... +} +finally +{ + if (session != null) + { + session.close(); + } + + if (sf != null) + { + sf.close(); + } +} + + 下面的例子给出了一个JMS客户端是如何适当关闭相关资源的: + +Connection jmsConnection = null; + +try +{ + ConnectionFactory jmsConnectionFactory = HornetQJMSClient.createConnectionFactory(...); + + jmsConnection = jmsConnectionFactory.createConnection(); + + ... do some stuff with the connection... +} +finally +{ + if (connection != null) + { + connection.close(); + } +} + + 然而有时候资源在客户端得不到合理的关闭。有的客户端应用在结束时忘记了关闭资源,有的客户端有时发生故障导致 + 程序突然中断,相关资源也没有来得及关闭! + 如果上述情况发生了,那么这些资源就会留在服务器端而不会被清理。这就会造成资源泄漏现象并最終导致服务器内存 + 溢出或其它资源的溢出错误。 + 因此在服务器端要有某种机制来避免资源的泄漏。也就是对无效资源进行回收。在判断什么是无效资源时,HornetQ + 考虑到了客户端重新连接的情况。就是当一个连接由于网络临时中断后又恢复正常时,客户端有可能通过不断重试 + 成功地连接到服务器端。如果服务器端过早清除了相关的连接资源,则客户端就可能重试失败。 + HornetQ的资源回收是完全可配置的。每个 ClientSessionFactory 有一个连接 TTL的参数。 + 这个参数的意义是当客户端的一个连接没有任何数到达服务器时,服务器充许这个连接有效的最长时间。客户端通过定 + 时向服务器端发送“ping“数据包来维持连接的有效,以免被服务器关掉。如果服务器在TTL指定的时间内没有收到任何 + 数据包,则认为该连接无效,继而关闭与该连接相关的所有的会话(session)。 + 如果使用JMS,HornetQConnectionFactoryConnectionTTL + 属性是用来定义连接的存活时间的。如果你将JMS连接工厂部署到JNDI中,则应使用配置文件中的connection-ttl参数来定义连接的TTL。 + 默认的连接TTL值是60000毫秒,即一分钟。 ConnectionTTL + 设为-1表示服务器永远不检测超时的连接。 + 如果你不想让客户端来规定连接存活时间(TTL),你可以在服务器端的配置文件中定义 + connection-ttl-override属性。它的默认值是-1,表示 + 服务器端该属性无效(即客户端可以定义自己的连接TTL)。 +
+ 关闭没有被成功关闭的核心会话或JMS连接 + 如前所述,在使用完毕后在finally中将所有的核心会话或JMS连接关闭是十分重要的。 + 如果你没有这样做,HornetQ会在拉圾回收时进行检测并会在日志中打印类似以下的警告(如果是JMS则在警告中 + 是相应的JMS连接): + + +[Finalizer] 20:14:43,244 WARNING [org.hornetq.core.client.impl.DelegatingSession] I'm closin +g a ClientSession you left open. Please make sure you close all ClientSessions explicitly before let +ting them go out of scope! +[Finalizer] 20:14:43,244 WARNING [org.hornetq.core.client.impl.DelegatingSession] The sessi +on you didn't close was created here: +java.lang.Exception +at org.hornetq.core.client.impl.DelegatingSession.<init>(DelegatingSession.java:83) +at org.acme.yourproject.YourClass (YourClass.java:666) + + + HornetQ然后将未关闭的连接/会话关闭。 + 注意在日志的警告中还给出了创建JMS连接/客户端会话的具体行号,以便准确地确定出错的地方。 +
+
+
+ 客户端的故障检测 + 前面讲述了客户端如何向服务器发送ping以及服务器端如何清理失效的连接。发送ping还有另外一个目的,就是能 + 让客户端检测网络或服务器是否出现故障。 + 从客户端的角度来看,只要客户端能从一个连接不断接收服务器的数据,那么这个连接就被认为是一个有效的连接。 + 如果在属性client-failure-check-period所定义的时间内(单位毫秒)客户端没有 + 收到任何数据,客户端就认为这们连接发生了故障。根据不同的配置,客户端在这种情况下要么进行failover,要么 + 调用FailureListener的接口(或者是JMS的ExceptionListener)。 + 如果使用JMS,这个参数是HornetQConnectionFactoryClientFailureCheckPeriod。 + 如果你向JNDI部署JMS连接工厂,那么相应的参数在hornetq-jms.xml配置文件中,参数名 + 为client-failure-check-period + 这个参数的默认值是30000毫秒,即半分钟。-1表示客户端不检查 + 连接的有效性。即不论是否有数据来自服务器,连接都一直有效。这一参数通常要比服务器端的连接TTL小许多,以使 + 客户端在出现短暂连接故障的情况下可以与服务器成功地重新连接。 +
+
+ 配置异步连接任务执行 + 默认情况下,服务器接收到的数据包被远程模块的线程处理。 + 为了避免远程模块的线程被长时间占用,数据包可以转给另外的一个线程池来处理。要注意这样做的增加了一些时间延迟。 + 因此如果数据包处理耗时很少,还是由远程模块线程来处理较好。 + + 要配置这样的异步连接很行任务,将hornetq-configuration.xml文件中的 + async-connection-execution-enabled 参数设为true + (默认值是 true)。 +
+
diff --git a/docs/user-manual/zh/core-bridges.xml b/docs/user-manual/zh/core-bridges.xml new file mode 100644 index 0000000000..5adc9e24ed --- /dev/null +++ b/docs/user-manual/zh/core-bridges.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + 核心桥 + 桥的功能是从一个源队列中接收消息,再将消息转发到目的地址。通常这个目的地址在另外一个HornetQ服务器中。 + 源与目的不需要在同一个集群中。所以桥很适合将消息从一个集群中可靠地转发到另一个集群。比如通过一个WAN,或 + internet,等连接不稳定的网络。 + 桥有处理故障的能力。如果目的服务器的连接失败(像网络故障),桥会重试与目的服务器的连接,直接连接成功 + 为止。当连接成功后,桥则继续进行工作。 + 总之,桥是可靠连接两个HornetQ服务器的一种手段。使用核心桥时源和目的服务器必须都是HornetQ服务器。 + 桥可以通过配置提供一次且只有一次的传递保证。其采用的方法是重复检测(详细 + 描述在)。 + + 核心桥的功能与JMS桥的功能相似,但是不能将它们混淆! + 核心桥用来连接两个HornetQ节点,它不使用JMS接口。JMS桥使用的是JMS接口,它连接的是任何两个符合 + JMS 1.1规范的服务器。因此,JMS桥可以将两个不同的JMS服务器连接起来。从性能角度考虑,核心桥由于采用 + 重复检测来实现一次且只一次的传递保证,可以提供更高的性能。 + JMS桥则需要使用XA这种复杂的机制来提供同样的传递保证,因些性能要比核心桥低。 + +
+ 桥的配置 + 桥的配置在hornetq-configuration.xml文件中。让我们先看一个配置的例子 + (它实际上出自bridge例子): + +<bridge name="my-bridge"> + <queue-name>jms.queue.sausage-factory</queue-name> + <forwarding-address>jms.queue.mincing-machine</forwarding-address> + <filter-string="name='aardvark'"/> + <transformer-class-name> + org.hornetq.jms.example.HatColourChangeTransformer + </transformer-class-name> + <retry-interval>1000</retry-interval> + <retry-interval-multiplier>1.0</retry-interval-multiplier> + <reconnect-attempts>-1</reconnect-attempts> + <failover-on-server-shutdown>false</failover-on-server-shutdown> + <use-duplicate-detection>true</use-duplicate-detection> + <confirmation-window-size>10000000</confirmation-window-size> + <connector-ref connector-name="remote-connector" + backup-connector-name="backup-remote-connector"/> + <user>foouser</user> + <password>foopassword</password> +</bridge> + + 在上面的配置中包括了桥的所有参数。在实际应用中可能其中很多的参数可以使用默认值,不需要在配置中 + 指定。 + 下面我们对每个参数分别说明: + + + name参数。所有桥都必须有一个唯一的名字。 + + + queue-name。本地队列的名字。桥从本地队列中接收消息。 + 这是一个必要的参数。 + 这个队列在桥的启动之前必须已经存在。 + + 如果使用JMS,JMS的配置文件hornetq-jms.xml在核心配置文件 + hornetq-configuration.xml之后装载。所以如果你的桥要从JMS + 队列接收消息,就需要保证JMS队列同时要作为核心队列部署。具体方法可以参见 + bridge例子。 + + + + forwarding-address。目的服务器中的地址。消息将被转发到这个地址。 + 如果没有指定这个转发地址,消息的原始地址将会保留。 + + + filter-string。一个可选的过滤器表达式。它表示只有过滤器表达式选择 + 的消息才被转发。过滤器表达式的语法参见 + + + transformer-class-name。可选的转换器类名。这是一个用户定义的 + 类,它需要实现接口org.hornetq.core.server.cluster.Transformer + 。 + 如果指定了这个类,每当一个消息被转发之前,它的transform()方法 + 就会被调用。用户利用这个机会可以对消息本身或消息头信息进行修改。 + + + retry-interval。这个可选参数决定了在进行连接重试时,两次重试 + 之间的时间间隔。默认值是2000毫秒。 + + + retry-interval-multiplier。这个可选参数基于前一次重试连接 + 的时间间隔来计算下一次重试的间隔,即前一次的间隔乘以该参数。 + 这样可以实现重试间隔的指数延迟(exponential backoff) + 让我们看一个例子: + 假设retry-interval1000 ms,并且我们 + 将retry-interval-multiplier设为2.0,如果 + 第一次尝试失败,则等待1000毫秒后进行第二次重试,如果再失败,则每三次重 + 试要在2000毫秒后进行,第四次要等待4000毫秒, + 以此类推。 + 默认值是1.0,表示每次重试间隔相同的时间。 + + + reconnect-attempts。可选参数。它表示要进行多少重试后才放弃 + 并退出。-1表示进行无限次重试。默认值是-1 + + + failover-on-server-shutdown。可选参数。它指定了当目的服务器正常 + 退出时桥是否尝试失效备援(failover)到备份服务器(如果配置了的话)上。 + 桥的连接器可以配置一个主服务器和一个备份服务器。如果配置了备份服务器,并且这个参数是 + true时,在主服务器正常退出时,桥会自动地连接到备份服务器上继续工作。 + 如果桥的连接器没有配置备份服务器,则这个参数不起作用。 + 你的桥配置了备份服务器后,有时你需要临时将主服务器关闭进行一些维护,此时并不希望桥连接到备份服务 + 器中。使用该参数就可以达到这个目的。 + 这个参数的默认值是false + + + use-duplicate-detection。可选参数。它控制桥是否在转发的消息中自动 + 添加一个重复ID的属性。 + 添加这样一个属性可以使目的服务器对来自源服务器的消息进行重复检测。当出现连接故障或服务器崩溃时, + 桥在恢复时将重新转发那些没有被通知的消息。这在目的服务器端有可能造成重复发送。使用重复检测功能,可 + 以将重复发送的消息过滤掉。 + 使用这个功能,服务器就可以保证 一次并且只有一次的传递,而不需要使用 + 重量级的方法,如XA(参见 )。 + 默认的值是true. + + + confirmation-window-size。这个可选参数决定了向目的服务器转发消息时 + 所使用的确认窗口的大小。详细的描述在 + + 当桥从一个设置了max-size-bytes参数的队列接收并转发消息时,一个重要的事情就是要将 + confirmation-window-size的值设置为小于等于 + max-size-bytes的值,以避免造成消息流的停止。 + + + + connector-ref。这是一个必需的参数。它指定了桥用来连接目的服务器的 + 连接器 + connector包含了所用的传输(TCP, SSL, HTTP等),以及服务器连接参数 + (如主机名,端口等)。关于连接器的详细信息请参见()。 + connector-ref有两个参数: + + + connector-name。这个指的是核心配置文件hornetq-configuration.xml中定义的连接器的名字。桥使用 + 这个连接器创建与目的服务器的连接。这个参数是必需指定的。 + + + backup-connector-name。这个可选参数同样指定一个在核心 + 配置文件hornetq-configuration.xml中定义的连接器名字。 + 当目的服务器出现故障时,或者正常退出但是参数failover-on-server-shutdown的值设为true时,桥使用这个参数指定的连接器通过失效备援(failover)连接 + 到备用的服务器。 + + + + + user。这个可选参数指定了桥在创建与远程服务器连接时所用的用户名。如果 + 没有指定用户名,在配置文件hornetq-configuration.xml中 + cluster-user所定义的默认集群用户名将被使用。 + + + password。这个可选的参数给出的是桥创建与远程服务器连接所使用的密码。 + 如果没有指定密码,在配置文件hornetq-configuration.xml中 + cluster-password所定义的默认集群密码将被使用。 + + +
+
diff --git a/docs/user-manual/zh/diagrams/architecture-diagrams.odg b/docs/user-manual/zh/diagrams/architecture-diagrams.odg new file mode 100644 index 0000000000..33d99cf6bb Binary files /dev/null and b/docs/user-manual/zh/diagrams/architecture-diagrams.odg differ diff --git a/docs/user-manual/zh/diagrams/ha-replicated-store.odg b/docs/user-manual/zh/diagrams/ha-replicated-store.odg new file mode 100644 index 0000000000..495c672ecf Binary files /dev/null and b/docs/user-manual/zh/diagrams/ha-replicated-store.odg differ diff --git a/docs/user-manual/zh/diagrams/ha-shared-store.odg b/docs/user-manual/zh/diagrams/ha-shared-store.odg new file mode 100644 index 0000000000..3b976924f4 Binary files /dev/null and b/docs/user-manual/zh/diagrams/ha-shared-store.odg differ diff --git a/docs/user-manual/zh/diverts.xml b/docs/user-manual/zh/diverts.xml new file mode 100644 index 0000000000..fe51e6b2ac --- /dev/null +++ b/docs/user-manual/zh/diverts.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + 消息的转发(divert)与分流 + 在HornetQ中可以配置一些称为转发器(diverts)的对象。 + 转发器可以将路由到一个地址的消息透明地转发到其它的地址去,不需要客户端的参与。 + 转发器可以是唯一(exclusive)的,即消息只转发到新的地址,不发到原 + 来的地址;也可以是不唯一(non-exclusive)的,即消息在发往原有地址的 + 同时,它的一个拷贝被发往新的地址。不唯一的转发器可以在应用中将消息进行 + 分流(splitting)。比如在一个订单系统中它可以用于监视发往订单队列中 + 的每个订单消息。 + 转发器还可以带一个可选的消息选择器。只有被选择器选择的消息才会被转发。 + 转发器还可以带有一个转换器(Transformer)。它可以将消息进行转换。 + 转发器只在同一个服务器中的地址间进行转发。如果要向另外服务器中的地址进行转发,可以采用转发器与桥配合 + 来实现。先将消息通过转发器转发到一个存储与转发的队列中,再由一个桥将这个队列的消息转发到远程服务器的目的 + 地址中。 + 由转发器与桥进行配合可以组成复杂的路由系统。在服务器中由一组转发器可以形成一个消息路由表。如果加上桥,就 + 可以进一步形成一个分布式的可靠的消息路由网。 + 转发器的配置在hornetq-configuration.xml中定义。可以配置零个或多个转发器。 + 参见转发器的例子,它展示了如何配置与使用转发器。 + 让我们看一些转发器的配置例子: +
+ 唯一式转发器 + 下面是一个唯一式转发器的例子。它将所有符合条件的消息转发到新的地址,而旧的地址将不能得到这些消息。 + 以下配置来自于divert例子: + +<divert name="prices-divert"> + <address>jms.topic.priceUpdates</address> + <forwarding-address>jms.queue.priceForwarding</forwarding-address> + <filter string="office='New York'"/> + <transformer-class-name> + org.hornetq.jms.example.AddForwardingTimeTransformer + </transformer-class-name> + <exclusive>true</exclusive> +</divert> + + 在这里我们定义了一相名为“prices-divert”的转发器,它将发往 + “jms.topic.priceUpdates”(对应JMS话题priceUpdates)的消息转向另一个本地地址“jms.queue.priceForwarding”(对应JMS队列 + priceForwarding)。 + 我们还配置了一相消息过滤器。只有office属性值为New York + 的消息才被转发到新地址,其它消息则继续发往原地址。如果没有定义过滤器,所有消息将被转发。 + 本例中还配置了一个转换器的类。当每转发一个消息时,该转换器就被执行一次。转换器可以对消息在转发前进行 + 更改。这里的转换器只是在消息中加入了一个记录转发时间的消息头。 + 本例中消息被转发到一个’存贮与转发是‘队列,然后通过一个桥将消息转发到另一个HornetQ服务器中。 +
+
+ 不唯一转发器 + 下面我们来看一个不唯一的转发器。不唯一转发器将消息的拷贝转发到新的地址中, + 原消息则继续发往原有地址。 + 因此不唯一转发器可以将消息进行分流(splitting)。 + 不唯一转发器的配置与唯一转发器的配置中一样的,也可以带一个可选的过滤器和转换器。下面的配置也是出自 + divert例子: + +<divert name="order-divert"> + <address>jms.queue.orders</address> + <forwarding-address>jms.topic.spyTopic</forwarding-address> + <exclusive>false</exclusive> +</divert> + + The above divert example takes a copy of every message sent to the address 'jms.queue.orders' (Which corresponds to a JMS Queue called 'orders') and sends it to a local address called 'jms.topic.SpyTopic' (which corresponds to a JMS Topic called 'SpyTopic'). +
+
diff --git a/docs/user-manual/zh/duplicate-detection.xml b/docs/user-manual/zh/duplicate-detection.xml new file mode 100644 index 0000000000..de675ac95a --- /dev/null +++ b/docs/user-manual/zh/duplicate-detection.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + 重复消息检测 + HornetQ具有强大的自动检测重复消息的功能。应用层无需实现复杂的重复检测。本章解释了什么是重复检测,它 + 在HornetQ中如何工作的,以及如何进行配置。 + 当客户端向服务器端发送消息时,或者从一个服务器向另一个服务器传递消息时,如果消息发送后目标服务器或者 + 连接出现故障,导致发送一方没有收到发送成功的确认信息,发送方因此就无法确定消息是否已经成功发送到了目标地 + 址。 + 如果上述的故障发生在消息被成功接收并处理后,但是在向发送方返回功能确认信息之前,那么消息实际上可以到达 + 其目的地址;如果故障发生在消息的接收及处理过程中,则消息不会到达其目的地址。从发送方的角度看,它无法区分 + 这两种情况。 + 当服务器恢复后,客户端面临的困难的选择。它知道服务器出了故障,但是不知道刚刚发送的消息是否成功到达目的 + 地址。如果它重新发送这个消息,就有可能造成消息的重复。如果这个消息是一个订单的话,重复发送消息就会产生两 + 个相同的订单,这当然不是所希望的結果。 + 将消息的发送放到一个事务中也不能解决这个问题。如果在事务提交的过程中发生故障,同样不能确定这个事务是否提交 + 成功! + 为了解决这个问题,HornetQ提供了自动消息重复检测功能。 +
+ 在消息发送中应用重复检测 + 在消息发送中启用重复检测功能十分简单:你只需将消息的一个特殊属性设置一个唯一值。你可以用任意方法来 + 计算这个值,但是要保证它的唯一性。当目标服务器接收到这个消息时,它会检查这个属性是否被设置,如果设置了, + 就检查内存缓存中是否已经接收到了相同值的消息。如果发现已经接收过具有相同属性值的消息,它将忽略这个消息。 + + 在节点之间的消息传递使用重复消息检测可以保证一次且只一次的传递,和使用 + XA事务接收消息的效果一样,但是比XA消耗的资源要少,并且更容易。 + + 如果是在一个事务中发送消息,则只需要设置其中一个消息的属性值。在服务器端如果服务器检测到一个事务中某一个 + 消息重复,则会忽略整个事务。 + 这个属性的名称由org.hornetq.api.core.HDR_DUPLICATE_DETECTION_ID定义,即: + _HQ_DUPL_ID + 该属性的值可以是byte[]类型或SimpleString类型(核心接口)。如果使用JMS,它必须是String + 类型。它的值一定是唯一的。一个简单的方法是使用UUID。 + 下面是一个使用核心接口设置这个属性的例子: + +... + +ClientMessage message = session.createMessage(true); + +SimpleString myUniqueID = "This is my unique id"; // Could use a UUID for this + +message.setStringProperty(HDR_DUPLICATE_DETECTION_ID, myUniqueID); + +... + + 下面则是一个使用JMS的例子: + +... + +Message jmsMessage = session.createMessage(); + +String myUniqueID = "This is my unique id"; // Could use a UUID for this + +message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID); + +... + +
+
+ 配置重复ID缓存 + 服务器缓存中保存接收到的消息的org.hornetq.core.message.impl.HDR_DUPLICATE_DETECTION_ID属性值。每个地址有 + 单独的缓存。 + 缓存的大小是固定的,循环使用。如果缓存的最大可以存放n条记录,那么n + 1条记录将会覆盖缓存中的第0 + 条记录。 + 缓存的最大容量在文件hornetq-configuration.xml中配置,参数是id-cache-size。默认值是2000条记录。 + 在文件hornetq-configuration.xml中还可以配置将缓存持久化到磁盘。相应的参数 + 是persist-id-cache。如果设为true,则每加入一个id就将 + 它同时保存到磁盘中。默认值是true + + 注意在设置缓存大小时,一定要保证缓存能保存足夠数量的记录,当消息被重新发送时,之前发送的ID不被 + 覆盖掉。 + +
+
+ 桥与重复检测 + 核心桥可以通过配置在将消息发向目的服务器之前自动向消息中添加唯一的id(如果消息中还没有的话)。这样 + 如果目的服务器发生故障,核心桥在重新发送消息时,目的服务器就可以自动检测重复的消息,发现重复消息即丢弃。 + 要配置核心桥的自动添加id的功能,需要在hornetq-configuration.xml中桥的配置 + 里将use-duplicate-detection参数设为true + 这个参数的默认值是true + 关于核心桥的配置和使用,参见 +
+
+ 重复检测与集群连接 + 集群连接内部使用核心桥在节点间可靠地移动消息,因此它们的核心桥也可以配置自动添加id的功能。 + 配置的方法是在hornetq-configuration.xml文件中将集群连接的 + use-duplicate-detection参数设为true + 这个参数的默认值是true + 有关集群连接配置的更多信息,请参见 +
+
+ 分页转存与重复检测 + HornetQ在将消息进行分页转存中也使用了重复检测。当分页转存消息被从磁盘中读回到内存时,如果服务器发生故障, + 重复检测可以避免在这一过程中有消息被重复读入,即避免了消息的重复传递。 + 关于分页转存的配置信息请参见 +
+
diff --git a/docs/user-manual/zh/embedding-hornetq.xml b/docs/user-manual/zh/embedding-hornetq.xml new file mode 100644 index 0000000000..1569b01745 --- /dev/null +++ b/docs/user-manual/zh/embedding-hornetq.xml @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + 嵌入式HornetQ + HornetQ是由简单传统Java对象(POJO)实现,因此它可以在任何依赖注入的框架中运行,比如JBoss + Microcontainer,Sprint或Google Guice。另外如果你的应用程序内部需要消息功能,你可以在程序中 + 直接实例化HornetQ的客户端或服务器端。我们称之为嵌入式 + HornetQ。 + 有些应用需要高性能、事务性及持久化的消息服务,但是又不希望自己去费时费力实现它。于是嵌入式HornetQ就 + 成为了一个很适当的选择。 + 要使用嵌入式HornetQ只需要几个简单的步骤。首先初始化配置对象,再初始化服务器并启动它,在你的虚拟机 + 中就运行越来了一个HornetQ服务器。就是这么简单。 +
+ POJO的初始化 + 按照以下步骤去做: + 创建配置对象--这个对象包装了HornetQ的配置信息。如果你想使用配置文件,则使用FileConfigurationImpl + import org.hornetq.core.config.Configuration; +import org.hornetq.core.config.impl.FileConfiguration; + +... + + +Configuration config = new FileConfiguration(); +config.setConfigurationUrl(urlToYourconfigfile); +config.start(); + 如果不需要配置文件,可以用ConfigurationImpl,只要将其中的各种配置参数设置好 + 即可。如添加适当的接收器。 + ConfigurationImpl用来配置接收器。和主要配置文件相似,只需要添加 + NettyAcceptorFactory即可。 + import org.hornetq.core.config.Configuration; +import org.hornetq.core.config.impl.ConfigurationImpl; + +... + +Configuration config = new ConfigurationImpl(); +HashSet<TransportConfiguration> transports = new HashSet<TransportConfiguration>(); + +transports.add(new TransportConfiguration(NettyAcceptorFactory.class.getName())); +transports.add(new TransportConfiguration(InVMAcceptorFactory.class.getName())); + +config.setAcceptorConfigurations(transports); + 接着就需要初始化并启动HornetQ服务。org.hornetq.api.core.server.HornetQ类有一些静态方法可用来创建HornetQ服务器。 + import org.hornetq.api.core.server.HornetQ; +import org.hornetq.core.server.HornetQServer; + +... + +HornetQServer server = HornetQ.newHornetQServer(config); + +server.start(); + 你还可以直接实例化HornetQServerImpl + HornetQServer server = + new HornetQServerImpl(config); +server.start(); +
+
+ 使用依赖注入框架 + 你还可以使用一个依赖注入框架来启动HornetQ,比如JBoss + MicrocontainerSpring框架 + HornetQ独立服务器使用的是JBoss Microcontainer作为其框架。在HornetQ的发布中包括的HornetQBootstrapServerhornetq-beans.xml文件共同实现了 + 在JBoss Microcontainer中对HornetQ服务器的引导。 + 要使用JBoss Microcontainer,需要在xml文件中声明HornetQServer + 和Configuration对象。另外还可以注入一个安全管理器和一个MBean服务器。但是这些 + 注入是可选的。 + 下面是一个基本的JBoss Microcontainer的XML Bean的声明: + <?xml version="1.0" encoding="UTF-8"?> + +<deployment xmlns="urn:jboss:bean-deployer:2.0"> + + <!-- The core configuration --> + <bean name="Configuration" + class="org.hornetq.core.config.impl.FileConfiguration"> + </bean> + + <!-- The core server --> + <bean name="HornetQServer" + class="org.hornetq.core.server.impl.HornetQServerImpl"> + <constructor> + <parameter> + <inject bean="Configuration"/> + </parameter> + </constructor> + </bean> + </deployment> + HornetQBootstrapServer实现了JBoss Microcontainer的简单封装。 + HornetQBootstrapServer bootStrap = + new HornetQBootstrapServer(new String[] {"hornetq-beans.xml"}); + bootStrap.run(); +
+
+ 连接嵌入式HornetQ + 嵌入式HornetQ的连接和普通的连接一样要创建连接工厂: +
+ 核心接口 + 使用核心接口,需要创建一个ClientSessionFactory然后正常建立连接。 + ClientSessionFactory nettyFactory = HornetQClient.createClientSessionFactory( + new TransportConfiguration( + InVMConnectorFactory.class.getName())); + +ClientSession session = factory.createSession(); + +session.createQueue("example", "example", true); + +ClientProducer producer = session.createProducer("example"); + +ClientMessage message = session.createMessage(true); + +message.getBody().writeString("Hello"); + +producer.send(message); + +session.start(); + +ClientConsumer consumer = session.createConsumer("example"); + +ClientMessage msgReceived = consumer.receive(); + +System.out.println("message = " + msgReceived.getBody().readString()); + +session.close(); +
+
+ JMS接口 + 使用JMS接口连接嵌入HornetQ同样简单。只需要直接实例化 + ConnectionFactory即可。如下面例子所示: + ConnectionFactory cf = + HornetQJMSClient.createConnectionFactory( + new TransportConfiguration(InVMConnectorFactory.class.getName())); + +Connection conn = cf.createConnection(); + +conn.start(); + +Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + +MessageProducer prod = sess.createProducer(queue); + +TextMessage msg = sess.createTextMessage("Hello!"); + +prod.send(msg); + +sess.commit(); + +MessageConsumer consumer = sess.createConsumer(queue); + +TextMessage txtmsg = (TextMessage)consumer.receive(); + +System.out.println("Msg = " + txtmsg.getText()); + +sess.commit(); + +conn.close(); +
+
+
+ JMS嵌入式HornetQ的例子 + 有关如何设置与运行JMS嵌入式HornetQ的例子请参见 +
+
diff --git a/docs/user-manual/zh/examples.xml b/docs/user-manual/zh/examples.xml new file mode 100644 index 0000000000..430dc64968 --- /dev/null +++ b/docs/user-manual/zh/examples.xml @@ -0,0 +1,427 @@ + + + + + + + + + + + + + + + + + + + + 例子 + 在HornetQ的发布包中有超过70个不同的例子。这些例子直接可以运行。它们分别展示了HornetQ所具有的各种功能。 + 所有的例子都在HornetQ发布包的 examples目录下。所有的例子被分成了两大类: + JMS例子和内核例子。JMS例子展现的是JMS的各种功能,内核的例子则展示的是内核API的功能。 + + 此外HornetQ还提供了一些Java EE的例子,这些例子需要JBoss应用服务器才能运行。 +
+ JMS 例子 + 要运行一个JMS例子,只要进入到相应例子的子目录,运行 ./build.sh (或者 + 在Windows平台上运行build.bat)即可。 + 下面列出的这些JMS例子并配有简要的说明。 +
+ 应用层的失效备援(Failover) + HornetQ支持应用层的失效备援。这在服务器端没有复制(replication)配置的情况下是很有用的。 + 应用程序可以注册一个JMS ExceptionListener。当HornetQ检测到连接故障时,它会 + 通知这个注册的Listener。 + 这个ExceptionListener在接到HornetQ的通知后可以与其它的节点创建 + 新的连接、会话等对象,以使应用程序能继续运行。 + 应用层的失效备援是实现高可获得性(HA)的一种方法。它与自动失效备援不同之处在于它需要编写额外的代码。 + 同时由于发生故障时旧的会话结束,这会造成那些还没来得及提交的工作丢失,还会造成任何没有通知的消息被重发。 +
+
+ 内核桥(Bridge)例子 + bridge例子展示的是将一个内核桥部署到一个服务器上,从本地的queue接收消息并将其转发到 + 另一服务器的地址上。 + 内核的bridge可用来在两个互相分开的HornetQ的服务器间建立一个消息流。它可以处理临时性的连接故障,特别适用于 + 不可靠的网络的情况。广域网就是一个例子。 +
+
+ 浏览器(Browser) + browser例子展示的是在HornetQ中如何使用JMS QueueBrowser + 有关JMS queue的概念在JMS 1.1 specification有明确的定义,这里就不再叙述。 + 一个QueueBrowser可以用来观察queue中的消息而影响它们。它可以观察queue中的全部 + 消息,也可以定义一个选择器(selector)来选择性地察看消息。 +
+
+ Client Kickoff + client-kickoff例子展示的是如何利用JMX管理接口通过已知的IP地址来断开客户端的连接。 +
+
+ 客户端的负载均衡 + client-side-load-balancing例子展示的是通过一个JMS连接可以在集群的不同节点上创建 + 会话。也就是说HornetQ可以对客户端的会话创建进行集群内的负载均衡。 +
+
+ 集群分组 + 与分组(grouping)例子相似,只是本例所展示的是集群的情况。发向不同节点的具有相同组id的消息 + 都会传送到同一个节点上的同一个接收者(consumer)。 +
+
+ 集群队列 + clustered-queue 例子将一个JMS queue部署到两个节点上。这两个节点组成一个集群。 + 我们在每个节点上各创建一个接收者(consumer),但只在其中一个节点上创建一个发送者(producer)。利用发送者 + 发送一些消息,然后确认两个接收者以轮换方式(round-robin)接收这些消息。 +
+
+ 单机集群 + clustered-standalone例子所展示的是如何在同一台机器上配置并运行 + 3个节点的集群。在每个节点上都创建了一个JMS topic的订阅者(subscriber)。只在其中一个节点上 + 创建了一相发送者来向这个topic发送一些消息。然后我们确认所有的subscriber都接收到了这些消息。 +
+
+ 集群的Topic + clustered-topic例子将一个JMS topic部署到两个节点上。这两个节点组成一个集群。 + 然后在每个节点上创建了一个订阅者(subscriber),只在一个节点上创建一个发送者(producer)。通过这个发 + 送者发送一些消息,确认两个订阅者都收到了这些消息。 +
+
+ 限制接收速率 + HornetQ可以控制一个JMS消息接收者接收消息的速度。这是在创建或部署连接工厂时通过其配置参数来完成的。 + 如果设置了这个速度的限制,HornetQ会保证其向接收者传递消息的速度永远不会超过这个限制。 +
+
+ 死消息(Dead Letter) + dead-letter例子让你了解如何定义和处理死消息。有时候消息由于某种原因不能成功 + 地传递出去,比如接收者在接收消息的交易中发生回滚。 + 发生回滚后,消息被”退回“到JMS目标(destination)准备进行重发。这一过程可能会被不停地重复下去造成 + 消息永远发不出去,而且浪费系统的时间。 + 为了避免上述情况的发生,消息系统引入了死消息的概念:即当一个消息被反复重发不成功达到一定的次数时,该消息 + 便成为了死消息,它将从所属目标(destination)中删除并发送到一个称为死消息目标的目标。用户可以从死消息目标 +          上接收这些死消息以便进行分析。 +
+
+ 延迟再发送 + delayed-redelivery是一个展示如何配置HornetQ延迟再发送消息的例子。 + 当客户端经常发生故障或发生事务回滚时,消息会不停地重复发送,这样会造成CPU和网络资源被不间断的 + 重复发送所占用,影响其它工作的进行。延迟再发送可以有效地减轻这种情况。 +
+
+ 转移(Divert) + HornetQ通过配置可以将消息从一个地址自动地转移到另一地址。这个例子就是向用户展示转移的配置和使用。 +
+
+ 持久订阅(Durable Subscription) + durable-subscription是一个在HornetQ中如何使用持久订阅(durable + subscription)的例子。持久订阅是标准JMS的一部分,在JMS 1.1规范中有它的详细定义。 + 对于一个持久订阅来说,它的消息可以在订阅没有处于接收状态时被保留。另外,如果发到它的消息是持久 + 消息的话,这些消息可以在服务器故障或重启时不丢失。 +
+
+ 嵌入方式(Embedded) + embedded是一个如何将HornetQ服务嵌入到你的应用中的例子。 +
+
+ HTTP 传输协议的支持 + http-transport展示了HornetQ如何支持在传输层使用HTTP协议来发送和接收消息。 +
+
+ 直接实例化JMS对象 + JMS 对象是指 连接工厂(ConnectionFactory)队列(Queue)话题(Topic) 的实例。通常情况下它们通过JNDI服务 + 来获取。它们在JMS术语中被称为“被管理的对象(administered objects)”。 + 有的时候客户端没有JNDI服务可用,或者不适合使用JNDI。那么在没有JNDI的情况下HornetQ允许直接在客户端 + 将这些JMS对象实例化。 +
+
+ 拦截器(Interceptor) + HornetQ可以配置拦截器以便用户可以自己处理各种各样的消息事件。这个例子就是给用户展示如何使用 + 拦截器。 +
+
+ JAAS + jaas是一个如何配置JAAS安全模式的例子。HornetQ可以使用JAAS来进行用户的验证与权限控制。 +
+
+ JMS桥(Bridge) + jms-brige是一个在两个单独HornetQ服务器之间设置桥的例子。 +
+
+ JMX管理 + jmx例子展示了如何使用JMX来管理HornetQ。 +
+
+ 大消息 + large-message例子给用户展示了使用HornetQ来发送和接收大消息的功能。HornetQ + 支持超大消息的发送与接收。这些消息可以大到内存无法装下。它的大小只受服务器的硬盘空间的限制。 + 在服务器端大消息是被持久化的,所以它可以承受服务器的崩溃或重启而不丢失或损坏。 +
+
+ 最新值队列 + last-value-queue向用户展示了如何定义与使用最新值队列。当在配置文件定义好 + 最新值的参数后,这些最新值队列就会自动地用新的消息取代旧的消息,也就是说旧的消息被抛弃掉。这样一个最新 + 值的队列总是保留最新的消息在队列中。 + 股票价格消息就是一个典型的最新值队列的用例。对用户来说他所关心的是一支股票的最新价格,对于过去的价格 + 是没有多大兴趣的。 +
+
+ 分布式队列的负载均衡 + clustered-queue例子中配置了一个2节点的HornetQ服务集群。在集群上部署了 + 一个分布式JMS队列。 + 然后在一个节点上创建了一个发送者(producer),在两个节点上分别创建一个接收者(consumer)。通过 + 发送者向队列发送一些消息然后被两的接收者以轮流(round-robin)的方式接收。 + 本例说明了HornetQ可以将消息向集群中的每个接收者分布式地传递消息。 +
+
+ 管理 + management例子展示的是如何使用JMS消息来实现对HornetQ的管理。 +
+
+ 管理通知 + management-notification展示了HornetQ如何以JMS消息的形式向用户发送 + 管理通知。当某些事件发生时(如接收都创建,关闭;地址创建与删除;安全验证失败等等),HornetQ会向客户 + 发出JMS消息以通知客户这些事件的相关信息。客户接收到这些信息后可以作出相应的处理。 +
+
+ 消息计数器 + message-counters是一个展示如何使用消息计数器获取JMS队列中的消息信息。 +
+
+ 消息失效 + expiry例子中包括了如何定义和使用消息失效期。消息如果在消息服务器中存留超过一定 + 的时间,就可以被删除。根据JMS规范,接收者就不应该接收到已经过了失效期的消息。(但是并不保证一定接收不到)。 + HornetQ可以给一个队列配上一个失效地址,当队列中的消息失效时,它们就会从队列中删除并转移到该失效地址。 + 这些“失效"的消息可以从失效地址中接收并进行分析。 +
+
+ 消息组 + message-group展示的是如何在HornetQ中配置消息组。消息组可以让你的消息 + 只被一个接收者接收。属于一个消息组中的消息有如下特性: + + + + 同一个消息组中的消息都有相同的组ID。即它们的JMSXGroupID属性值相同。 + + + 第一个接收到消息组中的消息的接收者将会接收到所有该组中的消息。 + + + +
+
+ 消息组(例2) + message-group2是另外一个消息组的例子。它展示的是通过配置连接工厂来实现 + 消息组的功能。 +
+
+ 消息优先级 + 消息优先级会影响消息的传递顺序。 + 消息优先级由标准的JMS消息头属性JMSPriority的值确定。参见JMS 1.1规范。 + 优先级是一个0到9之间的整数值。当消息被传递时,根据优先级的不同消息的传递顺序会收到影响。优先级 + 高的消息往往会比优先级低的先传递给接收者。 + 优先级相同的消息会按照它们到达目标的顺序来传递。在JMS 1.1规范中有详细的规定。 +
+
+ 零接收缓冲 + 默认时HornetQ的接收者客户端有一个消息缓冲,它用来保存从服务器上预先接收的消息。这样做是为了提高 + 性能。因为如果没有这个缓冲,每次调用receive()或onMessage()后,HornetQ就会访问一次服务器请求下 + 一个消息。 + 这样每接收一个消息就会增加一次网络往返的传输。因此,HornetQ在默认情况下使用客户端的接收缓冲来 + 预先接收消息,以提高效率。 + 然而在某些情况下这样的缓冲不符合应用需要。那么可以将缓冲关闭。本例就是展示如何关闭接收缓冲。 +
+
+ 带有服务器数据复制的非事务失效备援 + non-transaction-failover例子展示了由两个服务器组成的高可获得性主/从关系。 + 客户端使用一个非交易的JMS会话(session)可以在主节点崩溃的情况下从主节点失效备援到备份节点。 + HornetQ的这一功能是通过主、备节点间的状态复制来实现的。当主节点发生故障崩溃时,客户端的连接可以自动 + 转向备份节点以继续的发送或接收消息。当使用非事务性的会话时,有可能发生消息丢失或重复传递的情况。 +
+
+ 分页(paging) + paging例子展示了HornetQ在内存有限时如何支持超大容量的队列。当内存不够时, + HornetQ会将消息保存到磁盘上;需要时再将它们从磁盘读入内存。这一过程对用户是透明的。 +
+
+ 预先通知 + 标准的JMS支持3种通知模式: + AUTO_ACKNOWLEDGE(自动通知)、CLIENT_ACKNOWLEDGE客户通知以及 DUPS_OK_ACKNOWLEDGE可重复通知。请参阅JMS规范和教程来进一步了解这几种通知方式。 + 所有方式都需要从客户端发通知到服务器端。有时当发生故障时你并不在乎丢失一些消息,这样可以采用在服务器端在消息 + 传递前进行通知就显得比较合理。本例就是展示如何使用这一HornetQ独有的通知方式。 +
+
+ 消息发送速度限制 + producer-rte-limit例子展示了如何设置HornetQ的最大消息发送速率。它控制消息的 + 发送者(JMS producer)发送消息的最大速度。 +
+
+ 队列 + 这一个简单的JMS队列的例子。 +
+
+ Message再分配 + queue-message-redistribution例子展示了如何将消息在集群的各节点同名的队列 + 间进行再分配。 +
+
+ 队列请求 + 这是一个简单的实现队列请求的例子。 +
+
+ 带消息选择器(selector)的队列 + queue-selector例子展示了如何使用选择器来有条件地选择消息进行接收。 +
+
+ 节点连接重试 + reattach-node例子展示了如何使客户端在发生故障时重试连接到原有服务器,而不是 + 直接放弃并通知用户的ExceptionListener。通过配置,客户端可以自动的不断重试连接直到服务器连接上为止。 +
+
+ 请求/应答 + 一个简单的展示JMS 请求/应答消息方式的例子。 +
+
+ 定时消息 + scheduled-message例子展示了如何向HornetQ发送定时消息(scheduled message)。 + 所谓定时消息就是在规定的将来的某一时间传递的消息。 +
+
+ 安全 + security例子展示了如何配置HornetQ的安全参数。 +
+
+ 发送通知 + send-acknowledgements例子展示了如何使用HornetQ提供的高级异步发送通知功能 + (asynchronous send acknowledgements)。这是服务器向客户端通知消息已经 + 被接收。 +
+
+ SSL传输支持 + ssl-enabled例子展示了如何配置使用SSL来发送与接收消息。 +
+
+ 静态消息选择器 + static-selector例子展示了如何配置HornetQ核心队列的静态消息选择器(又称过滤器)。 +
+
+ 使用JMS方法来配置静态消息选择器 + static-selector-jms例子采用JMS方法来配置HornetQ的队列的静态选择器(过滤器)。 +
+
+ Stomp + stomp例子展示了如何配置HornetQ来发送与接收Stomp消息。 +
+
+ Stomp与Web Sockets + stomp-websockets例子给出了如何配置一个HornetQ服务器直接从Web浏览器 + 中(需要支持Web Socket)发送和接收Stomp消息。 +
+
+ 对称型集群 + symmetric-cluster例子展示如何设置一个HornetQ的对称型集群。 + HornetQ的集群配置是非常灵活的。你可以根据需要设置不同的集群结构。最常用的就是对称型的集群了。这是在应用 + 服务器中常见的集群类型。 + 对称型的集群具有同一性,即每个节点与其他节点处于同等地位,并且每一个节点都与其他任一节点相连接。 +
+
+ 临时队列 + 本例展示的是如何使用一个JMS临时队列(temporary queue)。 +
+
+ 话题(Topic) + 一个简单的JMS topic的例子。 +
+
+ 话题体系(Topic Hierarchy) + HornetQ支持话题体系。所谓话题体系就是允许你使用通配符来注册一个订阅(subscriber),这样所有发送到 + 与该通配符相匹配的地址的消息都可以被该订阅收到。 +
+
+ 话题选择器例1 + topic-selector-example1例子展示的是如何创建带有选择器的JMS话题(Topic)订阅。 +
+
+ 话题选择器例2 + topic-selector-example2 是另一个使用带有选择器的JMS话题(Topic)订阅的例子。 +
+
+ 带有数据复制的事务性失效备援 + transaction-failover例子展示了由两个服务器组成的高可获得性主/备关系。 + 客户端使用一个交易的JMS会话(session)可以在主节点崩溃的情况下从主节点失效备援到备份节点。 + HornetQ的这一功能是通过主、备节点间的状态复制来实现的。当主节点发生故障崩溃时,客户端的连接可以自动 + 转向备份节点以继续的发送或接收消息。当使用事务性的会话时,能够保证消息被传递并且只被传递一次。 +
+
+ 事务性会话 + transactional例子展示了如何在HornetQ中使用事务性会话。 +
+
+ XA Heuristic + xa-heuristic例子给出了如何通过HornetQ的管理接口来做出一个XA的heuristic决定。 + 一个XA的heuristic决定是一个单方面的对一个已经准备的(prepared)XA事务分支提交或回滚的决定。 +
+
+ XA 接收 + xa-receive例子展示的是如何使用HornetQ在一个XA事务内接收消息。 +
+
+ XA 发送 + xa-send例子展示的是如何使用HornetQ在一个XA事务内发送消息。 +
+
+ XA与事务管理器(transaction manager) + xa-with-jta展示了如何在HornetQ中使用JTA接口来控制事务。 +
+
+
+ 核心API的例子 + 运行核心API的例子很简单,只要进到相应的例子目录下运行“ant"即可。 +
+ 嵌入式 + 本例展示了如何将HornetQ服务器嵌入到你的代码中。 +
+
+
+ Java EE 例子 + 绝大多数的Java EE例子都可以按如下步骤运行:进入到相应的目录中,先运行ant deploy。 + 这一步创建了一个新的JBoss的服务器配置方案并启动它。当JBoss服务器启动后,再运行ant run + 启动例子程序。有些例子需要额外的步骤,请参见相关的例子的文档。 +
+ EJB/JMS 事务 + 这个例子展示了在一个事务内使用EJB和JMS的方法。 +
+
+ HAJNDI (High Availability) + 这个例子展示了如何使用集群中的JNDI服务。 +
+
+ 资源适配器的配置(JCA) + 本例展示了如何配置HornetQ的JCA适配器的各种参数。 +
+
+ 资源适配器运程服务器的配置 + 本例展示了如何配置HornetQ的JCA适配器来与远程的HornetQ服务器通迅。 +
+
+ JMS 桥(Bridge) + 本例展示了如何使用HornetQ的JMS bridge。 +
+
+ MDB (消息驱动Bean) + 一个消息驱动bean的例子。 +
+
+ Servlet传输 + 一个展示在HornetQ中使用servlet作为传输层的例子。 +
+
+ Servlet SSL 传输 + 一个展示在HornetQ中使用基于SSL之上的servlet传输的例子。 +
+
+ XA 恢复(recovery) + 这是一个展示HornetQ在JBoss应用服务器中的XA recovery是如何工作的例子。 +
+
+
diff --git a/docs/user-manual/zh/filter-expressions.xml b/docs/user-manual/zh/filter-expressions.xml new file mode 100644 index 0000000000..8a3e560101 --- /dev/null +++ b/docs/user-manual/zh/filter-expressions.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + 过滤器表达式 + HornetQ提供了一套强大的过滤器(filter)语言。它的语法是基于SQL 92表达式的部分语法。 + 实际上它与JMS选择器(selector)的语法是相同的。只是其中有一些预定义的标识符有所不同。有关 + JMS选择器的相关知识参见 javax.jms.Message + HornetQ在以下以个地方使用了过滤器表达式: + + + 预定义的队列。当在hornetq-configuration.xmlhornetq-jms.xml定义 + 队列时,可以使用过滤器。只有与过滤器表达式相匹配的消息才能达到该队列中。 + + + 核心桥可以使用可选的过滤器表达式。只有与表达式相匹配的消息才被桥处理。 + 参见()。 + + + 转移(Divert)也可以使用可选的过滤器表达式。只有与表达式匹配的消息才被转移。 + 参见()。 + + + 另外过滤器还可以在编程方式创建接收者(consumer)和队列时使用。还有一些应用过滤器的地方在 + 中有所描述。 + + + HornetQ的内核过滤器表达式与JMS选择器表达式是有所不同的。JMS选择器应用于JMS消息,而HornetQ的内核过滤 + 器表达式则用于内核消息。 + 以下标识符可以用在内核消息的过滤器表达式中,用来引用内核消息的属性: + + + HQPriority。代表消息的优先级。消息优先级属性的有效值为0到9间的整数。 + 0为最低优先级,9为最高优先级。例:HQPriority = 3 AND animal = 'aardvark' + + + HQExpiration。代表消息的失效时间。其值为一长整形数。 + + + HQDurable。代表消息是否是持久消息。它是一个字符型的属性,有效值为 DURABLE + 或 NON_DURABLE + + + HQTimestamp。代表消息的创建时间,其值为一长整形数。 + + + HQSize。消息的大小。单位为字节。其值是一个整形数。 + + + 任何其它的标识符在内核过滤器的表达式中都认为是代表着该消息的一个属性。 + diff --git a/docs/user-manual/zh/flow-control.xml b/docs/user-manual/zh/flow-control.xml new file mode 100644 index 0000000000..c1e041e22d --- /dev/null +++ b/docs/user-manual/zh/flow-control.xml @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + 流控制 + 流控制是指对客户端与服务器之间,或者服务器之间的数据流量进行限制,目的是防止通迅双方由于大量数据而过载。 +
+ 接收者(consumer)流控制 + 这是指对客户端的接收者接收消息流的控制。通常为了提高效率,在客户端通常将消息放入缓存,然后再将缓存中 + 的消息传递给接收者(consumer)。当接收者处理消息的速度小于服务器向其发送消息的速度时,就可能造成消息在 + 客户端不断积累,最終引起内存溢出的错误。 +
+ 基于窗口的流控制 + 默认情况下HornetQ的接收者一端会将消息进行缓存以提高性能。如果不这样做,那每次接收者收到一个消息, + 都得通知服务器传递下一个消息,然后服务器再将下一个消息传递过来。这就增加了通信的次数。 + 对于每一次消息传递都有一个网络的往返通信,这样降低了性能。 + 为了避免这样,HornetQ将每个接收者的消息提前接收到一处缓存中。每个缓存的最大值由 + consumer-window-size参数决定(单位字节)。 + consumer-window-size的默认值是 1 MiB (1024 * 1024 + 字节)。 + 它的值可以是: + + + -1 代表大小无限制的缓存。 + + + 0 代表不缓存消息。参见相关的例子 + + + >0 代表缓存的最大字节数。 + + + 合理设置接收者的窗口大小可以显著提高性能。下面是两个极端的例子: + + + 快速接收者 + + 所谓快速接收者是指消息的接收者处理消息的速度大于等于它的接收速度。 + 对于快速接收者或以将consumer-window-size设为 + -1,使得客户端的消息缓存的大小 无限制 + 请谨慎使用这一设置值: 如果接收者的消息处理速度比接收速度小,可造成客户端内存溢出。 + + + + 慢接收者 + + 所谓慢接收者是指接收者每处理一个消息就要花很多时间。这样将缓存关闭就比较合理。服务器可以将多余的 + 消息传递给其它的接收者。 + 假设一个队列有2个接收者。其中一个接收者非常慢。消息被轮流传递到两个接收者。其中的快速接收者 + 很快将其缓存中的消息处理完毕。同时慢接收者的缓存中还有一些消息等待处理。这样快速接收者在一段时间 + 内就处于空闲状态。 + 这时,将consumer-window-size 设为0 (没有缓存),就可以将它变成 + 慢接收者。这样在慢接收者一方不会缓存消息,这使得快的接收者可以处理更多的消息,而不至于处于空闲 + 状态。 + 这说明将它设置为0可以控制一个队列的消息在多个接收者之间的消息分配。 + + + + 大多数情况下很难判断哪些接收者是快速的,哪些是慢速的。往往很多接收者是处于两者之间。这样对于 + consumer-window-size的值就要视具体情况而定。有时需要进行一定的测试 + 来决定它的最佳值。通常情况下将其设为1MiB可以满足大多数的应用情况。 +
+ 使用核心接口(Core API)进行流控制 + Hornet的核心接口中,ClientSessionFactory.setConsumerWindowSize()方法和一些 + ClientSession.createConsumer()方法可以控制流的窗口大小。 +
+
+ 使用JMS的流控制 + 若使用JNDI来获得连接工厂,则需要通过配置hornetq-jms.xml文件来设定窗口大小: + +<connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + + <!-- Set the consumer window size to 0 to have *no* buffer on the client side --> + <consumer-window-size>0</consumer-window-size> +</connection-factory> + + 如果直接实例化连接工厂,则使用HornetQConnectionFactory.setConsumerWindowSize() + 方法来设定窗口大小。 + 参见例子来了解如何配置HornetQ来 + 关闭接收者的缓存。 +
+
+
+ 速率流控制 + 我们还可以通过控制 速率的方法来控制流。这是一种像调节节流阀的形式。 + 这种方法保证一个接收者接收消息的速率不会超过设定的值。 + 速率必须是一个正整数。它代表最大接收速度,单位是消息每秒。将它设为-1就会关闭速率流控制。 + 默认值是-1 + 参见有关速率流控制的例子以进一步了解它的工作原理。 +
+ 使用核心接口(Core API) + HornetQ的核心接口的ClientSessionFactory.setConsumerMaxRate(int consumerMaxRate)方法或 + 某些ClientSession.createConsumer()方法可以实现对流的速率控制。 +
+
+ 使用JMS + 如果从JNDI中获取连接工厂,需要通过配置hornetq-jms.xml来进行速率流控制: + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <!-- We limit consumers created on this connection factory to consume messages + at a maximum rate + of 10 messages per sec --> + <consumer-max-rate>10</consumer-max-rate> + </connection-factory> + 如果是直接实例化连接工厂,则通过HornetQConnectionFactory.setConsumerMaxRate(int + consumerMaxRate)方法来设定最大流速率。 + + 速率流控制可以与窗口流控制结合使用。速率控制只规定了客户端每秒接收多少消息。因此如果你设定 + 了一个较低的速率,同时又设定了一个大的缓存窗口,那么客户端的缓存将会很快饱和。 + + 参见接收速率流控制的例子进一步了解速率流控制的配置和使用。 +
+
+
+
+ 发送者(producer)的流控制 + HornetQ还可以控制客户端向服务器发送消息的速度,以避免服务器因大量数据过载。 +
+ 基于窗口的流控制 + 与接收者的相应的控制相似。在默认条件下,发送者要有足够的份额(credits)才可以向服务器的地址发送消息。 + 这个份额就是消息的大小。 + 当发送者的份额不足时,它要向服务器请求更多的份额以便发送更多的消息。 + 发送者一次向服务器请求的份额值被称为窗口大小 + 于是窗口大小就是指发送者向服务器不间断发送消息的总最大字节数。当发送完毕时需再向服务器请求份额。这样就避免了 + 服务器消息过载的情况。 +
+ 使用核心接口(Core API) + 若使用核心接口,ClientSessionFactory.setProducerWindowSize(int producerWindowSize) + 方法可以对窗口大小进行设定。 +
+
+ 使用JMS + 如果使用JNDI来获得连接工厂,则需要配置hornetq-jms.xml文件以设定窗口大小: + + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <producer-window-size>10</producer-window-size> + </connection-factory> + 如果是直接实例化连接工厂,则使用HornetQConnectionFactory.setProducerWindowSize(int + producerWindowSize)方法来设定窗口大小。 +
+
+ 限定发送者窗口流控制 + 通常情况下客户端请求多少份额,HornetQ服务器就给予多少份额。然而我们还可以针对每个地址来设定一个最大 + 的份额值,以使服务器给出的份额都不大于该值。这样可以防止一个地址的内存溢出。 + 例如,如果有一个队列称为“myqueue”。将它的最大内存值设为10MiB,则服务器就会控制给出的份额以保证向该队列的地 + 址发送消息时不会占大于10MiB的内存空间。 + 当一相地址已经满了的时候,发送者将会阻塞直到该地址有了多余的空间为止,即地址中的消息被接收了一部分后使得 + 地址腾出了一些空间。 + 我们将这种控制方法称为限定发送者窗口流控制。这是一种有效的防止服务器内存溢出的手段。 + 它可以看成是分页转存(paging)的另一种方法。分页转存不阻塞发送者,它将消息转存到存贮介质上以节省内存的空间。 + 要配置一个地址的最大容量并告诉服务器在地址满了的情况下阻塞发送者,你需要为该地址定义一个 + AddressSettings () 并设定 + max-size-bytesaddress-full-policy + 这个配置对所有注册到该地址的队列有效。即所有注册队列的总内存将不超过 max-size-bytes。对于JMS topic情况则意谓着该topic的所有订阅的内存不能超过 + max-size-bytes的设定值。 + 下面是一个例子: + + <address-settings> + <address-setting match="jms.queue.exampleQueue"> + <max-size-bytes>100000</max-size-bytes> + <address-full-policy>BLOCK</address-full-policy> + </address-setting> + </address-settings> + 上面的例子将JMS队列"exampleQueue"的最大内存值设为 + 100000 字节并且阻塞发送者以防止消息量超过这个值。 + 注意必须设置 BLOCK的策略才能打开限定发送者窗口控制。 + 请注意默认的配置下当一个地址中的消息量达到10MiB时,其所有的消息发送者将变为阻塞状态,也就是说 + 在没有接收的情况下你不能向一个地址不阻塞地一次发送超过10MiB的消息。要想增加这个限制,可以加大 + max-size-bytes参数的值,或者调整地址的消息容量限制。 + +
+
+
+ 速率流控制 + HornetQ也可以控制发送者发送消息的速率。单位是每秒消息数。通过设定速率可保证发送者的发送速率不超过某个值。 + 速率必须是一个正整数。如果设为 -1 则关闭速率流控制。默认值是-1 + 请参见例子进一步了解速率流控制的使用方法。 +
+ 使用核心接口(Core API) + 如果使用核心接口,ClientSessionFactory.setProducerMaxRate(int consumerMaxRate)方法或 + 某些 ClientSession.createProducer()方法可以设置最大速率值。 +
+
+ 使用 JMS + 如果使用JNDI,需要配置hornetq-jms.xml文件: + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <!-- We limit producers created on this connection factory to produce messages + at a maximum rate + of 10 messages per sec --> + <producer-max-rate>10</producer-max-rate> + </connection-factory> + 如果直接实例化连接工厂,则使用HornetQConnectionFactory.setProducerMaxRate(int + consumerMaxRate)方法来设置。 +
+
+
+
diff --git a/docs/user-manual/zh/ha.xml b/docs/user-manual/zh/ha.xml new file mode 100644 index 0000000000..1977dfeb7e --- /dev/null +++ b/docs/user-manual/zh/ha.xml @@ -0,0 +1,283 @@ + + + + + + + + + + + + + + + + + + + + 高可获得性(High Availability)和失效备援(Failover) + 高可获得性是指当系统中有一台甚至多台服务器发生故障时还能继续运转的能力 + 作为高可获得性的一部分,失效备援的含意是 + 当客户端当前连接的服务器发故障时,客户端可以将连接转到另一台正常的服务器,从而能够继续工作 +
+ 主要-备份对 + HornetQ可以将两个服务器以主要-备份对的形式连接在一起。目前HornetQ允许一个 + 主要服务器有一个备份服务器,一个备份服务器只有一个主要服务器。在正常情况下主要服务器工作,备份服务器只有当 + 发生失效备援发生时工作。 + 没有发生失效备援时,主要服务器为客户端提供服务,备份服务器处于待机状态。当客户端在失效备援后连接到备份服务 + 器时,备份服务器开始激活并开始工作。 +
+ 高可获得性(HA)的模式 + HornetQ的高可获得性有两种模式:一种模式通过由主服务器日志向备份服务器日志 + 复制数据。另一种模式则是主服务器与备份服务器间存贮共享 + + 只有持久消息才可以在失效备援时不丢失。所有非持久消息则会丢失。 + +
+ 数据复制 + 在这种模式下,保存在HornetQ主服务器中日志中的数据被复制到备份服务器日志中。注意我们并不复制 + 服务器的全部状态,而是只复制日志和其它的持久性质的操作。 + 复制的操作是异步进行的。数据通过流的方式复制,复制的結果则通过另一个流来返回。通过这样的异步方式 + 我们可以获得比同步方式更大的呑吐量。 + 当用户得到确认信息如一个事务已经提交、准备或加滚,或者是一个持久消息被发送时,HornetQ确保这些状态 + 已经复制到备份服务器上并被持久化。 + 数据复制这种方式不可避免地影响性能,但是另一方面它不依赖于昂贵的文件共享设备(如SAN)。它实际上是 + 一种无共享的HA方式。 + 采用数据复制的失效备援比采用共享存储的失效备援要快,这是因为备份服务器在失效备援时不用重新装载日志。 + +
+ 配置 + 首先在主服务器的 hornetq-configuration.xml文件中配置备份服务器。 + 配置的参数是backup-connector-ref。这个参数指向一个连接器。这个连接器 + 也在主服务器上配置。它定义了如何与备份服务器建立连接。 + 下面就是一个在hornetq-configuration.xml文件中的例子: + + <backup-connector-ref connector-name="backup-connector"/> + + <connectors> + <!-- 这个连接器用于连接备份服务喝咖啡 --> + <!-- 备份服务器在主机"192.168.0.11"上,端口"5445" --> + <connector name="backup-connector"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class> + <param key="host" value="192.168.0.11"/> + <param key="port" value="5445"/> + </connector> + </connectors> + 其次在备份服务器上,我们设置了备份服务器的标志,并且配置了相应的接受器以便主服务器能够建立 + 连接。同时我们将shared-store参数设为false。 + + <backup>true</backup> + + <shared-store>false<shared-store> + + <acceptors> + <acceptor name="acceptor"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class> + <param key="host" value="192.168.0.11"/> + <param key="port" value="5445"/> + </acceptor> + </acceptors> + + 为了使备份服务器正常工作,一定要保证它与主服务器有着同样的桥、预定义的队列、集群连接、 + 广播组和发现组。最简单的作法是拷贝主服务器的全部配置然后再进行上述的修改。 +
+
+ 备份服务器与主服务器间的同步 + 为了能正常工作,备份服务器与主服务器必须同步。这意谓着备份服务器不能是当前任意一个备份服 + 务器。如果你这样做,主服务器将不能成功启动,在日志中会出现异常。 + 要想将一个现有的服务器配置成一个备份服务器,你需要将主服务器的data + 文件夹拷贝到并覆盖这个备份 + 服务器的相同文件夹,这样做保证了备份服务器与主服务器的持久化数据完全一致。 + 当失效备援发生后,备份服务器代替主服务器工作,原来的主服务器失效。这时简单的重启主服务 + 器是不行的。要想将主服务器与备份重新进行同步,就必须先将主服务器和备份服务器同时停止,再将 + 主服务器的数据拷贝到备份服务器,然后再启动。 + HornetQ以后将支持备份与主服务器间的自动同步,无需停止主服务器。 +
+
+
+ 存贮共享 + 使用存贮共享,主服务器与备份服务器共用相同目录的日志数据,通常是一个共享的 + 文件系统。这包括转存目录,日志目录,大消息及绑定日志。 + 当发生失效备援时,工作由备份服务器接管。它首先从共享的文件系统中读取主服务器的持久数据,然后 + 才能接受客户端的连接请求。 + 与数据复制方式不同的是这种方式需要一个共享的文件系统,主服务器与备份服务器都可以访问。典型的 + 高性能的共享系统是存贮区域网络(SAN)系统。我们不建议使用网络附加存贮(NAS),如NFS,来存贮共享 + 日志(主要的原因是它们比较慢)。 + 共享存贮的优点是不需要在主服务器与备份服务器之间进行数据复制,因此对性能不会造成影响。 + 共享存贮的缺点是它需要一个共享文件系统。同时,当备份服务器激活时它需要首先从共享日志中读取相应 + 的信息,从而占用一定的时间。 + 如果你需要在一般工作情况下保持高性能,并且拥有一个快速的SAN系统,同时能够容忍较慢的失效备援 + 过程(取决于数据量在多少),我们建议你采用存贮共享方式的高可获得性。 + +
+ 配置 + 要使用存贮共享模式,在两个服务器的配置文件hornetq-configuration.xml + 中将作如下设置: + + <shared-store>true<shared-store> + + 此外,备份服务器必须显式地指定: + + <backup>true</backup> + + 另外,需要将主服务器和备份服务器的日志文件位置指向同一个共享位置。 + (参见 + 如果客户端使用JMS自动失效备援,主服务器除了要配置一个连接器以连接到备份服务器外,还要在 + 配置文件hornetq-jms.xml中指向这个连接器,如 + 中所解释的那样。 +
+
+ 备份服务器与主服务器间的同步。 + 由于主备服务器之间共享存贮,所以它们不需要进行同步。但是它需要主备服务器同时工作以提供 + 高可获得性。如果一量发生失效备援后,就需要在尽可能早的时间内将备份服务器(处于工作状态)停下来, + 然后再启动主服务器和备份服务器。 + HornetQ以后将支持自动同步功能,不需要先停止服务器。 +
+
+
+
+
+ 失效备援的模式 + HornetQ定义了两种客户端的失效备援: + + + 自动客户端失效备援 + + + 应用层的客户端失效备援 + + + HornetQ还支持100%透明的同一个服务器的自动连接恢复(适用于网络的临时性故障)。这与失效备援很相似, + 只不过连接的是同一个服务器,参见 + 在发生失效备援时,如果客户端有非持久或临时队列的接收者时,这些队列会自动在备份服务器上重新创建。对于 + 非持久性的队列,备份服务器事先是没有它们的信息的。 +
+ 自动客户端失效备援 + HornetQ的客户端可以配置主/备份服务器的信息,当客户端与主服务器的连接发生故障时,可以自动检测到故障并 + 进行失效备援处理,让客户端连接到备份服务器上。备份服务器可以自动重新创建所有在失效备援之前存在的会话与接收 + 者。客户端不需要进行人工的连接恢复工作,从而节省了客户端的开发工作。 + HornetQ的客户端在参数client-failure-check-period(在 + 中进行了解释)规定的时间内如果没有收到数据包,则认为连接发生故障。 + 当客户端认为连接故障时,它就会尝试进行失效备援。 + HornetQ有几种方法来为客户端配置主/备服务器对的列表。可以采用显式指定的方法,或者采用更为常用的 + 服务器发现的方法。有关如何配置服务器发现的详细信息,请参见 + 。 + 关于如何显式指定主/备服务器对的方法,请参见中的解释。 + 要使客户端具备自动失效备援,在客户端的配置中必须要指定重试的次数要大于零(参见 + 中的解释)。 + 有时你需要在主服务器正常关机的情况下仍然进行失效备援。如果使用JMS,你需要将HornetQConnectionFactoryFailoverOnServerShutdown属性设为true,或者是在hornetq-jms.xml(参数为failover-on-server-shutdown)文件中进行相应的配置。如果使用的是核心接口,可以在创建 + ClientSessionFactoryImpl实例时将上述同名属性设置为true。 + 这个属性的默认值是false。这表示如果主服务器是正常关机,客户端将不会进行失效备援 + + + 默认正常关机不会不会导致失效备援。 + 使用CTRL-C来关闭HornetQ服务器或JBoss应用服务器属于正常关机,所以不会触发客户端的失效 + 备援。 + 要想在这种情况下进行失效备援必须将属性FailoverOnServerShutdown + 设为true。 + + + 默认情况下至少创建了一个与主服务器的连接后失效备援才会发生。换句话说,如果客户端每一次创建与 + 主服务器的连接失败,它会根据参数reconnection-attempts的设置进行连接重试,而不是进行失效备援。 + 如果重试次数超过的该参数的值,则连接失败。 + 在有些情况下,你可能希望在初始连接失败和情况下自动连接到备份服务器,那么你可以直接在 + ClientSessionFactoryImplHornetQConnectionFactory上设置FailoverOnInitialConnection + 参数,或者在配置文件中设置failover-on-initial-connection。默认的值是false + 有关事务性及非事务性JMS会话的自动失效备援的例子,请参见 + +
+ 关于服务器的复制 + HornetQ在主服务器向备份服务器复制时,并不复制服务器的全部状态。所以当一个会话在备份服务器 + 中重新创建后,它并不知道发送过的消息或通知过的消息。在失效备援的过程中发生的消息发送或通知也可 + 能丢失。 + 理论上如果进行全部状态的复制,我们可以提供100%的透明的失效备援,不会失去任何的消息或通知。 + 但是这样做要付出很大的代价:即所有信息都要进行复制(包括队列,会话等等)。也就是要求复制服务 + 器的每个状态信息,主服务器的每一步操作都将向其备份进行复制,并且要在全局内保持顺序的一致。这样 + 做就极难保证高性能和可扩展性,特别是考虑到多线程同时改变主服务器的状态的情况,要进行全状态复制 + 就更加困难。 + 一些技术可以用来实现全状态复制,如虚拟同步技术 + (virtual synchrony)。但是这些技术往往没有很好的可扩展性,并且将所有操作都 + 进行序列化,由单一线程进行处理,这样明显地将底了并行处理能力。 + 另外还有其它一些多线程主动复制技术,比如复制锁状态或复制线程调度等。这些技术使用Java语言非常 + 难于实现。 + 因此得出结论,采用大量牺牲性能来换取100%透明的失效备援是得不偿失的。没有100%透明的失效 + 备援我们仍然可以轻易地保证一次且只有一次的传递。这是通过在发生故障时采用重复检测结合事务重试 + 来实现的。 +
+
+ 失效备援时阻塞调用的处理 + 如果当发生失效备援时客户端正面进行一个阻塞调用并等待服务器的返回,新创建的会话不会知道这个调用, + 因此客户端可能永远也不会得到响应,也就可能一直阻塞在那里。 + 为了防止这种情况的发生,HornetQ在失效备援时会解除所有的阻塞调用,同时抛出一个 + javax.jms.JMSException异常(如果是JMS)或HornetQException异常。异常的错误代码是HornetQException.UNBLOCKED。客户端需要自行处理这个异常,并且进行 + 必要的操作重试。 + 如果被解除阻塞的调用是commit()或者prepare(),那么这个事务会被自动地回滚,并且HornetQ + 会抛出一个javax.jms.TransactionRolledBackException(如果是JMS) + 或都是一个HornetQException,错误代码为 HornetQException.TRANSACTION_ROLLED_BACK(如果是核心接口)。 +
+
+ 事务的失效备援处理 + 如果在一个事务性会话中,在当前事务中消息已经发出或通知,则服务器在这时如果发生失效备援,它不 + 能保证发出的消息或通知没有丢失。 + 因此这个事务就会被标记为只回滚,任何尝试提交的操作都会抛出一个javax.jms.TransactionRolledBackException异常(如果是JMS),或者是一 + 个HornetQException的异常,错误代码为HornetQException.TRANSACTION_ROLLED_BACK(如果是核心接口)。 + 客户端需要自行处理这些异常,进行必要的回滚处理。注意这里不需要人工将会话进行回滚-此时它已经 + 被回滚了。用户可以通过同一个会话重试该事务操作。 + HornetQ发布包中包括了一个完整的例子来展示如何处理这种情况。参见 + + 如果是在提交过程中发生了失效备援,服务器将这个阻塞调用解除。这种情况下客户端很难确定在事故发生 + 之前事务是否在主服务器中得到了处理。 + 为了解决这个问题,客户端可以在事务中使用重复检测() + ,并且在提交的调用被解除后重新尝试事务操作。如果在失效备援前事务确实在主服务器上已经完成提交,那么 + 当事务进行重试时,重复检测功能可以保证重复发送的消息被丢弃,这样避免了消息的重复。 + + 通过处理异常和重试,适当处理被解除的阻塞调用并配合重复检测功能,HornetQ可以在故障条件下保证 + 一次并且只有一次的消息传递,没有消息丢失和消息重复。 + +
+
+ 非事务会话的失效备援处理 + 如果会话是非事务性的,那么通过它的消息或通知在故障时可能会丢失。 + 如果你在非事务会话中要保证一次并且只有一次 + 的消息传递,你需要使用重复检测功能,并适当处理被解除的阻塞调用。参见 +
+
+
+ 连接故障的通知 + JMS提供了标准的异步接收连接故障通知的机制:java.jms.ExceptionListener。 + 请参考JMS的javadoc或者其它JMS教程来进一步了解怎样使用这个接口。 + HornetQ的核心接口也提供了一个相似的接口 + org.hornet.core.client.SessionFailureListener + 任何ExceptionListener或SessionFailureListener的实例,在发生连接故障时,都会被HornetQ + 调用,不管该连接是否得到了失效备援、重新连接还是得到了恢复。 +
+
+ 应用层的失效备援 + 在某些情况下你可能不需要自动的客户端失效备援,希望自己来处理连接故障,使用自己的重新连接方案等。 + 我们把它称之为应用层失效备援,因为它是发生在应用层的程序中。 + 为了实现应用层的失效备援,你可以使用监听器(listener)的方式。如果使用的是JMS,你需要在JMS连接上 + 设置一个ExceptionListener类。这个类在连接发生故障时由HornetQ调用。在这个类 + 中你可以将旧的连接关闭,使用JNDI查找新的连接工厂并创建新的连接。这里你可以使用 + HA-JNDI + 来保证新的连接工厂来自于另一个服务器。 + 请参见。这是一个完整的应用层失效备援的例子。 + 如果你使用核心接口,则过程也是很相似的:你在核心的ClientSession实例上设置一个 + FailureListener,然后在这个类中进行相应的处理即可。 +
+
+
diff --git a/docs/user-manual/zh/images/architecture1.jpg b/docs/user-manual/zh/images/architecture1.jpg new file mode 100644 index 0000000000..cb1161f645 Binary files /dev/null and b/docs/user-manual/zh/images/architecture1.jpg differ diff --git a/docs/user-manual/zh/images/architecture2.jpg b/docs/user-manual/zh/images/architecture2.jpg new file mode 100644 index 0000000000..274f578a5e Binary files /dev/null and b/docs/user-manual/zh/images/architecture2.jpg differ diff --git a/docs/user-manual/zh/images/architecture3.jpg b/docs/user-manual/zh/images/architecture3.jpg new file mode 100644 index 0000000000..3c1dfd5742 Binary files /dev/null and b/docs/user-manual/zh/images/architecture3.jpg differ diff --git a/docs/user-manual/zh/images/console1.png b/docs/user-manual/zh/images/console1.png new file mode 100644 index 0000000000..19b6cbd835 Binary files /dev/null and b/docs/user-manual/zh/images/console1.png differ diff --git a/docs/user-manual/zh/images/ha-replicated-store.png b/docs/user-manual/zh/images/ha-replicated-store.png new file mode 100644 index 0000000000..9065dfee67 Binary files /dev/null and b/docs/user-manual/zh/images/ha-replicated-store.png differ diff --git a/docs/user-manual/zh/images/ha-shared-store.png b/docs/user-manual/zh/images/ha-shared-store.png new file mode 100644 index 0000000000..0be2766553 Binary files /dev/null and b/docs/user-manual/zh/images/ha-shared-store.png differ diff --git a/docs/user-manual/zh/images/hornetQ-banner_final.png b/docs/user-manual/zh/images/hornetQ-banner_final.png new file mode 100644 index 0000000000..6388dff1f5 Binary files /dev/null and b/docs/user-manual/zh/images/hornetQ-banner_final.png differ diff --git a/docs/user-manual/zh/images/hornetQ_logo_600px.png b/docs/user-manual/zh/images/hornetQ_logo_600px.png new file mode 100644 index 0000000000..b71f4ba130 Binary files /dev/null and b/docs/user-manual/zh/images/hornetQ_logo_600px.png differ diff --git a/docs/user-manual/zh/intercepting-operations.xml b/docs/user-manual/zh/intercepting-operations.xml new file mode 100644 index 0000000000..63912e0270 --- /dev/null +++ b/docs/user-manual/zh/intercepting-operations.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + 拦截操作 + HornetQ支持拦截器。拦截器可以拦截进入服务器的数据包。每进入服务器 + 一个数据包,拦截器就被调用一次,允许一些特殊和处理,例如对包的审计、过滤等。拦截器可以对数据包 + 进行改动。 +
+ 实现拦截器 + 拦截器必须要实现Interceptor接口 + +package org.hornetq.api.core.interceptor; + +public interface Interceptor +{ + boolean intercept(Packet packet, RemotingConnection connection) + throws HornetQException; +} + + 它的方法的返回值是很重要的: + + + 如果返回true,处理正常进行下去。 + + + 如果返回false,则处理被中断,其它的拦截器将不会被调用,数据包将不会 + 被服务器所处理。 + + +
+
+ 配置拦截器 + 拦截器的配置在hornetq-configuration.xml文件中: + +<remoting-interceptors> + <class-name>org.hornetq.jms.example.LoginInterceptor</class-name> + <class-name>org.hornetq.jms.example.AdditionalPropertyInterceptor</class-name> +</remoting-interceptors> + + 拦截器的类(以及它们依赖的类)必须要在服务器的classpath中,否则不能被正常初始化及调用。 +
+
+ 客户端拦截器 + 在客户端也可以有拦截器来拦截来自服务器的数据包。ClientSessionFactory + 的addInterceptor()方法可以用来添加拦截器。 + 同样拦截器的类(以及它们依赖的类)必须要在客户端的classpath中,否则它们不能被正常初始化及调用。 +
+
+ 例子 + 参见。这个例子中展示了如何使用拦截器向发往服务器的消息中 + 添加属性。 +
+
diff --git a/docs/user-manual/zh/interoperability.xml b/docs/user-manual/zh/interoperability.xml new file mode 100644 index 0000000000..4baed4a084 --- /dev/null +++ b/docs/user-manual/zh/interoperability.xml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + 互操作性 +
+ Stomp + Stomp是一个基于文本的协议。使用Stomp协议的 + 客户端可以与Stomp的代理(broker)进行通迅。 + Stomp客户端支持多种语言和平台,因此 + 它有着很好的互操作性。 +
+ 内建Stomp支持 + HornetQ内建支持Stomp功能。要使用Stomp发送与接收消息,必须配置一个NettyAcceptor, + 其中的protocol参数值应设为stomp + + <acceptor name="stomp-acceptor"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> <param key="protocol" value="stomp"/> + <param key="port" value="61613"/> + </acceptor> + + 有了上述的配置,HornetQ就可以在端口61613(这是Stomp代理的默认端口)接受Stomp连接了。 + stomp例子展示了如何在HornetQ中配置Stomp。 +
+ 限制 + 消息的通知不是事务性的。ACK信号不能作为事务的一部分来传输(如果设置了transaction + 属性,它将被忽略)。 +
+
+
+ Stomp目标与HornetQ的地址和队列的映射 + Stomp客户端在消息发送和订阅中使用的是目标(destination)。目标名称是简单的字符串,对应的是服务 + 器端的目的地。不同服务器对这种映射有着不同的实现。 + 在HornetQ中这些目标被映射为地址队列。 + 当一个Stomp客户端发送一个消息(使用SEND信号)到一个目标时,这个目标被映射到一个地址。 + 如果一个Stomp客户端订阅(或解除订阅)一个目标时(使用SUBSCRIBE或 + UNSUBSCRIBE),这个目标被映射到一个HornetQ的队列。 +
+
+ Stomp与JMS的互操作性 +
+ 使用JMS目标 + 正如解释的那样,JMS的目标同样映射到HornetQ的地址与队列。如果你使用 + Stomp向JMS的目标发送消息,那么Stomp的目标必须要遵照相同的命名规则: + + + 如果向JMS队列发送数据或订阅它,则队列的名称前缀必须是jms.queue. + 例如,如果向名为orders的JMS队列发送消息,Stomp客户端必须发送以下信息: + +SEND +destination:jms.queue.orders + +hello queue orders +^@ + + + + 如果向JMS 话题(topic)发送或订阅消息,话题名称前缀必须是jms.topic. + 例如,如果订阅名为 stocks的JMS话题,Stomp客户端必须发送以下信息: + + SUBSCRIBE + destination:jms.topic.stocks + + ^@ + + + +
+ +
+ 使用JMS或核心接口发送和接收Stomp消息 + Stomp基本上是一个基于文本的协议。为了使用更简单,我们的Stomp实现通过检查content-length的值 + 来决定如何将一个Stomp消息映射成一个JMS消息或核心消息。 + + 如果在Stomp消息中没有content-length头,它将被映射为一个JMS的 + TextMessage,或者是一个核心消息,其消息体的缓存是一个SimpleString。 + 如果Stomp消息中content-length,则它被映射为一个JMS的 + BytesMessage,或者是一个核心消息,其消息体缓存中是一个字节数组byte[]。 + 从一个JMS消息或核心消息映射为Stomp消息时遵从同样的逻辑。一个Stomp客户端可以通过检查 + content-length来决定消息体的类型(字符串或字节)。 +
+
+
+ 通过Web Sockets使用Stomp + HornetQ还支持通过Web Sockets使用Stomp。任何支持 + Web Socket的浏览器中可以利用HornetQ来发送和接收Stomp消息。 + 要使用些功能,必须配置一个NettyAcceptor,并设置protocol + 的值为stomp_ws + +<acceptor name="stomp-ws-acceptor"> + <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class> + <param key="protocol" value="stomp_ws"/> + <param key="port" value="61614"/> +</acceptor> + + 使用上面配置,HornetQ在URL路径/stomp下端口61614接收Stomp连接。 + 浏览器然后就可以连接到ws://<server>:61614/stomp,使用Web Socket来发送和接收 + Stomp消息了。 + 为了简化客户端的开发,在GitHub + 上提供了一个JavaScript库(参见文档)。 + stomp-websockets例子给出一如何配置HornetQ服务器以使浏览器和Java应用程序通过一个JMS话题 + 进行消息的传递。 +
+
+ StompConnect + StompConnect是一个Stomp代理服务器, + 它可以将Stomp协议转换为标准的JMS接口调用。因此,通过StompConnect的作用HornetQ可以作为一个Stomp代理, + 与任何一个Stomp客户端通迅。这些客户端可以由C、C++、C#及.net等语言实现。 + 要运行StompConnect首先要启动HornetQ服务以及JNDI服务。 + Stomp需要jndi.properties文件要在classpath中。该文件 + 应有如下类似的内容: + java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.provider.url=jnp://localhost:1099 +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces + 要确保该文件与StompConnect的jar包以及HornetQ的jar文件都在classpath中。最后,运行 + java org.codehaus.stomp.jms.Main +
+
+
+ REST + HornetQ即将支持REST! +
+
+ AMQP + HornetQ即将支持AMQP! +
+
diff --git a/docs/user-manual/zh/jms-bridge.xml b/docs/user-manual/zh/jms-bridge.xml new file mode 100644 index 0000000000..b2896b4c87 --- /dev/null +++ b/docs/user-manual/zh/jms-bridge.xml @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + + + + + + + JMS桥(Bridge) + HornetQ提供了JMS消息桥服务。 + 桥的作用是从一个消息源队列或话题(topic)接收消息,然后将它们发送到一个目标队列或话题。通常源和 + 目的不在同一台服务器上。 + 作为消息源的服务器与目的服务器不必在同一个集群内。通过桥的作用,两台服务器可以通过非可靠的网络连接 + 起来,比如WAN。 + 桥可以作为单独的服务部署,或者部署于HornetQ单独服务器内,或者部署在JBoss应用服务器中。源或目的可以 + 在同一个VM中,也可以在其它的VM中。 + 桥还可以在HornetQ服务器与其它JMS 1.1 兼容的服务器之间进行消息的传递。 + 还要将JMS桥与核心桥混淆。JMB桥可以连接两个JMS 1.1兼容的服务器,它使用的是JMS接口。 + 而核心桥(在中描述)使用核心API将两个HornetQ实例连接 + 起来。核心桥的性能通常要比JMS桥的性能高,所以尽可能使用核心桥。另外核心桥可以不用XA + 就可以实现一次并只有一次的消息传递保证。 + 桥可以适当处理连接故障。当源的连接或目的的连接发生故障时,例如网络故障,桥将不断重试连接直到连接 + 恢复为止。当连接恢复后,桥会继续正常工作。 + 桥还可以有一个可选的JMS选择器,它可以使桥只接收选择器选择的消息。 + 可以配置桥从队列还是从话题中接收消息。如果配置成从话题中接收消息,还以设定是以非持久订阅的方式接收,还是 + 以持久订阅的方式接收。 + 通常桥是通过一个bean配置文件由JBoss Micro Container部署到JBoss应用服务器中。下面的就是一 + 个桥的bean文件例子。这个桥将同一服务器上的两个目标连接起来。 + <?xml version="1.0" encoding="UTF-8"?> + +<deployment xmlns="urn:jboss:bean-deployer:2.0"> + + <bean name="JMSBridge" class="org.hornetq.api.jms.bridge.impl.JMSBridgeImpl"> + <!-- HornetQ must be started before the bridge --> + <depends>HornetQServer</depends> + <constructor> + <!-- Source ConnectionFactory Factory --> + <parameter> + <inject bean="SourceCFF"/> + </parameter> + <!-- Target ConnectionFactory Factory --> + <parameter> + <inject bean="TargetCFF"/> + </parameter> + <!-- Source DestinationFactory --> + <parameter> + <inject bean="SourceDestinationFactory"/> + </parameter> + <!-- Target DestinationFactory --> + <parameter> + <inject bean="TargetDestinationFactory"/> + </parameter> + <!-- Source User Name (no username here) --> + <parameter><null /></parameter> + <!-- Source Password (no password here)--> + <parameter><null /></parameter> + <!-- Target User Name (no username here)--> + <parameter><null /></parameter> + <!-- Target Password (no password here)--> + <parameter><null /></parameter> + <!-- Selector --> + <parameter><null /></parameter> + <!-- Failure Retry Interval (in ms) --> + <parameter>5000</parameter> + <!-- Max Retries --> + <parameter>10</parameter> + <!-- Quality Of Service --> + <parameter>ONCE_AND_ONLY_ONCE</parameter> + <!-- Max Batch Size --> + <parameter>1</parameter> + <!-- Max Batch Time (-1 means infinite) --> + <parameter>-1</parameter> + <!-- Subscription name (no subscription name here)--> + <parameter><null /></parameter> + <!-- Client ID (no client ID here)--> + <parameter><null /></parameter> + <!-- Add MessageID In Header --> + <parameter>true</parameter> + <!-- register the JMS Bridge in the AS MBeanServer --> + <parameter> + <inject bean="MBeanServer"/> + </parameter> + <parameter>org.hornetq:service=JMSBridge</parameter> + </constructor> + <property name="transactionManager"> + <inject bean="RealTransactionManager"/> + </property> + </bean> + + <!-- SourceCFF describes the ConnectionFactory used to connect to the + source destination --> + <bean name="SourceCFF" + class="org.hornetq.api.jms.bridge.impl.JNDIConnectionFactoryFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/ConnectionFactory</parameter> + </constructor> + </bean> + + <!-- TargetCFF describes the ConnectionFactory used to connect to the + target destination --> + <bean name="TargetCFF" + class="org.hornetq.api.jms.bridge.impl.JNDIConnectionFactoryFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/ConnectionFactory</parameter> + </constructor> + </bean> + + <!-- SourceDestinationFactory describes the Destination used as the source --> + <bean name="SourceDestinationFactory" + class="org.hornetq.api.jms.bridge.impl.JNDIDestinationFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/queue/source</parameter> + </constructor> + </bean> + + <!-- TargetDestinationFactory describes the Destination used as the target --> + <bean name="TargetDestinationFactory" + class="org.hornetq.api.jms.bridge.impl.JNDIDestinationFactory"> + <constructor> + <parameter> + <inject bean="JNDI" /> + </parameter> + <parameter>/queue/target</parameter> + </constructor> + </bean> + + <!-- JNDI is a Hashtable containing the JNDI properties required --> + <!-- to connect to the sources and targets JMS resrouces --> + <bean name="JNDI" class="java.util.Hashtable"> + <constructor class="java.util.Map"> + <map class="java.util.Hashtable" keyClass="String" + valueClass="String"> + <entry> + <key>java.naming.factory.initial</key> + <value>org.jnp.interfaces.NamingContextFactory</value> + </entry> + <entry> + <key>java.naming.provider.url</key> + <value>jnp://localhost:1099</value> + </entry> + <entry> + <key>java.naming.factory.url.pkgs</key> + <value>org.jboss.naming:org.jnp.interfaces"</value> + </entry> + <entry> + <key>jnp.timeout</key> + <value>5000</value> + </entry> + <entry> + <key>jnp.sotimeout</key> + <value>5000</value> + </entry> + </map> + </constructor> + </bean> + + <bean name="MBeanServer" class="javax.management.MBeanServer"> + <constructor factoryClass="org.jboss.mx.util.MBeanServerLocator" + factoryMethod="locateJBoss"/> + </bean> +</deployment> +
+ JMS桥的配置参数 + 桥的主要的bean是JMSBridge。所有的配置参数需要传递给这个bean的 + 构造函数。 + + 如果不想指定某个参数的值(例如匿名认证或没有选择器),将该参数设为<null + />即可。 + + + + 源连接工厂的工厂(Source ConnectionFactory Factory) + 这个参数注入一个SourceCFFbean(由bean文件定义)。它被 + 用来创建ConnectionFactory + + + + 目标连接工厂的工厂(Target ConnectionFactory Factory) + 这个参数注入一个TargetCFFbean(由bean文件定义)。它被 + 用来创建目的ConnectionFactory + + + + 源目标工厂(Source DestinationFactory) + 这个参数注入一个SourceDestinationFactorybean(由 + bean文件定义)。它用来创建 + 目标(Destination) + + + + 目的目标工厂(Target DestinationFactory) + 这个参数注入一个TargetDestinationFactorybean(由 + bean文件定义)。它用来创建目的 + 目标(Destination) + + + + 源用户名(Source User Name) + 用于创建到的连接的用户名 + + + 源密码(Source Password) + 用于创建连接的密码 + + + 目的用户名(Target User Name) + 用于创建目的连接的用户名 + + + 目的密码(Target Password) + t用于创建目的连接的密码 + + + 选择器(Selector) + 这是一个JMS的选择器表达式,它用于从源目标接收消息。只有与选择器相匹配的消息才会被桥 + 转发到目的目标 + 选择器必须符合JMS + 选择器语法 + + + 故障重试间隔(Failure Retry Interval) + 代表当桥发现连接故障时在每两次重试连接之间所要等待的时间间隔,单位毫秒 + + + 最大重试次数(Max Retries) + 表示桥在发现连接故障时所进行的最大重试次数。超过这个次数,桥就放弃重试。 + -1代表一直重试下去 + + + 服务质量(Quality Of Service) + 这个参数代表所需要的服务质量模式 + 有效的值为: + + + AT_MOST_ONCE + + + DUPLICATES_OK + + + ONCE_AND_ONLY_ONCE + + + 有关这些模式的解释,参见 + + + 最大批量(Max Batch Size) + 表示桥一次性从源目标最多接收多少消息,并将它们一次发往目的地。它的值必须是 + >= 1 + + + + 最大批时间(Max Batch Time) + 代表桥在将一批消息发向目的之前等待的最大毫秒数。这个时间过后,即使接收的消息数小于 + MaxBatchSize,桥也会开始向目的发送消息。它的值必须是 + -1 (代表永远等待)或>= 1 + + + 订阅名(Subscription Name) + 如果源的目标是一个话题(topic),你想使用持久的订阅来接收消息的话,这个参数可以指定 + 订阅名。 + + + 客户ID(Client ID) + 如果源的目标是一个话题(topic),你想使用持久的订阅来接收消息的话,这个参数可以指定 + JMS的客户ID。它用于创建/查找持久订阅。 + + + 在消息头添加MessageID(Add MessageID In Header) + 如果值为true,原始的消息ID在发往目的是回到消息的名为HORNETQ_BRIDGE_MSG_ID_LIST的头中。如果一个消息被桥转发了多次, + 则每次转发的消息ID都添加在这个头中。这用于分布式请求/回答的消息模式。 + + 当收到一个消息时,通过它的相关ID(coorelation id)可以发送一个回答。这样 + 在消息发送方得到这个回答消息时,它可以与原消息相关联起来。 + + + + MBean服务器(MBean Server) + 要使用JMX管理JMS桥,需指定JMS桥所要注册的MBeanServer(如JVM Platform MBeanServer 或 + JBoss 应用服务器的MBeanServer) + + + ObjectName + 设置了MBeanServer后,你还需要设置JMS桥MBean注册用的ObjectName(必须是唯一的) + + +
+
+ 源和目的的连接工厂 + 源工目的的连接工厂分别用于创建到源和到目的的连接。 + 上面的配置例子中使用的是HornetQ提供的默认实现。它使用JNDI查找连接工厂。对于其它的应用服务器 + 或JMS提供者,需要实现相应的实现,即实现org.hornetq.jms.bridge.ConnectionFactoryFactory接口。 +
+
+ 源和目的的目标工厂 + 它们用来创建或查找相应的目标。 + 上面例子中,我们使用了HornetQ的默认实现,从JNDI中查找相应的对象。 + 要提供新的实现,只要实现接口org.hornetq.jms.bridge.DestinationFactory即可。 +
+
+ 服务质量 + 下面给是桥的三种服务质量的详细说明。 +
+ AT_MOST_ONCE + 这种QoS模式表示的是消息最多送达目标一次。在消息发往目的之前,消息就会被通知。因此, + 如果在消息被源删除但并未到达目的时发生故障,消息有可能丢失。所以说消息的 + 发送最多一次。 + 这个模式适用于持久或非持久的消息。 +
+
+ DUPLICATES_OK + 在这个QoS模式下,消息从源接收后再发送到目的,之后才对源进行消息通知。这样如果在发送成功之后 + 消息通知前的时间内发生故障的话,在故障恢复时同一个消息可能被再次传递。結果可能是在目的处 + 该消息收到了两次。 + 这个模式适用于持久或非持久的消息。 +
+
+ ONCE_AND_ONLY_ONCE + 这个模式保证消息从源发送到目的一次,并且只有一次。(有时这个模式又称为“只一次”)。若源与目的处于 + 同一个HornetQ服务器中,这个模式通过本地事务来保证消息的发送和通知。如果是在不同的服务器上, + 则会使用一个JTA的事务将发送和接收包括其中。这里使用的JTA事务是JBoss的实现,它包含有一个 + 完整的事务恢复管理器,所以能提供高度可靠的持久性。如果使用JTA则桥的所有连接工厂必须是 + XAConnectionFactory。这种模式的效率通常是最低的,因为它需要额外记录事务的日志。 + 这个模式只适用于持久性消息。 + + 某些情况下可以不使用ONCE_AND_ONLY_ONCE模式,而同样可以保证“一次且只一次”的效果。 + 这是通过使用DUPLICATES_OK模式,加上在目的端应用程序来检测重复的消息,如果有则将其丢弃。 + 一些JMS服务器本身提供自动重复消息检测的功能,这样节省了在应用层实现的工作。在应用层常见 + 的实现方法是将接收到的消息的ID存放到缓存文件中,然后与每个新到的消息进行对比。这种方式 + 可能在某段时间内有效,所以它不如ONCE_AND_ONLY_ONCE那样严格,它视具体情况也可能是一个 + 不错的选择。 + +
+
+ JMS bridge中的超时问题 + 有时候目标服务器或源服务器会连接不上,这里桥就会尝试重新连接。重新连接的次数由Max Retries + 参数决定,两次重新连接的时间间隔由Failure Retry Interval定义。 + 在重新尝试时会进行JNDI的查找。HornetQ的JNDI使用的是JBoss的实现,如果在JNDI查找过程中网络出现故障, + 查找的操作可能挂起。为了避免这种情况的发生,我们可以为JNDI设置适当的超时。这是通过定义初始上下文的 + jnp.timeout参数和jnp.sotimeout参数来 + 实现的。第一个参数定义了初始连接的超时,第二个参数定义的是套接字的读取超时。 + + 一旦JNDI连接成功,所有调用都是通过RMI完成。如果你想要控制RMI连接的超时,你需要定义相应的系统变量。 + JBoss使用Sun的RMI实现,它的控制参数可以在这里找到。 + 默认的连接超时是10秒,默认的读超时是18秒。 + + 如果你使用自己的实现来查找JMS资源,你需要注意超时问题。 +
+
+ 例子 + 参见。这个例子展示了如何在JBoss应用服务器中配置并使用 + JMS桥从一处目标将消息转发到另一个目标。 + 关于如何在两个单独HornetQ服务器间使用桥的例子,请参见 +
+
+
diff --git a/docs/user-manual/zh/jms-core-mapping.xml b/docs/user-manual/zh/jms-core-mapping.xml new file mode 100644 index 0000000000..50861048d8 --- /dev/null +++ b/docs/user-manual/zh/jms-core-mapping.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + JMS与内核API之间的映射关系 + 本意讲述JMS的目标实体(destination)如何映射到HornetQ的地址(addresses)。 + HornetQ的内核没有JMS的任何实现。在内核中没有topic的概念,它是通过在一个地址上(相当于topic的名字)绑定 + 零或多个queue来实现JMS topic的功能的。每个绑定的queue相当于该topic的一个订阅(subscription)。 + 类似地通过在一个地址上(相当于queue的名字)绑定单一的queue就可以实现JMS queue的功能。 + 按照惯例,所有的JMS queue所对应的内核queue的名字都以jms.queue.做为开头。比如 + 当JMS queue的名字是"orders.europe"时,其对应的内核queue的名字应该是"jms.queue.orders.europe"。 + 那么内核queue所绑定的地址的名字和该内核queue的名字是相同的。 + 同样,所有JMS topic所对应的内核地址的名字都以 "jms.topic."为前缀。比如当一个JMS topic的名字是"news.europe" + 时,它对应的内核的地址应该是"jms.topic.news.europe"。 + 换句话说就是如果你向JMS queue “orders.europe"发送一个消息,这个消息就会被路由到绑定在内核地址为“jms.queue.orders.europe” + 的同名内核queue中。 如果是向JMS topic “news.europe“发送一个消息,它会被路由到绑定到内核地址为 + ”jms.topic.news.europe“的所有的内核queue中。 + 具体要配置一个名为“orders.europe"的JMS队列时,你需要配置相应的内核queue“jms.queue.orders.europe“: + +<!-- expired messages in JMS Queue "orders.europe" + will be sent to the JMS Queue "expiry.europe" --> +<address-setting match="jms.queue.orders.europe"> + <expiry-address>jms.queue.expiry.europe</expiry-address> + ... +</address-setting> + + diff --git a/docs/user-manual/zh/large-messages.xml b/docs/user-manual/zh/large-messages.xml new file mode 100644 index 0000000000..641bceaab5 --- /dev/null +++ b/docs/user-manual/zh/large-messages.xml @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + 大消息 + HornetQ支持超大消息的发送和接收。消息的大小不受客户端或服务器端的内存限制。它只受限于你的磁盘空间的大小。 + 在我们作过的测试中,消息最大可达8GiB,而客户端和服务器端的内存只有50MiB! + 要发送一个大消息,用户需要为大消息提供一个InputStream,当大消息被发送时, + HornetQ从该InputStream读取消息。例如,要将一个磁盘中的大文件以消息形式发送,可以 + 使用FileInputStream + 数据从InputStream读出并分解为一个个数据片段向服务器以流的形式发送。服务器在收到 + 这些片段后将它们保存到磁盘上。当服务器准备向接收者传递消息时,它将这些片段读回,同样以片段流的形式向接收者 + 一端发送。当接收者开始接收时,最初收到的只是一个空的消息体。它需要为其设置一个OutputStream + 以便向大消息保存到磁盘上或其它地方。从发送到接收整个过程中不需要整个消息都在内存中。 +
+ 服务器端的配置 + 大消息在服务器端是直接保存在磁盘目录中。这一目录可以在HornetQ的配置文件中定义。 + 这个参数的名字是large-messages-directory + <configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd"> + +... + +<large-messages-directory>/data/large-messages</large-messages-directory> + +... + +</configuration + 默认的大消息保存目录是data/largemessages + 为了提高性能,我们建议将大消息的保存目录定义到与消息日志(journal)或分页转存目录分开的物理卷上。 +
+
+ 设定限制 + 参数min-large-message-size定义了大消息的最小值。 + 任何消息的大小如果超过了该值就被视为大消息。一旦成为大消息,它将被分成小的 + 片段来传送。 + 默认值是100KiB. +
+ 使用核心的API + 如果使用HornetQ的核心,ClientSessionFactory.setMinLargeMessageSize方法 + 可以设置大消息的最小值。 + ClientSessionFactory factory = + HornetQClient.createClientSessionFactory(new + TransportConfiguration(NettyConnectorFactory.class.getName()), null); +factory.setMinLargeMessageSize(25 * 1024); + 对于如何实例化一个会话工厂(session factory) + 给出了进一步的说明。 +
+
+ 使用JMS + 如果连接工厂是通过JNDI方式获得的,则需要在hornetq-jms.xml文件中定义: + ... +<connection-factory name="ConnectionFactory"> +<connectors> + <connector-ref connector-name="netty"/> +</connectors> +<entries> + <entry name="ConnectionFactory"/> + <entry name="XAConnectionFactory"/> +</entries> + +<min-large-message-size>250000</min-large-message-size> +</connection-factory> +... + 如果是直接实例化连接工厂,则使用HornetQConnectionFactory.setMinLargeMessageSize方法来定义。 +
+
+
+ 大消息与流(stream) + 在HornetQ中可以定义大消息所使用的输入和输出流(java.lang.io)。 + HornetQ将使用定义的流来发送(输入流)和接收(输出流)大消息。 + 在使用输出流接收大消息时,有两种选择:你可以用ClientMessage.saveOutputStream方法 + 以阻塞的方式保存大消息;或者你可以使用ClientMessage.setOutputstream方法 + 以异步方法保存大消息。在采用后一种方法时,必须保证接收者(consumer)在大消息的接收过程中保持 + 有效状态。 + 根据需要选择所适合的流。最常见的情况是将磁盘文件以消息方式发送,也有可能是JDBC的Blob数据, + 或者是一个SocketInputStream,或是来自HTTPRequests + 的数据等等。只要是实现了java.io.InputStream和 + java.io.OutputStream的数据源都可以作为大消息传送。 +
+ 核心API中流的使用 + 下表列出了ClientMessage上可以使用的方法。 + 通过相应的对象属性也可以在JMS中应用。 + + org.hornetq.api.core.client.ClientMessage API + + + + + + + 名称 + 说明 + JMS相对应的属性 + + + + + setBodyInputStream(InputStream) + 设定大消息发送时所使用的输入流。 + JMS_HQ_InputStream + + + setOutputStream(OutputStream) + 设定异步接收大消息所使用的输出流。 + JMS_HQ_OutputStream + + + saveOutputStream(OutputStream) + 设定保存大消息所使用的输出流。这个方法将会阻塞直到大消息全部 + 保存完毕才返回。 + JMS_HQ_SaveStream + + + +
+ 下面代码中设定了接收核心消息所用的输出流: + +... +ClientMessage msg = consumer.receive(...); + + +// This will block here until the stream was transferred +msg.saveOutputStream(someOutputStream); + +ClientMessage msg2 = consumer.receive(...); + +// This will not wait the transfer to finish +msg.setOutputStream(someOtherOutputStream); +... + + + 设定发送核心消息所用的输入流: + +... +ClientMessage msg = session.createMessage(); +msg.setInputStream(dataInputStream); +... + +
+
+ 在JMS中使用流 + 使用JMS时,HornetQ根据定义的属性值调用对应的核心接口(参见 )来使用流。你只需要用 + Message.setObjectProperty方法设置适当的输入/输出流即可。 + 输入流InputStream可以通过JMS属性JMS_HQ_InputStream来定义: + +BytesMessage message = session.createBytesMessage(); + +FileInputStream fileInputStream = new FileInputStream(fileInput); + +BufferedInputStream bufferedInput = new BufferedInputStream(fileInputStream); + +message.setObjectProperty("JMS_HQ_InputStream", bufferedInput); + +someProducer.send(message); + 输出流OutputStream可以通过JMS属性JMS_HQ_SaveStream来定义。下面是阻塞式方法: + +BytesMessage messageReceived = (BytesMessage)messageConsumer.receive(120000); + +File outputFile = new File("huge_message_received.dat"); + +FileOutputStream fileOutputStream = new FileOutputStream(outputFile); + +BufferedOutputStream bufferedOutput = new BufferedOutputStream(fileOutputStream); + +// This will block until the entire content is saved on disk +messageReceived.setObjectProperty("JMS_HQ_SaveStream", bufferedOutput); + + 也可以使用JMS_HQ_OutputStream属性以非阻塞式(异步)方法来定义输出流OutputStream + +// This won't wait the stream to finish. You need to keep the consumer active. +messageReceived.setObjectProperty("JMS_HQ_OutputStream", bufferedOutput); + + + 使用JMS时,只有StreamMessageBytesMessage才支持大消息的传送。 + +
+
+
+ 不使用流的方式 + 如果不想使用输入流与输出流来传送大消息,可以用另外一种方法。 + 使用核心接口时,可以直接从消息中读字节。 + ClientMessage msg = consumer.receive(); + +byte[] bytes = new byte[1024]; +for (int i = 0 ; i < msg.getBodySize(); i += bytes.length) +{ + msg.getBody().readBytes(bytes); + // Whatever you want to do with the bytes +} + 使用JMS接口时,BytesMessageStreamMessage + 本身提供这样的支持。 + BytesMessage rm = (BytesMessage)cons.receive(10000); + +byte data[] = new byte[1024]; + +for (int i = 0; i < rm.getBodyLength(); i += 1024) +{ + int numberOfBytes = rm.readBytes(data); + // Do whatever you want with the data +} +
+
+ 在客户端缓存大消息 + 大消息通过流在服务器和客户端之间传输。每个大消息被分割成很多小的数据包传递。因此大消息只能被 + 读取一次。这样一个大消息在收到后就不能再被再次传送。例如,JMS Bridge在发送大消息时如果在出现故障, + 将不能把它重新发送。 + 要解决这个问题,可以在连接工厂上设置cache-large-message-client属性。 + 这个属性可以使客户端接收者创建一个临时的文件保存收到的大消息,这样就可以在需要时能够重新发送该消息。 + 如果JMS Bridge用来发送大消息,可以在它使用的连接工厂上使用它。 +
+
+ 大消息例子 + 我们在提供了一个在JMS中配置和使用大消息的例子。 +
+
diff --git a/docs/user-manual/zh/last-value-queues.xml b/docs/user-manual/zh/last-value-queues.xml new file mode 100644 index 0000000000..cd80899ed4 --- /dev/null +++ b/docs/user-manual/zh/last-value-queues.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + 最新值队列(Last-Value Queues) + 最新值队列是一种特殊的队列。当一个新消息到达一个最新值队列时,它会将所有与该消息定义的Last-Value相同的旧消息 + 抛弃。换句话说,只有最新的消息被保留下来。 + 一个典型的用例是股价信息,通常你只关心一支股票的最新价格。 +
+ 最新值队列的配置 + 最新值队列的配置在address-setting内: + +<address-setting match="jms.queue.lastValueQueue"> + <last-value-queue>true</last-value-queue> +</address-setting> + + 默认的last-value-queue值是false。可以使用通配符来匹配地址。 + (参见 )。 +
+
+ 使用Last-Value参数 + 用来标识最新值的参数名是"_HQ_LVQ_NAME" + (相当于核心API中定义的常量Message.HDR_LAST_VALUE_NAME)。 + 如果两个消息具有相同的Last-Value值,那么较新的消息就会保留,另外一个被丢弃: + +// send 1st message with Last-Value property set to STOCK_NAME +TextMessage message = + session.createTextMessage("1st message with Last-Value property set"); +message.setStringProperty("_HQ_LVQ_NAME", "STOCK_NAME"); +producer.send(message); + +// send 2nd message with Last-Value property set to STOCK_NAME +message = + session.createTextMessage("2nd message with Last-Value property set"); +message.setStringProperty("_HQ_LVQ_NAME", "STOCK_NAME"); +producer.send(message); + +... + +// only the 2nd message will be received: it is the latest with +// the Last-Value property set +TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000); +System.out.format("Received message: %s\n", messageReceived.getText()); + +
+
+ 例子 + 参见。它展示的是在JMS应用中来配置和使用 + 最新值队列。 +
+
diff --git a/docs/user-manual/zh/libaio.xml b/docs/user-manual/zh/libaio.xml new file mode 100644 index 0000000000..c31d4bd4c0 --- /dev/null +++ b/docs/user-manual/zh/libaio.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + Libaio平台专有库 + HornetQ发布包中包括一个平台专有的库,它可以使HornetQ使用Linux操作系统的libaio。 + libaio是Linux项目的一个库。它将用户提交的写操作用异步的方式执行。通过 + 回调用户的代码来通知写操作的完成。 + 通过配置,HornetQ可以使用这个库来访问高性能的日志,具体请参见 + 下面列出了HornetQ所带的平台专有库文件: + + + libHornetQAIO32.so - x86 32 位平台 + + + libHornetQAIO64.so - x86 64 位平台 + + + 当使用libaio时,HornetQ会在库路径中寻找并装 + 载这些文件。 +
+ 库文件的编译 + 如果你的Linux平台不是x86_32或x86_64(比如Itanium 64或IBM Power),你需要自己编译相应的库文件, + 因为HornetQ不提供这些平台的库文件。 +
+ 安装要求 + + 目前libaio只在Linux上有。所以它不可能在其它操作系统上编译。 + + 编译需要autoconf工具,它用来简化编译过程。除此之外还需要一些安装包: + + + gcc - C 编译器 + + + gcc-c++ or g++ - gcc的c++编译工具扩展 + + + autoconf - 自动编译工具 + + + make - make 工具 + + + automake - make文件自动生成工具 + + + libtool - 库连接工具 + + + libaio - 磁盘异步IO库 + + + libaio-dev - libaio的编译支持 + + + 完整的JDK,JAVA_HOME要指向正确的位置 + + + 如果在RHEL或Fedora上进行安装,输入以下命令: + sudo yum install automake libtool autoconf gcc-g++ gcc libaio libaio-dev make + 如果是 debian系统,则: + sudo apt-get install automake libtool autoconf gcc-g++ gcc libaio libaio-dev make + + 在有些Linux的版本中上述的安装包名可能有一些差别。(例如Fedora中的gcc-c++在Debian系统中 + 的名称为g++) + +
+
+ 开始编译 + 在HornetQ发布包的native-src目录下,执行shell脚本 + bootstrap。这个脚本会调用 automake以及make来创建所有的make文件和专有库。 + someUser@someBox:/messaging-distribution/native-src$ ./bootstrap +checking for a BSD-compatible install... /usr/bin/install -c +checking whether build environment is sane... yes +checking for a thread-safe mkdir -p... /bin/mkdir -p + +... + +configure: creating ./config.status +config.status: creating Makefile +config.status: creating ./src/Makefile +config.status: creating config.h +config.status: config.h is unchanged +config.status: executing depfiles commands +config.status: executing libtool commands + +... + 编译好的库文件在./native-src/src/.libs/libHornetQAIO.so。将该文件移到发布包的 + bin目录下,或者你的库目录 + 所指向的目录即可。 + 如果你修改了HornetQ的libaio代码,只需要在native-src目录下直挂运行make即可完成编译。 +
+
+
diff --git a/docs/user-manual/zh/logging.xml b/docs/user-manual/zh/logging.xml new file mode 100644 index 0000000000..519d9729b8 --- /dev/null +++ b/docs/user-manual/zh/logging.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + 日志(Logging) + HornetQ有自己的独立的日志系统,不依赖于任何其它的日志框架。在默认情况下所有HornetQ的日志将输入到 + 标准的JDK日志系统, + (即JUL-Java Util Logging)。服务器在默认条件下读取config目录下的 + logging.properties文件做为JUL的配置文件。它配置了使用HornetQ自己的格式化 + 方法,将日志输出到屏幕终端(Console)及文件中。请访问Sun公司的相关网址来进一步了解如何配置使用JUL。 + 你可以通过编程或定义系统变量的方法来配置不同的日志代理(Logging Delegate)。 + 采用编程方法,只需要调用方法: + org.hornetq.core.logging.Logger.setDelegateFactory(new Log4jLogDelegateFactory()) + 其中Log4jLogDelegateFactory实现了org.hornetq.spi.core.logging.LogDelegateFactory 接口。 + 如果要使用系统变量方法,则需要设置变量org.hornetq.logger-delegate-factory-class-name为相应的代理工厂,即 + -Dorg.hornetq.logger-delegate-factory-class-name=org.hornetq.integration.logging.Log4jLogDelegateFactory + 上面的例子可以看出HornetQ提供了一些代理工厂以方便用户使用,它们是:org.hornetq.core.logging.impl.JULLogDelegateFactory - 默认的JUL日志代理工厂。 + org.hornetq.integration.logging.Log4jLogDelegateFactory + - Log4J的日志代理工厂。 + 如果在客户端使用JUL代理,注意要提供logging.properties文件,并且在客户端启动之前设置java.util.logging.config.file属性。 +
+ 与JBoss应用服务器日志的关系 + 当HornetQ部署到JBoss应用服务器版本5.x或以上时,虽然HornetQ仍然使用JUL,但是所有的日志输出被重定向到 + JBoss logger。请参阅相关的JBoss文档来了解更多的信息。如果是以前版本的JBoss,则必需指定你所需要的日志代理。 +
+
diff --git a/docs/user-manual/zh/management.xml b/docs/user-manual/zh/management.xml new file mode 100644 index 0000000000..21a3587259 --- /dev/null +++ b/docs/user-manual/zh/management.xml @@ -0,0 +1,805 @@ + + + + + + + + + + + + + + + + + + + + 管理 + HornetQ拥有套丰富的管理接口。用户使用这些接口可以修改服务器配置、创建新的资源(如队列和 + 话题)、检查这些资源(如队列中有多少消息)并进行管理(从队列中删除消息)。这样用户可以 + 管理HornetQ。另外,客户还可以订阅管理通知。 + 有三种方式管理HornetQ: + + + 使用JMX -- JMX是标准的Java应用程序管理方式。 + + + 使用核心接口 -- 管理操作通过核心消息的方法发向HornetQ服 + 务。 + + + 使用JMS接口 -- 管理操作通过JMS消息的方式发向HornetQ服务器。 + + + 虽然有三种方式,但它们提供相同的功能。使用JMX方法能完成的功能使用核心接口或JMS接口都可以完成。 + 根据不同的应用环境来选择最适当的方式。 +
+ 管理接口API + 不管使用哪种方式,管理接口都是一样的。 + 对于每个被管理的资源都有一个Java的接口提供可使用的操作。 + HornetQ的管理接口分布在2个包中: + + + 核心资源的管理接口在 org.hornetq.api.core.management包中。 + + + JMS资源的管理接口在 org.hornetq.api.jms.management包中。 + + + 调用管理操作的方法由所使用是方式是JMX、核心消息还是JMS + 消息来决定。 + + 一小部分的管理接口需要一个过滤器参数来选择需要的消息。 + 如果要求所有的消息,传递该参数时使用 + null或者一个空的字符串即可。 + +
+ 核心管理接口 + HornetQ定义了一套对核心资源的管理接口。关于它们的详细说明请参见相应的javadoc。 + 下面是对它们的概述: +
+ 核心服务器管理 + + + 队列的列表、创建、部署与删除 + getQueueNames() method方法用来列出所有已经部署的队列。 + HornetQServerControl (ObjectName org.hornetq:module=Core,type=Server或资源名core.server)上有队列创建或删除的方法,它们是 + createQueue()deployQueue()和 + destroyQueue() + 如果队列已经存在,那么createQueue方法调用会出错,而 + deployQueue方法调用没有任何作用。 + + + 暂停与恢复队列 + QueueControl可用来暂停与恢复队列。如果一个队列被暂停,它 + 虽然可以继续接收消息但是不传递消息;当被恢复时,队列又会开始传递消息。 + + + + 远程连接的列表与关闭 + listRemoteAddresses()方法可以用来列出客户端的远程地址。 + 还可以使用closeConnectionsForAddress()方法来关闭 + 与该地址相关的远程连接。 + 另外,使用listConnectionIDs()方法可以列出连接ID, + 使用listSessions()方法可以列出与一个连接ID相关的所有 + 会话(session)。 + + + 事务的手动操作(heuristic operations) + 当服务器由于故障而重新启动时,可能造成一些事务没有完成而需要人工干预。 + listPreparedTransactions()方法可以列出所有处于 + 准备(prepared)状态的事务(事务是用Base64字符串的形式列出)。如果要提交或回滚, + 可以使用commitPreparedTransaction()方法或 + rollbackPreparedTransaction()方法。采用启发式 + (heuristic)完成的事务可以用listHeuristicCommittedTransactions() + 方法和listHeuristicRolledBackTransactions方法列出。 + + + 打开和重置消息计数器 + 消息计数器可以用enableMessageCounters()方法打开,用 + disableMessageCounters()方法关闭。如果要重置消息计数器, + 可以使用resetAllMessageCounters()方法和 + resetAllMessageCounterHistories()方法。 + + + 获得服务器的配置和属性 + HornetQServerControl提供了访问HornetQ服务器所有属性 + 的方法(例如getVersion()方法可以得到服务器的版本,等等)。 + + + 核心桥和转发器的创建,删除与列表 + 使用getBridgeNames()可以列出部署的核心桥。 + 使用getDivertNames()可以列出部署的转发器。 + 使用HornetQServerControl (ObjectName org.hornetq:module=Core,type=Server 或资源名 core.server)的方法createBridge() +              和destroyBridge()可以创建和删除核心桥。 + 通过createDivert()destroyDivert() + 可以创建和删除转发器。 + + +
+
+ 核心地址的管理 + 核心地址可以通过AddressControl类进行访问(ObjectName + 是 org.hornetq:module=Core,type=Address,name="<the + address name>"或者资源名 core.address.<the + address name>)。 + + + 修改地址的角色和权限。 + 你可以使用addRole()方法或removeRole() + 方法添加或删除地址的角色。用getRoles()方法可以列出一个地址的所有角色。 + + +
+
+ 核心队列的管理 + 管理接口中的一大部分是管理核心队列的。QueueControl类定义了核心队列的管理 + 接口(ObjectName org.hornetq:module=Core,type=Queue,address="<绑定地址 + address>",name="<队列名>" 或资源名 core.queue.<队列名>)。 + 绝大部分的队列管理方法需要一个消息ID参数(如删除一个消息)或一个过滤器参数(如将具有某个 + 属性值的所有消息设置为过期)。 + + + 消息的过期,发向死信地址及删除 + expireMessages()方法可以使消息过期。如果设置了一个过期地址, + 这些消息会被发到过期地址。否则这些消息会被丢弃。setExpiryAddress() + 方法可以用来设置队列的过期地址。 + 消息可以用sendMessagesToDeadLetterAddress()方法发送到 + 一个死信地址。它返回发到这个死信地址的消息的数量。如果没有设置死信地址,那么消息就会从队列中 + 删除。用setDeadLetterAddress()方法可以设置队列的死信地址。 + 消息还可以从一个队列转移到另一个队列。其方法是 + moveMessages() + + + 消息的列表与删除 + listMessages()方法可以列出一个队列中的所有消息。这个方法 + 返回的是一个Map的数组。每一个Map对应一个消息。 + 消息可以用removeMessages()方法删除。如果是使用消息ID, + 返回的是一个布尔常量;如果是用过滤器,则返回的 + 是删除的消息数量。在使用过滤器来删除过滤的消息时,如果传入一个空字符串则表示要删除 + 所有的消息。 + + + 消息计数 + 一个队列中的消息数可以用getMessageCount()方法获得。 + 此外,countMessages()方法可以返回队列中与一 + 个过滤器匹配的消息数量。 + + + 修改消息的优先级 + changeMessagesPriority()方法可以改变消息的优先级。 + 该方法如果带一个消息ID参数,返回一个布尔常量;如果带一个过滤器参数,返回优先级 + 被更新的消息的数量。 + + + 消息计数器 + listMessageCounter()方法和 + listMessageCounterHistory()方法可以列出一个队列的消息计数器。 + (参见 )。消息计数器还可以 + 用resetMessageCounter()方法重置。 + + + 获得队列的属性 + 通过QueueControl可以获得核心队列的属性(例如用 + getFilter()方法可以得到队列的 + 过滤器,isDurable()方法可以知道队列是否是持久的队列等等)。 + + + 暂停和恢复队列 + QueueControl可用来暂停与恢复队列。如果一个队列被暂停,它 + 虽然可以继续接收消息但是不传递消息;当被恢复时,队列又会开始传递消息。 + + +
+
+ 其它核心资源的管理 + HornetQ允许用户启动或停止其远程资源(接收器,转发器,桥,等等)。这样可以使服务器暂停工作 + 而不需要完全停止服务器(比如可以临时对服务器进行一些离线操作,像对一些事务的处理)。这些资源有: + + + 接收器 + AcceptorControl类(ObjectName org.hornetq:module=Core,type=Acceptor,name="<接收器名 + >" 或资源名 core.acceptor.<地址名 + >)的start()方法启动,用 + stop()方法停止。接收器的参数可以通过AcceptorControl + 的属性获得。(参见 )。 + + + 转发器 + DivertControl(ObjectName是 org.hornetq:module=Core,type=Divert,name=<转发器名> + 或资源名core.divert.<转发器>)类的 + start()方法可以启动,用stop()方法可以停止。 + 通过DivertControl还可以获得转发器的各种属性。(参见 )。 + + + + 桥可以通过BridgeControl类(ObjectName org.hornetq:module=Core,type=Bridge,name="<桥的名字 + >" 或资源名 core.bridge.<桥的名字 + >)的start() + 方法启动,用stop()方法停止。它的属性可以通过 + BridgeControl的属性获得(参见 + )。 + + + 广播组 + 广播组可以通过BroadcastGroupControl类(ObjectName org.hornetq:module=Core,type=BroadcastGroup,name="<广播组名 + >" 或者资源名 core.broadcastgroup.<广播组名>)的 + start()方法启动,用stop()方法停止。 + 它的属性也可以通过BroadcastGroupControl的属性获得(参见)。 + + + 发现组 + 发现组可以通过DiscoveryGroupControl类 + (ObjectName org.hornetq:module=Core,type=DiscoveryGroup, + name="<发现组名>" 或资源名core.discovery.< + 发现组名>)的 + start()方法启动,用stop()方法停止。 + 它的参数可以通过DiscoveryGroupControl的属性获得(参见 + )。 + + + 集群连接 + 集群连接可以通过ClusterConnectionControl类( + ObjectName org.hornetq:module=Core,type=ClusterConnection,name="<集群连接名 + >" 或资源名 core.clusterconnection.<集群连接名>)的 + start()方法启动,用stop()方法停止。 + 它的参数可以通过ClusterConnectionControl的属性来获得(参见 + )。 + + +
+
+
+ JMS管理接口 + HornetQ定义了一套JMS管理接口来管理JMS的可管理的对象 + (例如JMS队列,话题及连接工厂)。 +
+ JMS服务器管理 + JMSServerControl类(ObjectName org.hornetq:module=JMS,type=Server 或资源名jms.server)用来创建JMS资源(连接工厂和目标)。 + + + 列表、创建、删除连接工厂 + 使用getConnectionFactoryNames() 方法可以列出部署的连接工厂的 + 名字。 + createConnectionFactory()方法和destroyConnectionFactory()方法能创建和删除JMS连接工厂。 + 这些连接工厂都与JNDI绑定以便于客户端来查找。如果是在图形介面下创建连接工厂,在广本框内输入 + 有关的传输参数时可使用一组用逗号隔开的键-值对(例如key1=10, key2="value", key3=false)。 + 如果需要定义多个传输,你需要将每个传输的参数对用大括号括起来,例如{key=10}, {key=20}。 + 第一个key属于第一个传输配置,第二个key属于第二个传输配置。 + (有关传输的各种参数参见)。 + + + 列表、创建与删除队列 + getQueueNames()方法可以获得部署的JMS队列的名字列表。 + JMS队列可以用createQueue()方法创建,用destroyQueue()方法删除。 + 创建的队列都绑定到JNDI以便JMS客户端可以查找。 + + + 列表、创建与删除话题(topic) + getTopicNames()方法可以获得部署的JMS话题名字。 + JMS话题可以用createTopic()方法来创建,用destroyTopic()方法来删除。 + 创建的话题都绑定到JNDI以便客户端查找。 + + + 远程连接的列表与关闭 + listRemoteAddresses()方法可以获得JMS客户端的远程地址。 + 还可以用closeConnectionsForAddress()方法关闭与某个远程地址相关联的连接。 + 另外,listConnectionIDs()方法可以列出连接的ID, + 而listSessions()方法可以列出一个给定的连接ID的所有会话(session)。 + + +
+
+ JMS连接工厂的管理 + 使用类(ObjectName org.hornetq:module=JMS,type=ConnectionFactory, + name="<连接工厂名>"或者资源名jms.connectionfactory.< + 连接工厂名>)可以管理JMS的连接工厂。 + + + 获得连接工厂的属性 + ConnectionFactoryControl类可以用来获得连接工厂的属性( + 例如getConsumerWindowSize()方法可以获得接收者流控制的窗口大小, + isBlockOnNonDurableSend()方法可以知道从这个连接工厂创建的发送 + 者是否采用阻塞方式发送非持久的消息,等等)。 + + +
+
+ JMS队列管理 + 使用JMSQueueControl类(ObjectName org.hornetq:module=JMS, + type=Queue,name="<队列名>"或资源名 jms.queue.<队列名 + >可以管理JMS队列。 + JMS队列的管理操作与核心队列的管理十分相似。 + + + 过期,发送到死信地址和移动消息 + 可以使用expireMessages()方法将队列中的消息设成过期消息。 + 如果配置有过期地址,消息就会被发到过期地址。过期地址可以用 + setExpiryAddress()方法来设定。 + 使用sendMessagesToDeadLetterAddress()方法可以将消息发送到死信地址。 + 它返回发送到死信地址消息的数量。如果没有设定死信地址,那么消息会被丢弃。使用 + setDeadLetterAddress()方法可以设定队列的死信地址。 + moveMessages()方法将消息从一个队列移动到另一个队列。 + + + 列表与删除消息 + 使用listMessages()方法可以列出一个队列中的所有消息。它返回的是一个 + Map的数组。每一个Map对应一个消息。 + 使用removeMessages()方法可以从队列中删除消息。如果带的参数是消息ID, + 返回的是一个布尔常是;如果带的参数是一个过滤器,则返回删除的消息数。带有过滤器参数的removeMessages()方法只删除过滤器选择的消息。如果些参数是一个空字符串,那么将 + 删除所有的消息。 + + + 消息计数 + 使用getMessageCount()方法可以得到队列中的消息数。另外,方法 + countMessages()可以得到队列中所有与过滤器相匹配的消息数。 + + + 修改消息的优先级 + 消息的优先级可以用changeMessagesPriority()方法修改。如果是带一个消 + 息ID参数,它返回的是一个布尔常量;如果是带一个过滤器参数,则它返回的是优先级更新了的消息数。 + + + 消息计数器 + listMessageCounter()方法和listMessageCounterHistory() + 方法可以用来列出队列中的所有消息计数器。(参见 )。 + + + 获取队列的属性 + JMSQueueControl类可以用来获取JMS队列的设置参数(例如方法isTemporary() + 可以判断队列是否为临时的,方法isDurable()可以判断队列是否为持久的等等)。 + + + 队列的暂停与恢复 + JMSQueueControl可以暂停一个队列或恢复一个队列。 + 如果一个队列被暂停,它虽然可以继续接收消息但是不传递消息; + 当被恢复时,队列又会开始传递消息。 + + +
+
+ JMS话题(Topic)的管理 + JMS话题的管理是通过TopicControl类( + the ObjectName org.hornetq:module=JMS,type=Topic,name="<话题名>" + 或资源名 jms.topic.<话题名>)。 + + + 订阅和消息的列表 + listAllSubscriptions()listDurableSubscriptions()listNonDurableSubscriptions()方法可以列出话题的不同订阅。 + 这些方法都返回Object数组,表示订阅的细节(如订阅名, + 客户ID,持久性,消息计数等)。用listMessagesForSubscription()方法可以列出一个订阅上的JMS消息。 + + + 删除订阅 + 持久性订阅可以使用dropDurableSubscription()方法来删除。 + + + 订阅消息计数 + countMessagesForSubscription()方法可以得到一个订阅上面所持有 + 的消息数(还可带一个消息选择器来得出有多少消息与之匹配)。 + + +
+
+
+
+ 使用JMX + HornetQ提供了JMX + HornetQ通过MBean的接口暴露其JMX管理操作。它将自己的资源注册到org.hornetq域。 + 比如,用来管理一个名为exampleQueueJMS队列的ObjectName是: + + org.hornetq:module=JMS,type=Queue,name="exampleQueue" + + MBean为: + + org.hornetq.api.jms.management.JMSQueueControl + + MBean的ObjectNameorg.hornetq.api.core.management.ObjectNameBuilder来产生出来的。你也可以使用jconsole来查找你想要的MBean的ObjectName + 使用JMX来管理HornetQ与用JMX管理其它Java应用程序没有什么不同。你可以使用反射或者创建MBean代理的方法。 +
+ 配置JMX + 默认情况下HornetQ的JMX是打开的。将hornetq-configuration.xml文件中的jmx-management-enabled设置为false就可以关闭JMX: + +<!-- false to disable JMX management for HornetQ --> +<jmx-management-enabled>false</jmx-management-enabled> + + 如果JMX功能是打开的,则使用jconsole可以管理本地的HornetQ。 + + 出于安全考虑,默认情况下JMX远程连接是关闭的。参见Java管理指南来配置服务器的远程管理(系统变量必须在run.shrun.bat中定义)。 + + HornetQ默认使用JMX域名"org.hornetq"。如果要用一个MBeanServer管理多个HornetQ服务器,可以将每个HornetQ + 服务器配置成不同的JMX域。方法就是在hornetq-configuration.xml文件中设置jmx-domain + +<!-- use a specific JMX domain for HornetQ MBeans --> +<jmx-domain>my.org.hornetq</jmx-domain> + +
+ MBeanServer的配置 + HornetQ在独立运行时使用Java虚拟机的Platform MBeanServer来注册其MBean。这在JBoss Microcontainer(微容器)的bean + 文件中进行配置(参见): + <!-- MBeanServer --> +<bean name="MBeanServer" class="javax.management.MBeanServer"> + <constructor factoryClass="java.lang.management.ManagementFactory" + factoryMethod="getPlatformMBeanServer" /> +</bean> + + 当与AS 5+集成运行时,它使用应用服务器自己的MBean服务,这样就可以使用它的jmx-console: + <!-- MBeanServer --> +<bean name="MBeanServer" class="javax.management.MBeanServer"> + <constructor factoryClass="org.jboss.mx.util.MBeanServerLocator" + factoryMethod="locateJBoss" /> +</bean> + +
+
+
+ 例子 + 参见,这个例子展示了如何使用远程JMX连接或MBean代理来管理HornetQ。 +
+
+
+ 使用核心接口 + 核心管理接口的调用实际上是向一个特殊的地址发送核心消息。这个特殊地址称为管理地址 + 管理消息是一些定义了一些固定属性的普通核心消息。服务器通过这些属性来解释管理操作: + + + 管理资源的名称 + + + 管理操作的名称 + + + 管理操作的参数 + + + 当一个管理消息发送到管理地址时,HornetQ服务器将从中提取出相应的信息,再调用相应的管理资源的方法,之后向 + 该管理消息的回答地址(reply-to address,由ClientMessageImpl.REPLYTO_HEADER_NAME + 定义)发送一个管理回答 + 一个ClientConsumer用来接收管理回答并提取出其中的操作的結果(如果有的话)。 + 考虑到可移植性,返回的結果采用的是格式的字符串,而没有采用Java的序列化技术 + (org.hornetq.api.core.management.ManagementHelper可以用来将JSON字符串 + 转换成Java对象)。 + 使用以下步骤可以简化使用核心消息调用管理操作: + + + 创建一个ClientRequestor对象,用来发送管理消息并接收回答。 + + + 创建一个ClientMessage + + + 使用org.hornetq.api.core.management.ManagementHelper类来帮助设置消息的管理参数。 + + + 通过ClientRequestor将消息发送 + + + 使用 org.hornetq.api.core.management.ManagementHelper类从管理操作結果中提取返回值。 + + + 例如,要得到核心队列exampleQueue中消息的数量: + + ClientSession session = ... + ClientRequestor requestor = new ClientRequestor(session, "jms.queue.hornetq.management"); + ClientMessage message = session.createMessage(false); + ManagementHelper.putAttribute(message, "core.queue.exampleQueue", "messageCount"); + ClientMessage reply = requestor.request(m); + int count = (Integer) ManagementHelper.getResult(reply); + System.out.println("There are " + count + " messages in exampleQueue"); + + 管理操作名及其参数必须和management包中定义的Java接口一致。 + 资源的名称是用org.hornetq.api.core.management.ResourceNames类来生成的, + 命名都非常直观(如核心队列exampleQueue的名称为core.queue.exampleQueue, + JMS Topic exampleTopic的名称为jms.topic.exampleTopic,等等)。 + +
+ 配置核心管理 + 管理地址的配置在文件hornetq-configuration.xml中: + + <management-address>jms.queue.hornetq.management</management-address> + + 它的默认地址是jms.queue.hornetq.management (地址前缀加上 + “jms.queue”是为了方便JMS客户端也可以向它发送管理消息。 + 管理地址需要一个特殊的用户权限 + manage来接收并处理管理消息。这个权限也在hornetq-configuration.xml文件中配置: + + <!-- users with the admin role will be allowed to manage --> + <!-- HornetQ using management messages --> + <security-setting match="jms.queue.hornetq.management"> + <permission type="manage" roles="admin" /> + </security-setting> + +
+
+
+ 使用JMS进行管理 + 使用JMS管理HornetQ与使用核心API管理HornetQ十分相似。 + 其中一个重要的不同是JMS需要一个JMS队列来发送消息(而核心接口使用的是一个地址)。 + 管理队列是一个特殊的队列,它需要客户端直接实例化: + + Queue managementQueue = HornetQJMSClient.createQueue("hornetq.management"); + + 其余步骤完全和使用核心接口一样,只是相应的对象不同: + + + 创建一个QueueRequestor来向管理地址发送管理消息并接收回答。 + + + 创建一个消息 + + + 使用 org.hornetq.api.jms.management.JMSManagementHelper类向消息中设置管理参数。 + + + 再使用QueueRequestor发送消息。 + + + 使用org.hornetq.api.jms.management.JMSManagementHelper来从回答中提取返回結果。 + + + 例如,要得到一个JMS队列exampleQueue中有多少消息: + + Queue managementQueue = HornetQJMSClient.createQueue("hornetq.management"); + + QueueSession session = ... + QueueRequestor requestor = new QueueRequestor(session, managementQueue); + connection.start(); + Message message = session.createMessage(); + JMSManagementHelper.putAttribute(message, "jms.queue.exampleQueue", "messageCount"); + Message reply = requestor.request(message); + int count = (Integer)JMSManagementHelper.getResult(reply); + System.out.println("There are " + count + " messages in exampleQueue"); + +
+ 配置JMS管理 + JMS管理的配置与核心接口管理的配置步骤是一样的(参见)。 +
+
+ 例子 + 参见,它展示了如何使用JMS消息来管理HornetQ。 +
+
+ +
+ 管理通知 + HornetQ可以向listener发送各种事件的通知(如资源的创建,安全破坏等)。 + 有三种方式接收管理通知 + + + JMX通知 + + + 核心消息 + + + JMS消息 + + +
+ JMX通知 + 如果设置了JMX(参见),就可以通过订阅以下 + 两个MBean来获得通知: + + + org.hornetq:module=Core,type=Server 可以获得有关 + 核心资源的通知 + + + org.hornetq:module=JMS,type=Server可以获得有关 + JMS资源的通知 + + +
+
+ 核心消息通知 + HornetQ定义了一个特殊的管理通知地址。核心队列绑定到该地址后,客户 + 端就可以接收以核心消息形式发送的管理信通知了。 + 一个核心客户端要想接收到管理通知,它必须要创建一个队列并绑定到这个管理通知地址上,然后从这个 + 队列接收通知。 + 通知消息就是普通的核心消息加上相关的属性(如通知类型,事件发生时间,资源等)。 + 由于是标准的核心消息,使用选择器还能够过滤掉一部分通知而只接收感兴趣的通知。 +
+ 配置核心管理通知地址 + 用来发送管理通知的地址在文件中hornetq-configuration.xml配置: + + <management-notification-address>hornetq.notifications</management-notification-address> + + 默认的地址是hornetq.notifications +
+
+
+ JMS消息通知 + HornetQ还可以通过JMS消息的方式发送通知。 + 这种方式与核心消息通知相似,但是有一个重要的不同:JMS消息需要一个JMS的目标(通常是一个Topic)。 + 要通过一个JMS目标来接收管理通知,必须将服务器的管理通知地址修改为以jms.queue开头(如果是一个 + JMS队列)或者jms.topic(如果是一个话题): + + <!-- 通知将从JMS话题 "notificationsTopic"上接收 --> + <management-notification-address>jms.topic.notificationsTopic</management-notification-address> + + 这个通知话题一旦被创建,就可以接收消息了(或者使用MessageListener): + + Topic notificationsTopic = HornetQJMSClient.createTopic("notificationsTopic"); + + Session session = ... + MessageConsumer notificationConsumer = session.createConsumer(notificationsTopic); + notificationConsumer.setMessageListener(new MessageListener() + { + public void onMessage(Message notif) + { + System.out.println("------------------------"); + System.out.println("Received notification:"); + try + { + Enumeration propertyNames = notif.getPropertyNames(); + while (propertyNames.hasMoreElements()) + { + String propertyName = (String)propertyNames.nextElement(); + System.out.format(" %s: %s\n", propertyName, notif.getObjectProperty(propertyName)); + } + } + catch (JMSException e) + { + } + System.out.println("------------------------"); + } + }); + +
+
+ 例子 + 参见。本例采用了JMS的 + MessageListener方法从HornetQ + 服务器接收管理通知。 +
+
+
+ 消息计数器 + HornetQ保存着队列的历史数据,而消息计数器可以从服务器上获取这些信息。 + 这些信息可以显示队列的一些趋势。例如,使用管理接口你可以定期来查询一个队列 + 的消息数量。但这个数量不足以说明这个队列是否在工作--也许这个队列既没有发送者也没有接收者;也许这个队列 + 在不停地发送与接收,但是发送消息的速度与接收的速度相等。两咱情况下都会造成消息数在队列中不变,但实际队列 + 的状态确完全不一样。 + 消息计数器可以提供队列的更多的信息: + + + count + 从服务器启动时加到队列中的消息数。 + + + countDelta + 上次消息计数器更新后加入到队列的消息数。 + + + depth + 队列当前的消息数。 + + + depthDelta + 上次消息计数器更新后被加入/删除的消息总数。 + 例如,如果depthDelta-10,就意谓着有10个消息从 + 队列中删除了(有可能是2个消息加入了但有12个消息删除了)。 + + + lastAddTimestamp + 最后一个消息加入到队列的时间戳。 + + + udpateTimestamp + 最后一次消息计数器更新的时间戳。 + + +
+ 配置消息计数器 + 默认的消息计数器是关闭的,因为它需要占用一些内存。 + 要打开消息计数器,编辑hornetq-configuration.xml文件将其设为true + +<message-counter-enabled>true</message-counter-enabled> + + 消息计数器会保存队列的历史数据(默认是10天)。它以一定间隔(默认10秒一次)对每个队列进行扫描。 + 如果消息计数器打开,这些参数可以在hornetq-configuration.xml文件中进行调整: + +<!-- keep history for a week --> +<message-counter-max-day-history>7</message-counter-max-day-history> +<!-- sample the queues every minute (60000ms) --> +<message-counter-sample-period>60000</message-counter-sample-period> + + 使用管理接口可以获得消息计数器。例如要使用JMX得到一个JMS队列的消息计数器: + +// retrieve a connection to HornetQ's MBeanServer +MBeanServerConnection mbsc = ... +JMSQueueControlMBean queueControl = (JMSQueueControl)MBeanServerInvocationHandler.newProxyInstance(mbsc, + on, + JMSQueueControl.class, + false); +// message counters are retrieved as a JSON String +String counters = queueControl.listMessageCounter(); +// use the MessageCounterInfo helper class to manipulate message counters more easily +MessageCounterInfo messageCounter = MessageCounterInfo.fromJSON(counters); +System.out.format("%s message(s) in the queue (since last sample: %s)\n", + counter.getDepth(), + counter.getDepthDelta()); + +
+
+ 例子 + 参见。这个例子使用消息计数器来获得一个JMS队列的相关数据。 +
+
+
+ 通过JBoss应用服务器的Admin Console来管理HornetQ的资源 + 通过JBoss应用服务器的Admin Console可以创建与配置HornetQ的各种资源。 + Admin Console允许你创建各种目标(JMS话题与队列)和JMS的连接工厂。 + 登录admin console后你在左边的树中会看到JMS Manager节点。所有HornetQ的资源都属于这个节点。在它的下面有JMS Queues、 + Topics以及Connection Factories。分别点击它们将会看到相应的资源。下面将解释如何创建并配置它们。 +
+ JMS队列 + 要创建一个新的JMS队列,点击JMS Queues将列出当前的队列。在右边的窗口中有一个“add a new resource“按钮,点击这个按钮 + 并选择默认(JMS 队列)模板。点击“continue“。填入相应的队列名称与JNDI名称。其它的参数值都给出了合理的默认值,通常情况下 + 不用改动它们。在底部可以配置安全角色,如果你不提供将使用默认的配置。当这个队列成功创建后这些配置将会显示出来。除了队列的名字 + 和JNDI名字外,其它参数都可以在contiguration标签页下进行修改。下面就对它们分别解释。 + 点击 configuration后你将看到如下显示: + + + + name和JNDI name是不能改变的。如果你想改变它们,必须重新创建队列。其它选项是关于地址设置与安全设置。 + 默认的地址设置来自于服务器的配置。如果你通过console修改或创建一个队列,那么就会增加一条新的地址设置。有关 + 地址设置的完整说明参见 + 要删除一个队列,只要点击队列名称旁边的“delete“按钮即可。与此队列相关的任何地址设置或安全设置也将被删除。 + 配置的最后一部分是安全角色。如果在创建时没有给出则默认的安全设置将会显示在屏幕上。如果它们被修改并更新则队列的安全设置 + 将被更新。关于安全设置参见 + 在console中还有一个metrics标签页,它显示了队列的各项统计数据,如消息计数,接收者计数等。 + 在control标签页中可以对队列进行各种操作,比如启动和停止队列,对队列中的消息进行列表,移动,变为过期,删除等。 + 要进行一项操作只要点击相应的按钮,然后在出现的提示中输入相应的参数,再点击ok按钮即可。操作的結果会显示在屏幕的底部。 +
+
+ JMS话题 + 创建及配置JMS话题几乎与队列的操作是一样的。唯一不同的是这些配置应用于一个代表订阅的队列。 +
+
+ JMS连接工厂 + JMS连接工厂的创建的操作过程与上述队列或话题的操作一致,只是配置具体的参数不同而已。关于连接工厂的参数参见配置索引。 +
+
+
diff --git a/docs/user-manual/zh/master.xml b/docs/user-manual/zh/master.xml new file mode 100644 index 0000000000..9023ca09a1 --- /dev/null +++ b/docs/user-manual/zh/master.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]> + + + HornetQ 2.1用户手册 + Putting the buzz in messaging + + + + + ¬ice; + &preface; + &project-info; + &messaging-concepts; + &architecture; + &using-server; + &using-jms; + &using-core; + &jms-core-mapping; + &client-classpath; + &examples; + &wildcard-routing; + &wildcard-syntax; + &filter-expressions; + &persistence; + &configuring-transports; + &connection-ttl; + &transaction-config; + &flow-control; + &send-guarantees; + &undelivered-messages; + &message-expiry; + &large-messages; + &paging; + &queue-attributes; + &scheduled-messages; + &last-value-queues; + &message-grouping; + &pre-acknowledge; + &management; + &security; + &appserver-integration; + &jms-bridge; + &client-reconnection; + &diverts; + &core-bridges; + &duplicate-detection; + &clusters; + &ha; + &libaio; + &thread-pooling; + &logging; + &embedding-hornetq; + &intercepting-operations; + &interoperability; + &perf-tuning; + &configuration-index; + + + diff --git a/docs/user-manual/zh/message-expiry.xml b/docs/user-manual/zh/message-expiry.xml new file mode 100644 index 0000000000..5feb6f2a99 --- /dev/null +++ b/docs/user-manual/zh/message-expiry.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + 过期的消息 + 消息在发送时有一个可选的生存时间属性。 + 如果一个消息已经超过了它的生存时间,HornetQ不再将它传递给任何接收者。 + 服务器会将过期的消息抛弃。 + HornetQ的地址可以配置一个过期地址,当消息过期时,它们被从队列中删除并被转移到过期地址中。 + 多个不同的队列可以绑定到一个过期地址上。这些过期的消息过后可以接收下来以供分析用。 +
+ 过期消息的配置 + 如果使用HornetQ核心API,可以直接在消息上设置过期时间: + +// message will expire in 5000ms from now +message.setExpiration(System.currentTimeMillis() + 5000); + + JMS的MessageProducer可以设置一个TimeToLive来控制其发送的消息: + +// messages sent by this producer will be retained for 5s (5000ms) before expiration +producer.setTimeToLive(5000); + + 从过期地址中接收下来的消息有以下属性: + + + _HQ_ORIG_ADDRESS + 这是一个字符串,它是该消息的原始地址 + + + _HQ_ACTUAL_EXPIRY + 一个长整型量,代表此消息实际过期时间 + + +
+
+ 配置过期地址 + 过期地址配置在地址设置(address-setting)中: + +<!-- expired messages in exampleQueue will be sent to the expiry address expiryQueue --> +<address-setting match="jms.queue.exampleQueue"> + <expiry-address>jms.queue.expiryQueue</expiry-address> +</address-setting> + + 如果没有定义过期地址,当一个消息过期时,它将被删除。配置过期地址时可以使用通配符 + 来给一组地址配置过期地址。(参见)。 +
+
+ 配置过期回收线程 + HornetQ有一个回收线程定期地检查队列中的消息,目的是发现是否有消息过期。 + hornetq-configuration.xml文件中可以对回收线程进行配置,参数如下: + + + message-expiry-scan-period + 过期消息的扫描间隔(单位毫秒,默认为30000ms)。如要关闭扫描,将其设为-1 + + + message-expiry-thread-priority + 回收线程的优先级(为0到9的整数,9优先级最高。默认是3)。 + + +
+
+ 例子 + 参见。这个例子展示了在JMS中如何配置使用消息过期功能。 +
+
diff --git a/docs/user-manual/zh/message-grouping.xml b/docs/user-manual/zh/message-grouping.xml new file mode 100644 index 0000000000..c41341fc1b --- /dev/null +++ b/docs/user-manual/zh/message-grouping.xml @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + 消息分组 + 消息组是具有下列特性的消息集合: + + + 在一个消息组中的消息有相同的组标识(id),即它们的JMSXGroupID(JMS)或 + _HQ_GROUP_ID(HornetQ核心)的值相同。 + + + 不管存在多少个接收者(consumer),一个消息组的所有消息总是被同一个接收者所接收。一个组id总是 + 与同一个接收者相关联。如果这个接收者被关闭,另外一个接收者就被选中来代替它接收该消息组的消息。 + + + 消息组在需要同一个接收者按顺序处理某类消息的时候很有用。 + 一支股票的订购就是一个例子。某支股票的订单需要同一个接收者按顺序处理。于是可以每支股票有一个接收者 + 来处理(也可以用少一些的接收者),然后将每支股票的名字设在消息的_HQ_GROUP_ID参数中。 + 这样可以保证一支股票的消息只被同一个接收者处理。 +
+ 使用核心接口 + 用来标识一个消息组的参数是 "_HQ_GROUP_ID"" (或者相应的常量MessageImpl.HDR_GROUP_ID)。另一种方法是在SessionFactory + 中将autogroup设置为true。这样做的话组id是随机给出的。 +
+
+ 使用JMS + 用来标识一个消息组的参数是JMSXGroupID + + // send 2 messages in the same group to ensure the same + // consumer will receive both + Message message = ... + message.setStringProperty("JMSXGroupID", "Group-0"); + producer.send(message); + + message = ... + message.setStringProperty("JMSXGroupID", "Group-0"); + producer.send(message); + + 另一个方法是将HornetQConnectonFactoryautogroup + 属性设为true,或者在hornetq-jms.xml文件中进行配置: + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <autogroup>true</autogroup> +</connection-factory> + 还可以通过连接工厂来设置组id。来自这个连接工厂的所有的发送者(producer)发送的消息的JMSXGroupID将具有指定的值。这种方法需要在hornetq-jms.xml + 文件中作如下配置: + + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <group-id>Group-0</group-id> + </connection-factory> + +
+
+ 例子 + 参见。这个例子展示的是在JMS中如何配置与使用消息组。 +
+
+ 例子 + 是另外一个消息组的例子,在这个例子中通过配置连接工厂 + 来使用消息组。 +
+
+ 集群中的消息组 + 在集群中使用消息组是相对比较复杂的。这是因在在集群中,一个消息组中的消息有可能被送到集群中的任一全节点, + 这就要求每个节点都要知道这个消息是属于哪个节点上的哪个接收者(consumer)。一个消息组的消息往往会被发送到 + 集群中的一个节点,而该消息组的接收者在另一个节点上。每个节点都要知道这些细节以便能将消息正确路由到所属接收 + 者所在的节点上。 + 为了解决上述问题,我们使用了消息组处理器。每个节点都有一个自己的消息组处理器。当一个带有组id的消息收到时, + 这些节点的消息组处理器就会协同作出决定该如何对这个消息进行路由。 + 消息组处理器有两种:本地消息组处理器和远程消息组处理器。在一个集群中要选择一个节点作为本地消息组处理器的 + 节点,集群中所有其它的节点都持有远程消息组处理器。在集群中由本地消息组处理器最終决定消息怎样路由,其它的远程 + 处理器配合本地处理器完成决策。消息组处理器的配置在hornetq-configuration.xml + 文件中,下面就是一个例子: + <grouping-handler name="my-grouping-handler"> + <type>LOCAL</type> + <address>jms</address> + <timeout>5000</timeout> + </grouping-handler> + + <grouping-handler name="my-grouping-handler"> + <type>REMOTE</type> + <address>jms</address> + <timeout>5000</timeout> + </grouping-handler> + address属性表示一个集群的连接以及它使用的地址。有关如何配置集群 + 参见集群章节。timeout属性代表做出路由决定所需要等待的时间。如果超过 + 了这个时间还没有做出决定,则会抛出异常。这可以保证严格的顺序。 + 收到消息的节点会首先提出一个消息路由的建议。它采用轮询方式来选择一个合适的路由。它首先选择一个本地的队列,之后 + 再选择一个有接收者的队列。如果这个建议被所有组处理器接受,消息就会被路由到所选的队列。如果被拒绝就提出另一个路 + 由方案,如此反复直到方案被接受为止。队列选择后所有其它的节点都将消息路由到这个队列。这样所有的消息组的消息在一个 + 节点上进行处理,也就是该节点上的接收者接收所有的同组的消息。 + 由于只有一个本地处理器,如果它的节点出现故障则无法做出决定。这时所有的消息将不能被传递,并且会抛出异常。 + 为了避免这一单点故障,本地处理器可以在备份节点上有一个复本。只要创建备份节点并配置一个相同的本地处理器即可。 + +
+ 集群消息组的最佳使用惯例 + 下面是一些很好的建议: + + 尽可能使接收者均匀分布在不同的节点上。由于消息组的消息总是传递到同一个队列的同一个接收者, + 如果你经常性地创建与关闭接收者,就可能出现消息由于没有接收者而传递不出去,造成消息在队列中 + 不断积累的情况。因此,尽量要避免关闭接收者,或者确保有足够数量的接收者。例如,如果你的集群 + 有3个节点,那么就创建3个接收者。 + + + 尽可能使用持久型队列。如果消息组的消息与一个队列绑定,一旦这个队列被删除,其它节点可能仍然 + 尝试向这个已删除的队列路由消息。为避免这种情况,要确保这个队列由发送消息的会话来删除。这样如果 + 下一个消息发出后发现原来的队列被删除,新的路由建议就会提出。另外一种方案是你可以重新使用一个不 + 同的组ID。 + + + 一定要确保本地的消息组处理器有备份。这样在有故障时消息组仍然可以正常工作。 + + +
+
+ 集群消息组例子 + 参见,这个例子给出了如何在HornetQ集群中配置消息组。 +
+
+
diff --git a/docs/user-manual/zh/messaging-concepts.xml b/docs/user-manual/zh/messaging-concepts.xml new file mode 100644 index 0000000000..eef961c41a --- /dev/null +++ b/docs/user-manual/zh/messaging-concepts.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + 消息的相关概念 + HornetQ是一个异步的 + 面向消息的中间件。在本文档中我们简称为消息系统。 + 首先我们简要介绍消息系统是做什么的,在哪些领域得到应用,以及与消息相关的一些概念。 + 如果你已经对消息系统的这些方面的知识很熟悉,可以跳过本章内容。 +
+ 消息相关的概念 + 消息系统可以将不同异种的系统松散地耦合在一起,提供基本的可靠性,事务及其它功能的支持。 + 与基于远程过程调用 + (RPC) 的系统不同,消息系统主要采用异步传送的方式,请求与响应之间的耦合很松。 + 大多数的消息系统也支持请求-响应的方式,但这不是消息的主要功能。 + 端与端之间采用异步通信的好处是可以充分利用硬件资源,最大程度减少IO操作引起的线程阻塞,并充分利用网络带宽。 + 而采用RPC方式,每一个请求必须要等待响应返回才能继续,因而要依赖你的网络的速度 + (latency)。异步系统则能将消息以管道的方式传送, + 它只受带宽的限制,并不因网络速度而降低效率。利用异步的方式往往可以创建更高效率的应用。 + 消息系统将消息的发送方与接收方分开,使消息的发送所接收完全独立于对方,有利于创建灵活的、松耦的系统。 + 大型的企业应用通常采用消息系统来实现一种消息总线,并基于这个总线将企业的各种不同结构的系统松散地连在一起工作。 + 消息总线也常常是企业服务总线(ESB)的核心。 + 采用这种方式搭建的松耦合系统可以非常容易地扩展和修改。由于系统各模块之间的信赖关系很弱,所以在需要时可以对系统灵活地添加和减少模块。 +
+
+ 消息的种类 + 消息系统通常支持两种异步的传送模式:消息队列 + (又称为点对点消息传送)模式和广播/订阅模式 +
+ 消息队列模式 + 在这种模式中消息被发送到队列中。通常消息会被持久化以保证可靠的传送。消息系统会将队列中的消息传送给接收者 + (receiver或consumer)。当接收者处理消息完成后,它会发出完成的通知给消息系统。得到通知的消息就会从队列 + 中删除,因此该消息不会被再次传送。如果在收到消息前消息服务器发生故障导致系统崩溃,当系统恢复时, + 该消息会被再次传送给接收者。 + 这种模式允许一个队列有多个接收者。但是一个消息最多只传送给一个接收者。一个队列的消息发送者(sender或producer) + 与接收者是完全独立的。它们不知道彼此的存在。 + 图书订单系统是一个典型的消息队列的用例。每一个订单都被包装为一个消息传送到订单队列中。假定有多个图书订购的终 + 端向订单队列发关订单消息。当一个消息到达队列时它被持久化以防止系统崩溃时订单的丢失。再假定有多个订单处理中心 + 分布在不同的机器上接收这个订单队列的消息。消息系统将每一个消息发送给其中一个(并且只发送一个)接收者(即一个订单处理模块)。 + 这样不同的订单可能会被不同的处理模块处理,但一个订单只会被处理一次。 + 当订单处理模块接收到一个消息,对它进行处理后将订单信息发送给仓库系统并更新订单数据库。处理完成后它会发出通知告诉服务 + 器可以删除此消息。通常这一系列和处理(接收,发送给仓库系统,更新数据库以及通知)会被作为一个交易来处理以保证它的完整性 + (ACID)。 +
+
+ 消息的广播/订阅模式 + 这种模式中,多个发送者将消息发送到服务器中一个特定的实体,JMS中通常称为话题(topic)。 + 一个Topic常常有多个订阅者(subscription,即消息的接收者)。 + 与消息队列的接收者不同,每个订阅者都会收到发送的队列中的每个消息。 + 订阅者可以选择为固定的方式(durable)。采用这种方式的订阅者, + 其消息会保留直到被接收为止。即使是其间服务器发生过故障或重启也不受影响。非固定的订阅者只在其连接期间有效, + 一但连接断开其消息将不会保留。 + 电子消息订阅是消息广播模式的一个例子。当新闻被世界各地的编辑編好后,他们将其发关到新闻topic。 + 同样对这些新闻兴趣的读者会订阅这个topic。消息系统将保证每个订阅者都能够收到每一篇新闻稿。 +
+
+
+ 传送的可靠性 + 大多数的消息系统是可靠的消息传送系统。消息系统可以保证一个消息被传送 + 给一个并且只传送给一个队列的接收者或每个话题的固定的订阅者。一个消息不会被传送两次。即使在系统出现故障时也是如此。 + 这一特性对于很多企业来说是非常重要的。比如你想要保证订单不丢失或被处理两次以上,就可以利用该特性。 + 在某些情况下这种“一次并且只有一次”的传送方式并不是很重要,重复消息和消息的丢失并不影响系统的功能。比如股票价格 + 的更新消息,它并不需要保证每次都能收到,因为前一次更新很快就会被下一次代替。这样的功能消息系统也可以支持。 +
+
+ 交易(Transactions) + 消息系统通常支持在一次本地交易中发送并通知多个消息。HornetQ还支持分布式交易。它可以通过Java的XA和JTA接口, + 将消息的发送与通知做为一个分布式交易的一部分来完成。 +
+
+ 持久性(Durability) + 消息可以分为持久消息和非持久消息。持久消息被保存到永久的存储介质中,不受服务器故障与重启的影响。非持久消息在服务 + 器故障与重启时则会丢失。像订单,交易信息属于持久消息,而股票价格更新由于它的即时性则可以做为非持久消息来处理。 +
+
+ 消息API和协议 + 客户端的应用程序怎样访问消息系统来进行消息的发送与接收呢? + 一些消息系统提供私有的API,客户端可以通过这些私有的API与相应的消息系统交互,实现消息的收发。 + 除此之外,还存在着一些标准的交互方式可供使用。另外还有一些标准正在不断完善。下面我们就介绍一下这些标准。 + Let's take a brief look at these: +
+ Java消息服务(JMS) + JMS 属于Sun公司JEE规范的一部分。 + 它定义了一套标准的API支持消息队列和广播-订阅模式。JMS是一套非常精简的通用的标准,它将当时已经存在的消息系统的共同功能包括了进去。 + + JMS是一个广泛使用的API,绝大多数的消息系统都支持它。JMS只有Java的客户端才可以使用。 + JMS并没有定义传输的格式(wire format)。因此不同的JMS消息服务器的和客户端相互之间通常不能交互,这是因为每个消息系统都自己的传输格式。 + HornetQ全面支持JMS 1.1 API。 +
+
+ 专有的API + 很多系统提供自己的一套API来与其消息系统进行通迅,其优势是它可以允许客户端使用其全部的功能。 + 像JMS那样的标准API往往不能提供许多消息系统所支持的额外的功能。 + HornetQ提供了一套自有的核心API,客户端程序可以通过它充分利用HornetQ的强大功能。 + 这对于一些JMS API满足不了的需求是非常有用的。 +
+
+ RESTful API + 采用REST REST[http://en.wikipedia.org/wiki/Representational_State_Transfer]方式与消息系统交互越来越被关注。 + 由于云计算技术的API标准目前倾向于采用REST的方式,所以采用REST方式的消息系统很有望成为云计算中消息传送的标准。 + REST方式中的各种消息资源以URI的方式来定义。用户通过一套很简单的操作与这些资源相交互,如PUT、POST、GET等。HTTP通常用来作为REST方式的通信协议。 + 采用HTTP的好处是它很简单实用,并且internet经过多年的发展已经能很好的支持HTTP协议。 + HornetQ将会很快地支持REST方式的API。 +
+
+ STOMP + Stomp 是为消息系统定义的一套简单的文本传输协议。它定义了一种线上传输的格式, + 因此采用Stomp编写的客户端可以与所有支持Stomp的消息系统交互。Stomp的客户端可以用多种编程语言来实现。 + 有关在HornetQ中如何使用Stomp的详细内容请参见 +
+
+ AMQP + AMQP 是一套可支持互操作的消息规范。 + 它定义了自己的传输格式,因些任何AMQP的客户端都可以和支持AMQP的系统进行交互。AMQP的客户端可以用多种编程语言来实现。 + HornetQ将会很快地支持AMQP。 +
+
+
+ 高可获得性(Availability) + 高可获得性是指在系统中有一个或多个服务器发生故障时仍然能够维持运转的特性。不同的消息系统对高可获得性的支持程度是不同的。 + HornetQ支持自动失效备援(failover),也就是当主服务器出现故障时,当前的会话会自动连接到备用的服务器上。 + 给出了HornetQ的HA特性的详细信息。 +
+
+ 集群 + 许多消息系统支持由多个消息服务器组成的集群。集群可以使发送和接收的负荷分散到不同的服务器中。 + 通过增加集群服务器,可以有效的增加整个集群处理消息的能力。 + 然而不同的消息系统有着不同的集群架构。有的集群架构十分简单,有的集群中成员间的联系很少。 + HornetQ提供了非常先进的可配置的集群模型。根据每个节点接收者(consumer)的多少以及是否具有接收状态,消息在集群中可以进行智能化负载均衡。 + HornetQ还能够在集群中的节点间进行消息的再分发,以避免在某个节点出现消息匮乏(starvation)现象。 + 有关集群的详细内容参见 +
+
+ 桥接(Bridge)和路由(Routing) + 有些消息系统可以将一些分散在不可靠的网络(如广域网或internet)上孤立的集群或节点桥接在一起。 + 通常一个桥的作用是从一台服务器的队列上接收消息然后将消息再转发到另一台服务器的队列中。桥连接可以解决不可靠网络连接的问题。 + 桥有自动重新连接的功能。一旦网络连接中断,桥可以自动进行重试直到重新连接上为止。 + HornetQ的桥接功能可以配置过滤表达式,以实现有条件的转发。另外,它还可以实现消息转换的功能(transformation)。 + HornetQ还允许配置消息在队列之间进行路由。利用它可以完成复杂的路由网络以便在不同队列间进行消息转发与复制,形成一个互连的消息代理(broker)网络。 + 有关的详细内容将在给出。 +
+
+ diff --git a/docs/user-manual/zh/notice.xml b/docs/user-manual/zh/notice.xml new file mode 100644 index 0000000000..c5afdda40d --- /dev/null +++ b/docs/user-manual/zh/notice.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + 法律声明 + + Red Hat, Inc. 以及其他公司2010年版权所有。 + Red Hat公司依照 CC-BY-SA 3.0 Unported(Creative Commons + Attribution-Share Alike)条款之规定授权用戶是用本手册中的文字和插图。 + 有关 CC-BY-SA 的解释请访问http://creativecommons.org/licenses/by-sa/3.0/。根据CC-BY-SA的规定,如果要发布本文档或任何本文档的修改版本,都必须给出原始版本文档的URL。 + Red Hat 作为本文档的授权方声明在相关法律允许的最大范围内放弃CC-BY-SA第4d节所规定的权利。 + diff --git a/docs/user-manual/zh/paging.xml b/docs/user-manual/zh/paging.xml new file mode 100644 index 0000000000..db3e945a63 --- /dev/null +++ b/docs/user-manual/zh/paging.xml @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + 分页转存 + HornetQ可以在有限的内存下支持包含百万消息的超大规模的队列。 + 当有限的内存无法装得下如此多的消息时,HornetQ将它们分页转存到磁盘中,在内存 + 有空闲时再将消息分页装载到内存。通过这样的处理,不需要服务器有很大的内存就可以支持大容量的队列。 + 通过配置可以给一个地址设置一个最大消息值。当这个地址消息数在内存中超过了这个值时,HornetQ开始将多余的消息 + 转存到磁盘中。 + 默认情况下HornetQ不转存任何消息。这一功能必须显式地通过配置来激活。 +
+ 分页文件 + 消息按照所属的地址分别保存在不同的文件中。每一个地址有一个单独的文件夹,每个文件夹内消息被保存在 + 数个文件中(分页文件)。每个文件保存固定数量的消息(由参数page-size-bytes + 设定)。当从分页文件中读取消息时,一个文件的所有消息被读到内存并被路由。当所有消息处理后,该文件就 + 被删除。 +
+
+ 配置 + 你可以配置分页转存文件夹的位置。 + 在主配置文件hornetq-configuration.xml)中 + 可以定义全局的分页转发参数。 + <configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd"> + + ... + + <paging-directory>/somewhere/paging-directory</paging-directory> + + ... + + + 分页转存的配置参数 + + + + + + + 参数名 + 说明 + 默认值 + + + + + paging-directory + 分页转存文件的位置。HornetQ在这个位置下为每个地址建立一个文件夹。 + data/paging + + + +
+
+
+
+ 分页转存模式 + 一个地址只要消息的数量超过定义的值,它就转到分页转存的模式。 + + 分页转存是针对每个地址设置的。如果你为一个地址配置了一个max-size-bytes,那么每个匹配的地址 + 都有一个最大值的限制。但是这并不表示所有匹配的地址的大小总和受这个参数的限制。 + +
+ 配置 + 有关分页转存的配置在主要配置文件(hornetq-configuration.xml) + 的地址设置的部分内。 + <address-settings> + <address-setting match="jms.someaddress"> + <max-size-bytes>104857600</max-size-bytes> + <page-size-bytes>10485760</page-size-bytes> + <address-full-policy>PAGE</address-full-policy> + </address-setting> + </address-settings> + + 下面列出了可用的参数: + + + 分页转存参数设置 + + + + + + + 参数名称 + 说明 + 默认值 + + + + + max-size-bytes + 地址的最大内存值。当消息占用内存超过此值时,进入分页转存模式。 + -1 (关闭分页转存功能) + + + page-size-bytes + 每个分页文件的大小。 + 10MiB (10 * 1024 * 1024 字节) + + + address-full-policy + 要使用分页转存,这个参数必须设为PAGE。PAGE表示多余的消息会被保存到磁盘。 + 如果设为DROP,那么多余的消息将会被丢弃。如果设为BLOCK,当消息占满设定的最大 + 内存时,在客户端消息的发送者将被阻塞,不能向服务器发送更多的消息。 + PAGE + + + +
+
+
+
+
+ 丢弃消息 + 一个地址除了可以分页转存多余的消息外,还可以配置为丢弃多余消息。 + 只要将address-full-policy设为DROP即可。 +
+
+ 阻塞发送者(producer) + 一个地址除了可以分页转存多余的消息外,还可以通过配置使得消息的发送者在消息达到最大值时阻塞消息 + 的发送,以防止服务器由于消息过多而耗尽内存。 + 随着服务器的内存被释放,发送者自动解除阻塞,继续发送消息。 + 这种方式需要将address-full-policy设为BLOCK + 在默认的配置中,所有的地址在消息的量达到10MiB后将阻塞发送者。 +
+
+ 对于有多个队列绑定的地址的配置注意事项 + 当一个消息被路由到一个绑定了多个队列(queue)的地址时(比如JMS的订阅),在内存中仍然只有一分消息的拷贝。每个 + 队列所持有的不过是它的一个引用。因此,只有所有队列中的消息都成功地传递出去后,这个消息才会从内存中清除。也就是说 + 只要有一个队列没有传递这个消息,那么就会造成这个消息处于未被传递的状态。 + 例如: + + + 一个地址绑定了10个队列(queue)。 + + + 其中一个队列没有传递它的消息(也许因为接收者很慢)。 + + + 消息不断增加,触发了分页转存模式。 + + + 而其它9个队列尽管发送了消息,但由于地址将多余的消息转存到磁盘,所以它们都是空的。 + + + 在这个例子中,必须要等到最后一个队列传递了一些消息后,那些转存的消息被装载回内存,其它队列才有机会得到更多的消息。 +
+
+ 分页转存与消息的选择器(selector) + 请注意消息选择器只对内存的消息进行操作。如果大量的消息被转存在磁盘中,而其中有些消息与选择器是相匹配的, + 那么只有内存的消息被传递,这些消息被重新装载入内存后才有可能被传递出去。 + HornetQ不会扫描在磁盘中的消息来找出与选择器匹配的消息。这样做的话需要实现并管理一种索引机制才能使扫描有效地进行,另外 + 需要其它额外的工作。所有这些如果去完成的话,相当于实现一个关系型数据库!这并不是消息系统的主要任务。如果你要完成的任务是 + 从海量的消息中选择少数消息,那么你很可能需要使用的是一个关系型数据库,不是消息系统。因为这相当于表的查询。 +
+
+ 分页转存与浏览器 + 请注意浏览器只对内存中的消息进行操作,它不对转存到磁盘中的消息进行操作。 + 消息是在被路由到任何队列之前进行转存的,所以在转存时刻,它们还没有进入到任何队列中, + 自然也就不可能出现在对某个队列浏览的結果中。 + +
+
+ 分页转存与未通知的消息 + + 请注意如果消息没有被通知,它会一直留在服务器的内存中,占用着内存资源。只要消息在被接收者收到并通知后,它才 + 会在服务器端被清除,空出内存空间以便转存在磁盘上的消息被装载到内存进行传递。如果没有通知,消息不会被清除, + 也就不会空出内存空间,转存到磁盘上的消息也就无法装载到内存进行传递。于是在接收端就会呈现出死机的现象。 + + 如果消息的通知是依靠ack-batch-size的设定进行的批量通知,那么一定要注意不要将 + 分页转存的消息临界值设得小于ack-batch-size,否则你的系统可能会发生死机现象! + +
+ + +
+ 例子 + 是一个说明如何使用HornetQ的分页转发功能的例子。 +
+
diff --git a/docs/user-manual/zh/perf-tuning.xml b/docs/user-manual/zh/perf-tuning.xml new file mode 100644 index 0000000000..a6f43ead2a --- /dev/null +++ b/docs/user-manual/zh/perf-tuning.xml @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + 性能调优 + 本章讲述如何优化HornetQ的性能 +
+ 持久层的优化 + + + 将消息日志放到单独的物理卷上。如果与其它数据共享,例如事务管理、数据库或其它日志等,那么就会 + 增加读写的负担,磁头会在多个不同文件之间频繁地移动,极大地降低性能。我们的日志系统采用的是只 + 添加的模式,目的就是最大程度減少磁头的移动。如果磁盘被共享,那么这一目的将不能达到。另外如果 + 你使用分页转存或大消息功能时,你最好分别将它们放到各自的独立卷中。 + + + 尽量减少日志文件的数量。journal-min-files参数的设置应以满足平均 + 运行需要为准。如果你发现系统中经常有新的日志文件被创建,这说明持久的数据量很大,你需要适当增加 + 这个参数的值,以使HornetQ更多时候是在重用文件,而不是创建新文件。 + + + 日志文件的大小。日志文件的大小最好要与磁盘的一个柱面的容量对齐。默认值是10MiB,它在绝大多数 + 的系统中能够满足需要。 + + + 使用AIO日志。在Linux下,尽量使用AIO型的日志。AIO的可扩展性要好于Java的NIO。 + + + 优化 journal-buffer-timeout。如果增加它的值,吞吐量会增加,但是 + 延迟也会增加。 + + + 如果使用AIO,适当增加journal-max-io可能会提高性能。如果使用的是NIO, + 请不要改变这个参数。 + + +
+
+ 优化JMS + 如果使用JMS接口,有以下几个方面可以改进性能。 + + + 关闭消息id。如果你不需要这个id,用MessageProducer的 + setDisableMessageID()方法可以关闭它。这可以减少消息的大小并且 + 省去了创建唯一ID的时间。 + + + 关闭消息的时间戳。如果不需要时间戳,用MessageProducersetDisableMessageTimeStamp()方法将其关闭。 + + + 尽量避免使用ObjectMessageObjectMessage会带 + 来额外的开销。ObjectMessage使用Java的序列化将它序列化为字节流。在对小的对象 + 进行序列化会占用大量的空间,使传输的数据量加大。另外,Java的序列化与其它定制的技术相比要慢。只有在不得 + 以的情况下才使用它。比如当你在运行时不知道对象的具体类型时,可以用ObjectMessage。 + + + 避免使用AUTO_ACKNOWLEDGEAUTO_ACKNOWLEDGE + 使得每收到一个消息就要向服务器发送一个通知--这样增加的网络传输的负担。如果可能,尽量使用 + DUPS_OK_ACKNOWLEDGE或者CLIENT_ACKNOWLEDGE。或者使用事务性会话,将通知在提交时批量完成。 + + + 避免持久化消息。默认情况下JMS消息是持久的。如果你不需要持久消息,则将其设定为非持久。 + 持久消息都会被写到磁盘中,这给系统带来了明显的负担。 + + + 将多个发送或通知放到一个事务中完成。这样HornetQ只需要一次网络的往返来发生事务的提交,而不是每次发送 + 或通知就需要一次网络的往返通迅。 + + +
+
+ 其它优化 + 在HornetQ中还有其它一些地方可以优化: + + + 使用异步发送通知。如果你在非事务条件下发送持久的消息,并且要保证在send()返回时持久消息已经到达服 + 务器,不要使用阻塞式发送的方式,应该使用异步发送通知的方式。参见中的说明。 + + + 使用预先通知模式。预先通知就是在消息发往客户端之前进行通知。它节省了正常 + 的消息通知所占用的通迅时间。详细的解释请参见 + + + + 关闭安全。将hornetq-configuration.xml文件中的security-enabled + 参数设为false以关闭安全。这可以带来一些性能的提高。 + + + 关闭持久化。如果不你不需要消息持久化,可以将hornetq-configuration.xml + 文件中的persistence-enabled参数设为false来完全关闭持久功能。 + + + 采用延迟方式事务同步。将hornetq-configuration.xml文件中的journal-sync-transactional参数设为false可以得到 + 更好的事务持久化的性能。但是这样做可能会造成在发生故障时事务的丢失。有关详细的说明参见 + + + + 采用延迟方式非事务同步。将hornetq-configuration.xml文件中的journal-sync-non-transactional参数设为false可以得到 + 更好的非事务持久化的性能。但是这样做可能会造成在发生故障时持久消息的丢失。有关详细的说明参见 + + + + 采用非阻塞方式发送消息。将文件hornetq-jms.xml中的参数 + block-on-non-durable-send设为false + (使用JMS和JNDI时)或者直接在上进行相应的设置,可以使 + 消息发送时不阻塞等待服务器的响应。参见 + + + 如果你的接收者速度很快,你可以增加consumer-window-size。这样实际上就关闭了流控制的功能。 + + + 套接字NIO与旧的IO对比。默认情况下HornetQ在服务器端使用套接字NIO技术,而在客户端则使用旧的(阻塞) + IO(参见传输配置一章)。NIO比旧的阻塞式IO有更 + 强的可扩展性,但是也会带来一些延时。如果你的服务器要同时有数千个连接,使用NIO效果比较好。但是如果 + 连接数并没有这么多,你可以配置接收器使用旧的IO还提高性能。 + + + 尽量使用核心接口而不用JMS。使用JMS接口会稍微比使用核心接口性能要低些。这是因为所有JMS操作 + 实际上要转化为核心的操作才能为服务器所处理。在使用核心接口时,尽量使用带有 + SimpleString类型参数的方法。SimpleString与 + java.lang.String不同,它在写入传输层时不需要拷贝。所以你如果在调用中重用SimpleString对象可以避免不必要的拷贝。 + + +
+
+ 传输层的优化 + + + TCP缓存大小。如果你的网络速度很快,并且你的主机也很快,你可以通过增加TCP的发送和接收缓存 + 来提高性能。参见中的详细说明。 + + 注意某些操作系统,如最近的Linux版本中,包括了TCP自动优化功能。如果再手工设置TCP缓存 + 会导致自动优化失效,最終使性能下降! + + + + + 增加服务器中文件句柄数量限制。如果你的服务器将要处理很多并行的连接,或者客户端在快速不停地 + 打开和关闭连接,你要确保在服务器端有足够的文件句柄以供使用。 + 这个限制在不同平台有不同的方法。在Linux系统中,你可以编辑文件/etc/security/limits.conf,增加以下内容: + +serveruser soft nofile 20000 +serveruser hard nofile 20000 + + 它设置了用户serveruser可以最多打开20000个文件句柄。 + + + 利用参数batch-delay并将参数direct-deliver + 设为false来提高小消息的处理效率。HornetQ在其hornetq-configuration.xml + 中预先配置了一个连接器/接受器对(netty-throughput),并且在 + hornetq-jms.xml中配置了一个JMS连接工厂( + ThroughputConnectionFactory)。它们可以用在小消息的处理应用中以提 + 供最佳呑吐量。参见 + + +
+
+ 优化虚拟机 + 我们强烈建议你使用最新的Java 6虚拟机。它在很多方面对以前Java 5的虚拟机进行了改进,特别是在网络功能方面。 + 这是根据我们内部使用Sun的实现测试的結果,可能不适用于其它的Java实现(例如IBM或JRockit)。 + + + 拉圾回收。为了使服务器的运行比较平滑,我们建议使用并行拉圾回收的算法。例如在Sun的JDK使用 + JVM选项-XX:+UseParallelOldGC. + + + 内存设置。尽量为服务器分配更多的内存。HornetQ利用其分页转存技术可以在很少的内存下运行(在 + 中有说明)。但是如果所有队列都在内存运行,性能将会很好。具体需要 + 多少内存要由你的队列的大小和数量以及消息的大小和数量决定。使用JVM参数-Xms + 和-Xmx来为你的服务器分配内存。我们建议两个参数的设为相同的值。 + + + 主动选项(Aggressive options)。不同JVM有不同的JVM优化参数。对于Sun的Hotspot JVM,在这里有一个完整的参数列表。我们建议至少要使用 -XX:+AggressiveOpts + -XX:+UseFastAccessorMethods选项。根据不同的平台,可能还有其它一些参数供你使用, + 以提高JVM的性能。 + + +
+
+ 避免违背设计模式 + + + 重用连接/会话/接收者/发送者。最常见的错误恐怕就是每发送/接收一个消息都要创建一个新的连接 + /会话/发送者或接收者。这样非常浪费资源。这些对象的创建要占用时间和网络带宽。它们应该进行重用。 + + 有些常用的框架如Spring JMS Template在使用JMS时违背了设计模式。如果你在使用了它后性能 + 受到了影响。这不是HornetQ的原因!Spring的JMS模板只有与能缓存JMS会话的应用服务器一起使用 + 才是安全的,并且只能是用于发送消息。使用它在应用服务器中同步接收消息是不安全的。 + + + + 避免使用繁锁的消息格式。如XML,它会使数据量变大进而降低性能。所以应该尽量避免在消息体中使用XML。 + + + 不要为每个请求都创建新的临时队列。临时队列通常用于请求-响应模式的消息应用。在这个模式中消息被发往 + 一个目的,它带有一个reply-to的头属性指向一个本地的临时队列的地址。当消息被收到后,接收方将响应做为消息发 + 往那个reply-to指定的临时的地址。如果每发一个消息都创建一个临时队列,那么性能将会受很大影响。正确的 + 作法是在发送消息时重用临时队列。 + + + 尽量不要使用MDB。使用MDB,消息的接收过程要比直接接收复杂得多,要执行很多应用服务器内部的代码。 + 在设计应用时要问一下是否真的需要MDB?可不可以直接使用消息接收者完成同样的任务? + + +
+
diff --git a/docs/user-manual/zh/persistence.xml b/docs/user-manual/zh/persistence.xml new file mode 100644 index 0000000000..b7f85288da --- /dev/null +++ b/docs/user-manual/zh/persistence.xml @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + 持久化 + 本章我们将描述HornetQ的持久化技术,包括持久化的工作原理和配置方法。 + HornetQ拥有一个高性能的日志(journal)模块来处理持久化。因此它并不依赖一个外部的数据库或第三方持久化产品。这个 + 日志模块针对消息的处理进行了高度的优化。 + 所谓HornetQ日志是一个只添加系统。它由一组磁盘文件构成。每个文件都是预先创建好的并且 + 大小是固定的。文件在创建时都进行了格式化。随着HornetQ不断地处理消息,如消息的增加、更新、删除等,一个个记录被添加 + 到日志中。当一个日志文件写满时,新记录就会写到下一个文件。 + 由于对日志的写入只是对文件的添加,这样有效减少了随机寻道的操作。而随机寻道的操作是磁盘操作中最耗时的操作。 + 所以这种设计可以使磁头的运动降到最低,效率最高。 + 而文件的大小是可以配置的。这使我们可以将文件大小配置为刚好占满一个磁盘柱面。不过现代的磁盘技术是复杂多样的, + 我们并不能控制文件与磁盘柱面的对应关系。尽管如此,我们通过最大限度地降低文件对磁盘柱面的占用,来降低磁头的运动。 + 这是因为在同一个柱面的存取只需要盘面的转动而不需要磁头的运动。 + 当被删除的记录越来越多时,有的文件最終会变成一个没有有效记录的文件。这样的文件就可以回收再利用。HornetQ有 + 一套复杂的文件回收算法来判断一个日志文件是否可以被回收。 + HornetQ还有一套文件整理的算法,它用来将日志文件中不用的空隙移除以达到更高的存贮效率。 + 这个日志系统全面支持事务功能。根据需要它可以支持本地事务或XA型事务。 + 日志系统的大部分是用Java实现的,但是HornetQ在其中实现了一层抽象的文件系统,这样就使得其它的语言实现能 + 方便地“插入”到日志模块中。实际上HornetQ自带有两种实现: + + + Java NIO + 第一种采用的是标准的Java NIO接口来进行文件的操作。它可以在任何安装有Java 1.6或以上的系统中运行。 + NIO的性能是很高的。 + + + Linux 异步IO (Asynchronous IO) + 第二种是采用的Linux系统中的异步IO技术(AIO)。它包括了少量的平台相关的代码(native code)来 +          调用AIO的接口。当数据被保存到磁盘上后,AIO会回调HornetQ进行通知。这样,HornetQ就避免了磁盘写 + 的同步操作。 + 使用AIO通常可以有比NIO更高的性能。 + 采用AIO的日志只能在运行 Linux kernel 2.6 或以上版本的内核的系统中才有。另外你需要安装libaio。 + 有关如何安装libaio请参见 + 另外请注意AIO只在以下文件系统上能正确工作:ext2, ext3, ext4, jfs, xfs。其他文件系统如NFS,虽然 + AIO看上去可以工作,实际上是以较慢的同步的方式在运行。所以不要在NFS上使用日志。 + 有关libaio的更多介绍参见 + libaio是Linux内核项目的一部分。 + + + 标准的HornetQ核心服务器使用了两种日志: + + + 绑定日志 + 这个日志用来保存与绑定有关的数据。其中包括在HornetQ上部署的队列及其属性,还有ID序列计数器。 + 绑定日志是一个NIO型日志。与消息日志相比它的呑吐量是比较低的。 + 这种日志文件的名字采用hornetq-bindings作为前缀。每个文件都有 + bindings这样的扩展。文件大小是1048576,它的位置在bindings文件夹下。 + + + JMS日志 + 这个日志保存所有JMS相关的数据,包括JMS队列,话题及连接工厂,以及它们的JNDI绑定信息。 + 通过管理接口创建的JMS资源将被保存在这个日志中。但是通过配置文件配置的资源则不保存。只有使用JMS时JMS的日志 + 才被创建。 + 这种日志文件的名字采用hornetq-jms作为前缀。每个文件都有 + jms这样的扩展。文件大小是1048576,它的位置在bindings文件夹下。 + + + 消息日志 + 这个日志用来存贮所有消息相关的数据,包括消息本身和重复ID缓存。 + 默认情况下HornetQ总是优先使用AIO型日志。如果AIO型日志不可用(比如在非Linux平台上运行,或系统内核版本不同) + 它将自动使用NIO型日志。 + 这种日志文件的名字采用hornetq-data。作为前缀。每个文件都有 +  hq作为扩展名。默认的文件大小是 10485760 (可配置)。文件保存在journal文件夹下。 + + + 对于超大消息,Hornet将它们保存在消息日志之外的地方。详见. + HornetQ还可以在内存不够用时将消息暂存到磁盘上。相关的配置和说明参见 + 如果不需要持久功能,HornetQ还可以配置成非持久的消息系统。参见 +
+ 配置绑定日志 + 绑定日志的配置参数在 hornetq-configuration.xml文件中。 + + + bindings-directory + 这是绑定日志的位置。默认值是data/bindings + + + create-bindings-dir + 如果设置为true,那么在 bindings-directory 所设定的位置不存在的情况下会自动创建它。默认值是true + + +
+
+ 配置JMS日志 + JMS日志的配置与绑定日志共用配置。 +
+
+ 配置消息日志 + 消息日志的配置在hornetq-configuration.xml文件中。 + + + journal-directory + 这是消息日志文件所在的目录。默认值是 + data/journal + 为以达到最佳性能,我们建议将日志设定到属于它自己的物理卷中以减少磁头运动。如果日志的位置与 + 其它进程共用(如数据库,绑定日志或事务的日志等)则磁头的运动显然要增加很多。性能也就没有保证了。 + 如果消息日志是贮存在SAN中,我们建议每个日志都拥有自己的LUN(逻辑单元)。 + + + create-journal-dir + 如果设为true,则当journal-directory所指定的日志目录不存在时,会自动创建它。默认值是true + + + journal-type + 有效值是NIO 或者 ASYNCIO + Choosing NIO chooses the Java NIO journal. Choosing + AIO 选择作用异步IO型日志。如果你的平台不是Linux或者你没有安装 + libaio,HornetQ会自动检测到并使用NIO + + + journal-sync-transactional + 如果设为true,HornetQ会保证在事务的边界操作时(commit, prepare和rollback)将事务数据 + 写到磁盘上。默认的值是 true + + + journal-sync-non-transactional + 如果设为true HornetQ将保证每次都将非事务性消息数据(发送和通知)保存到磁盘上。默认值是 true + + + journal-file-size + 每个日志文件的大于。单位为字节。默认值是 10485760 bytes (10MiB)。 + + + journal-min-files + 最少日志文件数。当HornetQ启动时会创建这一数量的文件。 + 创建并初始化日志文件是一项费时的操作,通常不希望这些操作在服务运行时执行。预先创建并初始化这些 + 日志文件将会使HornetQ在工作时避免浪费不必要的时间。 + 根据你的应用中队列中消息量的实际要求可以适当调节这一参数。 + + + journal-max-io + 写请求被放到一个队列中,然后再被发送到系统中执行。这个参数限制了在任一时间队列中可以存放的最大数量 + 的写请求。如果队列达到这个限制,任何新的写请求都将被阻塞,直到队列中有空位为止。 + 当使用NIO时,这个参数必须为 1 + 当使用AIO时,它的默认值是500 + 系统根据不同类型的日志提供不同的默认值。(NIO 为 1, AIO 为 500)。 + 如果是AIO,这个参数的上限不能超过操作系统的限制(/proc/sys/fs/aio-max-nr),这个值通常为65536. + + + journal-buffer-timeout + 日志模块中有一个内部缓冲。每次写的内容并不是都立即写到磁盘上,而是先放到这个内部缓存中。当这个缓存已满时,或 + 者超过了一定的时间(timeout),才将缓存的数据存到硬盘上。NIO和AIO都有这一特点。采用缓存的方式可以很好地满足 + 大量并发写数据的需要。 + 这一参数规定了缓存的失效时间,如果过了这个时间,即使缓存还没有满,也将数据写入磁盘中。AIO的写入 + 能力通常要比NIO强。因此系统对于不同类型的日志有着不同的默认值。( NIO的默认值是 3333333 纳秒,即每秒300次。 + 而AIO则是500000纳秒,即每秒2000次。) + + 加在这个参数有可能会增加系统的呑吐量,但可能会降低系统的响应能力。通常情况下默认值应该是比较理想的折中选择。 + + + + journal-buffer-size + AIO的定时缓冲的大小,默认值为490KiB + + + journal-compact-min-files + 进行整理压缩日志操作的最少文件数。当日志文件少于这个数时,系统不会进行文件的整理压缩。 + 默认值是 10 + + + journal-compact-percentage + 开始整理压缩的界限值。当有效数据的比例少于这个值时系统开始整理压缩日志。注意是否进行压缩还要 + 受到、journal-compact-min-files参数的控制。 + 这一参数的默认值是 30 + + +
+
+ 关于关闭磁盘写缓冲的重要说明 + + 大多数磁盘产品都有硬件的写缓冲。写缓冲可以明显提高写的效率。 + 这样的写缓冲与调用fsync()这样的系统函数无关,也与在Java程序中进行的同步调用无关! + 默认情况下许多磁盘的写缓冲是打开的。这样的情况下,即使你在程序中调用了同步操作也不能保证你的数据 + 就真正写到磁盘介质中了。因此如果故障发生时,关键的数据是有可能丢失的。 + 有些昂贵的磁盘采用非挥发性的介质或有电源的缓冲来保证故障情况下不丢失数据。但是你仍需要对这些硬盘进行测试! + 如果你的磁盘没有非挥发性或有电源的缓存,也不是某种冗余盘阵(如RAID)。要想保证关键数据不丢失,你需要 + 关闭磁盘的写缓冲。 + 需要知道的是关闭磁盘的写缓冲会显著降低磁盘的性能。如果平时你在使用磁盘时都打开写缓冲,那么当你为了 + 保护你的数据而关闭它时,你可能感到两种情况下的明显差异。 + Linux可以用hdparm (IDE硬盘) 或 sdparm 或 + sginfo (SDSI/SATA 硬盘)工具来查看并修改磁盘的写缓冲。 + 在Windows平台上你可以右键点击硬盘图标,并选择“属性”菜单项来操作。 + +
+
+ 安装AIO + Java NIO日志的性能是很好的。但是如果你是在Linux 内核2.6版本以上的系统中运行HornetQ,我们强烈建议 + 你使用 AIO日志,以获得更佳的性能。 + 在早期的Linux版本中或其它操作系统中不可以使用 AIO日志。 + 如果你的Linux内核是2.6版本或以上但没有安装 libaio,按照下列步骤可以很容易地安装它: + 使用 yum,(如 Fedora 或 Red Hat Enterprise Linux): + yum install libaio + 使用 aptitude, (如 Ubuntu 或 Debian): + apt-get install libaio +
+
+ 配置HornetQ不使用持久化 + 在一些情况下消息系统并不需要持久化。这时可以配置HornetQ不使用持久层。只要将hornetq-configuration.xml文件中的persistence-enabled + 参数设为false即可。 + 注意如果你将该参数设为 false来关闭持久化,就意味着所有的绑定数据、消息数据、超大消息数据、重复ID缓冲以及转移(paging)数据都将不会被持久。 +
+
+ 导入入/导出日志数据 + 有时你需要使用导入/导出工具来查看日志文件的记录。这个导入/导出工具类在hornetq-core.jar文件中。 +    使用以下命令可以将日志文件导出为文本文件: + java -cp hornetq-core.jar org.hornetq.core.journal.impl.ExportJournal + <JournalDirectory> <JournalPrefix> <FileExtension> <FileSize> + <FileOutput> + 要将日志文件导入,使用下面的命令(注意你需要netty.jar): + java -cp hornetq-core.jar:netty.jar org.hornetq.core.journal.impl.ImportJournal + <JournalDirectory> <JournalPrefix> <FileExtension> <FileSize> + <FileInput> + + + JournalDirectory:文件的位置,如./hornetq/data/journal + + + JournalPrefix: 日志文件的前缀。这里有关于前缀的详细描述。 + + + FileExtension: 文件的扩展名。详细讨论参见这里。 + + + + FileSize:日志文件的大小。详细讨论参见这里。 + + + FileOutput:输出的文本文件名。 + + +
+ +
diff --git a/docs/user-manual/zh/pre-acknowledge.xml b/docs/user-manual/zh/pre-acknowledge.xml new file mode 100644 index 0000000000..a7f42dd811 --- /dev/null +++ b/docs/user-manual/zh/pre-acknowledge.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + 预先通知模式(pre-acknowledge) + JMS 规定了三种消息通知方式 + + + AUTO_ACKNOWLEDGE + + + CLIENT_ACKNOWLEDGE + + + DUPS_OK_ACKNOWLEDGE + + + 还有一种情况JMS不支持:应用程序在出现故障时可以容忍消息丢失,这样可以在消息在传递给客户 + 端之前就通知服务器。 + HornetQ支持这种模式,称为pre-acknowledge + 这种模式的缺点是消息在通知后,如果系统出现故障时,消息可能丢失。并且在系统重启后该消息 + 不能恢复。 + 使用pre-acknowledgement模式可以节省网络传输和CPU处理资源。 + 股票价格更新是一个适用于此模式的例子。如果因为服务器故障丢失了一些消息,等服务器重启后新的 + 股票更新消息很快到达,以前丢失的过时的股票消息即使丢失也无关紧要。 + + 注意如果你使用pre-acknowledge模式,在接收消息端不能支持事务。因为这个模式不是在提交时 + 通知消息,是在消息在传递之前就通知了。 + +
+ 使用PRE_ACKNOWLEDGE + 这个模式在hornetq-jms.xml文件中 + 的connection factory下配置: + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty-connector"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + <pre-acknowledge>true</pre-acknowledge> +</connection-factory> + 另一个选择是使用JMS接口来设置pre-acknowledgement模式。只需要在创建JMS会话(session) + 时使用HornetQSession.PRE_ACKNOWLEDGE常数即可。 + +// messages will be acknowledge on the server *before* being delivered to the client +Session session = connection.createSession(false, HornetQSession.PRE_ACKNOWLEDGE); + + 你还可以直接在HornetQConnectionFactory实例上设置该模式。 + 另外,如果使用核心接口,则在ClientSessionFactory实例上直接 + 设置该模式。 +
+
+ 例子 + 参见。这是一个使用JMS的例子。 +
+
diff --git a/docs/user-manual/zh/preface.xml b/docs/user-manual/zh/preface.xml new file mode 100644 index 0000000000..fe25e7fc2b --- /dev/null +++ b/docs/user-manual/zh/preface.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + 前言 + 什么是HornetQ? + + + HornetQ 是一个开源的软件项目。它的目标是一个多协议、可嵌入、高性能、可集群的异步消息系统。 + + + HornetQ 是一个消息中间件(MoM)。有关MoM和其它消息相关的概念解释请参见 + + + 要了解有关HornetQ的更多信息请访问 + + + 为什么要使用HornetQ? 以下给出了几个理由: + + + HornetQ是100%的开源软件。 HornetQ 采用 Apache v 2.0开源协议,对用户的限制最小。 + + + HornetQ的设计强调可用性。 + + + 采用Java语言编写。可以在任何Java 6+ 的平台上运行。这几乎包括了从Windows到IBM mainframes的每个平台。 + + + 性能出众。不但对非持久化消息的处理性能达到了非常高的性能。独特高效的日志(journal)使持久消息处理接近非持久消息的性能。 + + + 功能全面。不仅拥有其它成熟消息产品所具有的全部功能,而且还有很多独特的功能。 + + + HornetQ的设计遵从了简约的原则。对第三方软件的依赖极少。根据不同的需要, + HornetQ可以单独运行,也可以运行于JEE应用服务器中。它还可以嵌入到你自己的应用程序中。 + + + 完美的可获得性。HornetQ提供自动客户端失效备援(automatic client failover)功能,能保证在服务器故障时没有消息丢失或消息重复。 + + + 超级灵活的集群方案。可以控制集群进行消息负载均衡的方式。分布在不同地理位置的各个集群间可以通过非可靠的网络连接形成一个全球网络。 + 还可以非常灵活地配置消息路由。 + + + 请访问 wiki + 来全面了解HornetQ的所有功能介绍。 + + + diff --git a/docs/user-manual/zh/project-info.xml b/docs/user-manual/zh/project-info.xml new file mode 100644 index 0000000000..820dc9334c --- /dev/null +++ b/docs/user-manual/zh/project-info.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + 项目信息 + HornetQ的官方网址是 http://hornetq.org/. +
+ 软件下载 + HornetQ的下载地址为:http://hornetq.org/downloads.html +
+
+ 其它相关信息 + + + + HornetQ的 wiki + + + 如果在使用HornetQ中发生任何问题,可以去我们的 用户论坛 + + + + 如果你有开发方面的问题与想法,请访问我们的 开发论坛 + + + 请加入我们的IRC频道与我们的核心开发工程师交流。 + + + 我们项目有自己的 博客 + + + 还可以跟踪我们的twitter + + + HornetQ的Git代码库地址 https://github.com/hornetq/hornetq + + + 每次发布的版本标签都在https://github.com/hornetq/hornetq/tags下能找到。 + + + + Red Hat 公司聘请全职工程师进行HornetQ项目的开发工作,他们是: + + + Tim Fox (项目主管) + + + Howard Gao + + + Jeff Mesnil + + + Clebert Suconic + + + Andy Taylor + + + 另外我们还有长期的和刚加入的一些贡献者,非常感謝他们的帮助。参见完整的贡献者名单 +
+
diff --git a/docs/user-manual/zh/queue-attributes.xml b/docs/user-manual/zh/queue-attributes.xml new file mode 100644 index 0000000000..33ae46b851 --- /dev/null +++ b/docs/user-manual/zh/queue-attributes.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + 队列属性 + 有两种方法可以设置队列的属性。一种使用配置文件,另一种使用核心接口(core API)。 + 本章讲述这些属性的配置以及这些属性的作用。 +
+ 预定义的队列 + 通过配置可以定义队列。队列的定义可以在核心层定义,也可以在JMS层来定义。首先我们看一下JMS层。 + 下面就是一个在hornetq-jms.xml中定义的一个队列的例子: + <queue name="selectorQueue"> + <entry name="/queue/selectorQueue"/> + <selector string="color='red'"/> + <durable>true</durable> +</queue> + 这个队列的name属性定义了队列的名字。例子中我们采用了一种命名的惯例,因些对应的核心队列的名字是 + jms.queue.selectorQueue + 在entry单元内定义的名字用来将队列绑定于JNDI。这是必不可少的。一个队列可以有多个entry定义,每个 + 定义中的名字都绑定到同一个队列。 + selector单元定义的是队列的选择器。定义了选择器后,只有与选择器相匹配的消息才能被加到队列中。 + 这是一个可选项。如果没有定义选择器,队列将默认没有选择器。 + durable定义了队列是否是一个可持久的队列。这也是一个可选项,默认值是true。 + 如果在核心层定义队列,则使用hornetq-configuration.xml文件。 + 下面是一个例子: + <queues> + <queue name="jms.queue.selectorQueue"> + <address>jms.queue.selectorQueue</address> + <filter string="color='red'"/> + <durable>true</durable> + </queue> +</queues> + 它的配置与JMS的配置很相似,但有三个不同之处: + + + 队列的name属性是队列的真正名字,不是JMS中的名字。 + + + address一项定义了消息路由的地址。 + + + 没有entry单元。 + + + filter的定义使用核心过滤器语法 (在 + 中描述),不是JMS的选择器语法。 + + +
+
+ 使用接口(API)创建队列 + 队列还可以使用核心接口或管理接口来创建。 + 核心接口的org.hornetq.api.core.client.ClientSession接口可以用来 + 创建队列。它有几个createQueue方法,可以在创建队列时对上述的属性进行设置。 + 除此之外,还有一个额外的属性temporary可以设置。如果将其设为true, + 那么队列在会话断开时将被删除。 + 中讲述了如何用管理接口来创建队列。 +
+
+ 通过地址设置来配置队列属性 + 有些属性的定义中地址可以使用通配符。下面是hornetq-configuration.xml + 文件中的一个address-setting的配置例子。 + <address-settings> + <address-setting match="jms.queue.exampleQueue"> + <dead-letter-address>jms.queue.deadLetterQueue</dead-letter-address> + <max-delivery-attempts>3</max-delivery-attempts> + <redelivery-delay>5000</redelivery-delay> + <expiry-address>jms.queue.expiryQueue</expiry-address> + <last-value-queue>true</last-value-queue> + <max-size-bytes>100000</max-size-bytes> + <page-size-bytes>20000</page-size-bytes> + <redistribution-delay>0</redistribution-delay> + <send-to-dla-on-no-route>true</send-to-dla-on-no-route> + <address-full-policy>PAGE</address-full-policy> + </address-setting> +</address-settings> + 通过上述的地址设定可以将多个属性应用于所有与match属性相匹配的地址。 + 上面例子中所定义的属性应用于jms.queue.exampleQueue的地址。如果使用 + 通配符,就可以将这些属性应用于一组匹配的地址。通配符的详细说明在这里。 + 例如在match中定义字符串jms.queue.#,那么 + 定义的属性就会应用于所有以jms.queue.开头的地址--即所有的JMS队列。 + 这些属性在本手册的各个地方有相应的介绍。在此处给出了简单的解释各它所在章的连接。 + max-delivery-attempts定义了最大重传递的次数。一个消息如果反复传递超过 + 了这个值将会被发往死信地址dead-letter-address。相关的完整的解释在 + 这里。 + redelivery-delay定义了重新传递的延迟。它控制HornetQ在重新 + 传递一个被取消的消息时要等待的时间。参见这里。 + expiry-address定义了过期消息的发送地址。参见这里。 + last-value-queue 定义一个队列是否使用最新值。参见这里。 + max-size-bytespage-size-bytes用来设置地址的分页转存功能。 + 它们在这里有详细的解释。 + redistribution-delay定义了当最后一个接收者关闭时重新分配队列消息前所等待的时间。 + 参见这里。 + send-to-dla-on-no-route。当一个消息被送到某个地址时,可能不会被路由到任何一个队列。 + 例如该地址没有绑定任何队列的情况,或者它所有的队列的选择器与该消息不匹配时。这样的消息通常情况下会被丢弃。这时 + 如果将这个参数设为true,则如果这个地址配置了死信地址的话,这样的消息就会被发送到该地址的死信地址(DLA)。 + address-full-policy。这个属性有三个可能的值:PAGE、 DROP 或 BLOCK。它决定了 + 如果地址的消息所占用的内存达到了max-size-bytes所定义的值时,如何处理后继到来的消息。 + 默认值是PAGE,就是将后续的消息分页转存到磁盘上。DROP则表示丢弃后续的消息。BLOCK表示阻塞消息的发送方发送后续 + 的消息。参见。 + + +
+
diff --git a/docs/user-manual/zh/scheduled-messages.xml b/docs/user-manual/zh/scheduled-messages.xml new file mode 100644 index 0000000000..9504ecf0d8 --- /dev/null +++ b/docs/user-manual/zh/scheduled-messages.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + 定期消息 + 与普通消息不同,定期消息是在未来某个指定时间发送的消息。 + 为了创建定期消息,需要设定一个特殊的参数. +
+ 定期传递参数 + 用来标识一个定期消息的参数是"_HQ_SCHED_DELIVERY" (相当于常量Message.HDR_SCHEDULED_DELIVERY_TIME)。 + 这个参数的值必须是一个大于零的长整型,单位是毫秒。下面例子给出了使用JMS接口创建定期消息的方法: + + TextMessage message = + session.createTextMessage("This is a scheduled message message which will be delivered + in 5 sec."); + message.setLongProperty("_HQ_SCHED_DELIVERY", System.currentTimeMillis() + 5000); + producer.send(message); + + ... + + // message will not be received immediately but 5 seconds later + TextMessage messageReceived = (TextMessage) consumer.receive(); + + 也可以使用核心接口来发送定期消息。它只需要将同样的参数设定到核心消息上即可。 +
+
+ 例子 + 参见,它是一个JMS使用定期消息的例子。 +
+
diff --git a/docs/user-manual/zh/security.xml b/docs/user-manual/zh/security.xml new file mode 100644 index 0000000000..e973586e7a --- /dev/null +++ b/docs/user-manual/zh/security.xml @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + 安全 + 本章讲述HornetQ的安全机制以及如何配置它。要完全关闭安全,只要将hornetq-configuration.xml + 文件中的security-enabled参数设为false即可。 + 出于性能的考虑,安全在HornetQ中被缓存一定的时间。要改变这个时间,需要设置参数 + security-invalidation-interval,单位是毫秒。默认值是 + 10000毫秒。 +
+ 基于角色的地址安全 + HornetQ采用了基于角色的安全模型来配置地址的安全以及其队列的安全。 + 正如在解释的那样,HornetQ核心主要由绑定到地址上的队列组成。 + 消息被发送到地址后,服务器查找与之绑定的队列,并将消息路由到这些队列中。 + HornetQ可以基于地址来给队列定义权限。在定义权限时可以使用通配符'#'和 + '*'。 + 队列的权限有7种,它们是: + + + createDurableQueue。允许用户在相应的地址上创建持久的队列。 + + + deleteDurableQueue。允许用户在相应的地址上删除相应的持久的队列。 + + + createNonDurableQueue。允许用户在相应地址上创建非持久的队列。 + + + deleteNonDurableQueue。允许用户在相应地址上删除非持久队列。 + + + send。允许用户向相应地址发送消息。 + + + consume。允许用户从相应地址上的队列接收消息。 + + + manage。允许用户调用管理操作,即向管理地址发关管理消息。 + + + 每个权限有一个角色表。如果用户的角色在这个表中,那么它将拥有这个权限。 + 让我们看个简单的例子。下面是从hornetq-configuration.xml文件或 + hornetq-queues.xml文件中提取的安全设置: + +<security-setting match="globalqueues.europe.#"> + <permission type="createDurableQueue" roles="admin"/> + <permission type="deleteDurableQueue" roles="admin"/> + <permission type="createNonDurableQueue" roles="admin, guest, europe-users"/> + <permission type="deleteNonDurableQueue" roles="admin, guest, europe-users"/> + <permission type="send" roles="admin, europe-users"/> + <permission type="consume" roles="admin, europe-users"/> +</security-setting> + + 在配置中字符'#'代表"任何单词序列“。单词由'.'字符分隔。 + 有关通配符的语法的完整说明请参见。上面的安全配置对以 + "globalqueues.europe."开始的地址有效: + 只有具有admin角色的用户才可以创建和删除绑定到以"globalqueues.europe."开始的地址的持久化队列。 + 具有adminguesteurope-users + 角色的用户可以在以开头的地址上创建临时的队列。 + 任何具有admineurope-users角色的用户可以向以"globalqueues.europe."开头的地址 + 发送消息,并从绑定到相同地址上的队列接收消息。 + 安全管理器处理一个用户和它的角色的对应关系。HornetQ本身自带一个用户管理器,能从文件中读取用户的身份信息。 + 另外HornetQ还可以使用JAAS或JBoss应用服务器的安全管理机制。 + 有关安全管理器的配置信息,请参见 + 在每个xml文件中可以有零个或多个 security-setting。当一组地址有多个这样的设置时, + HornetQ总是选取更具体的匹配。 + 让我们来看一个实例,下面是另一个security-setting + +<security-setting match="globalqueues.europe.orders.#"> + <permission type="send" roles="europe-users"/> + <permission type="consume" roles="europe-users"/> +</security-setting> + + 在这个security-setting块中,字符串 + 'globalqueues.europe.orders.#' 要比它之前的字符串'globalqueues.europe.#'更具体。 + 因此当一个地址与'globalqueues.europe.orders.#'匹配时,它选择这个安全配置。 + 注意安全设置没有继承性。对于像'globalqueues.europe.orders.plastics'的地址,只要上面的设置 + 能被采用。即角色europe-users有sendconsume权限。权限 + createDurableQueuedeleteDurableQueuecreateNonDurableQueuedeleteNonDurableQueue不会从先前的设置中继承。 + 由于权限的不可继承,如果我们不在更具体的security-setting设置中给出一个权限,这个权限就是没有的,不会因为继承而带来 + 麻烦。否则就不可能对一组地址中的部分地址进行如此的设置。 +
+
+ 安全套接字层(SSL)传输 + 当消息客户端与服务器端,或服务器之间(比如使用桥的情况)通过一个不信任的网络相互通信时,HornetQ + 支持使用加密的安全套接字(SSL)传输数据。 + 关于SSL的详细配置信息,请参见 +
+
+ 基本用户身份信息(Credentials) + HornetQ自带一个安全管理器(security manager)可以从xml文件中读取用户身份信息,即用户名、 + 密码、角色信息。该xml文件名为hornetq-users.xml,它必须要在classpath中。 + 如果你要使用这个安全管理器,就将用户名,密码,角色等信息加入到这个文件中。 + 让我们看一个例子: + +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq ../schemas/hornetq-users.xsd "> + + <defaultuser name="guest" password="guest"> + <role name="guest"/> + </defaultuser> + + <user name="tim" password="marmite"> + <role name="admin"/> + </user> + + <user name="andy" password="doner_kebab"> + <role name="admin"/> + <role name="guest"/> + </user> + + <user name="jeff" password="camembert"> + <role name="europe-users"/> + <role name="guest"/> + </user> + +</configuration> + + 首先要注意的是defaultuser,它定义的是默认的用户。当客户端创建会话时 + 没有提供用户名/密码时,就会使用这个用户。根据上述配置,这个默认用户是guest + 并且他的角色是guest。一个默认用户可以有多个角色。 + 另外三个用户中,用户tim具有角色admin。用户andy具有角色adminguest,用户jeff + 具有角色europe-usersguest +
+
+ 更换安全管理器 + 如果你不想用默认的安全管理器,可以通过修改配置文件hornetq-beans.xml + (或者在运行JBoss应用服务器情况下hornetq-jboss-beans.xml文件)来更换。同时要更换 + HornetQSecurityManager bean 的类。 + 让我们看一段默认bean文件的内容: + +<bean name="HornetQSecurityManager" + class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl"> + <start ignored="true"/> + <stop ignored="true"/> +</bean> + + org.hornetq.spi.core.security.HornetQSecurityManagerImpl + 类就是HornetQ服务器的在独立运行时的默认的安全管理器。 + HornetQ自带有另外两个安全管理器可供使用。一个是JAAS安全管理器,另一个是用来与JBoss应用服务 + 器集成的安全管理器。此外,你还可以编写实现你自己的安全管理器。首先要实现 + org.hornetq.core.security.SecurityManager接口,再将你的实现 + 类定义到hornetq-beans.xml文件中即可(或者在JBoss应用服务器中 + 使用hornetq-jboss-beans.xml文件)。 + 以下分别介绍这两咱安全管理器 +
+
+ JAAS安全管理器 + JAAS表示“Java认证与授权服务“。它是Java平台标准的一部分。它提供了进行安全认证与授权的通用接口。 + 它允许你插入自己的安全管理模块。 + 要配置使用你自己的JAAS安全实现,需要在bean文件中定义JAASSecurityManager。 + 下面是一个例子: + + 注意你需要为JAAS安全管理器提供三个参数: + + + ConfigurationName: LoginModule的名字。 + + + Configuration: Configuration的实现。 + + + CallbackHandler: CallbackHandler实现,用于用户交互。 + + +
+ 例子 + 参见。这个例子展示了怎样在HornetQ中配置使用JAAS。 +
+
+
+ JBoss 应用服务器安全管理器 + JBoss 应用服务器安全管理器适用于当HornetQ运行于JBoss应用服务器内时。它可以与JBoss应用服务器 + 的安全模型紧密集成。 + 此安全管理器的类是 org.hornetq.integration.jboss.security.JBossASSecurityManager + 要了解如何配置JBoss安全管理器,可以看一眼HornetQ发布包中相关例子中的 + hornetq-jboss-beans.xml文件。 +
+ 配置客户端登录 + JBoss可以配置使用客户登录。JEE的模块如servlet或EJB可以将安全认证信息设置到安全上下文(security context)中, + 用于整个调用过程。如果想在HornetQ在发送和接收消息时使用这些认证(credential)信息,需要将参数 + allowClientLogin设为true。它会越过HornetQ的身份验证过程并会传播安全上下文(security + context)。如果你想要HornetQ使用传播的安全信息进行身份验证,需要同时将参数authoriseOnClientLogin + 设为true。 + 关于客户端登录的详细信息请访问这里 + 如果消息是以非阻塞方式发送的,那么有可能在消息到达服务器时,调用线程已经结束,安全上下文也被清除了。 + 所以如果使用安全上下文,需要采用阻塞方式发送消息。 +
+
+
+ 集群用户名/密码的配置 + 为了使集群连接正常工作,每个节点都必须与其它节点相连接。它们连接所使用的默认用户名和密码在正式使用时 + 一定要做相应的更改,以防止安全隐患。 + 请参见了解怎样去做。 +
+
diff --git a/docs/user-manual/zh/send-guarantees.xml b/docs/user-manual/zh/send-guarantees.xml new file mode 100644 index 0000000000..ab3a041d2b --- /dev/null +++ b/docs/user-manual/zh/send-guarantees.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + 发送与提交的保证 +
+ 事务保证 + 在提交或回滚事务时,HornetQ将提交或回滚的请求发送到服务器,客户端阻塞等待服务器的响应。 + 当服务器端收到提交或回滚的请求时,它将事务信息记录到日志(journal)中。然后向客户端发回 + 响应。参数journal-sync-transactional控制着如何向客户端发回响应。 + 如果它的值是false,服务器向客户端发回响应时事务的处理結果不一定已经被 + 保存到磁盘中。可能会在之后的某个时间保存。如果期间服务器发生故障那么事务的处理信息可能丢失。 + 当它的值是true时,服务器将保证在向客户端发回响应时,事务的处理信息 + 已经被保存到了磁盘中。默认值是true + 显然将这个参数设为false可以提高性能,但是要以牺牲事务的持久性为代价。 + 这个参数在 hornetq-configuration.xml文件中。 +
+
+ 非事务性消息发送的保证 + 使用非事务性会话发送消息时,经过适当配置HornetQ,客户端在发送后以阻塞的方式等待,直到确认发出 + 的消息已经到达服务器后再返回。可以对持久化或非持久化的消息分别配置,具体参数如下: + + + BlockOnDurableSend。如果设为true则通过 + 非事务性会话发送持久消息时,每次发送都将阻塞直到消息到达服务器并返回通知为止。默认值是 + true。 + + + + BlockOnNonDurableSend。如果设为true, + 则通过非事务性会话发送非持久消息时,每次发送都将阻塞直到消息到达服务器并返回通知为止。默认值是 + false + + + 将发送设置为阻塞方式会降低程序的效率。因为每次发送都需要一次网络往返的过程,然后才可以进行下次发送。 + 这样发送消息的速度将受网络往返时间(RTT)的限制。这样你的网络带宽就可能没有被充分利用。为了提高效率,我们 + 建议采用事务来批量发送消息。因为在事务中,只有在提交或回滚时阻塞。另外你还可以利用HornetQ高级的 + 异步发送通知功能。这一功能在 + 进行了描述。 + 使用JMS时,如果JMS的连接工厂是在服务器端被注册到JNDI服务,你需要配置 + hornetq-jms.xml文件中的block-on-durable-send + 和block-on-non-durable-send。如果不使用JNDI,可以调用 + HornetQConnectionFactory相应的设置方法进行配置。 + 如果你使用的是内核服务,你可以直接在ClientSessionFactory上用相关的方法设置相应的参数。 + 当服务器从一个非事务性的会话收到一个消息时,如果这个消息是持久的并且此消息被路由到至少一个持久的队列中, + 则该消息会被持久化到永久存贮介质中。如果日志(journal)的参数journal-sync-non-transactional设为true,服务器在向客户 + 发送响应时,它能保证消息已经被持久化到磁盘中。默认值是true +
+
+ 非事务性通知的保证 + 当客户端使用非事务性会话向服务器通知消息收到时,可以配置HornetQ使得客户端的通知阻塞直到服务器收到 + 了通知并返回为止。其相应的配置参数是BlockOnAcknowledge。如果该参数设为 + true则所有的通过非事务会话的消息通知都是阻塞式的。如果你想要的消息传递策略是 + 最多一次的话,那么你需要将此参数设为。默认值是false +
+
+ 异步发送通知 + 如果你使用的是非事务会话来发送消息,并且希望保证每个发送出去的消息都到达服务器的话,你可以将HornetQ配置 + 成阻塞的方式,如讨论的那样。这样做的一个缺点是性能的降低。 + 因为这样每发送一个消息就需要一次网络的往返通信。如果网络时延越长,消息发送的效率就越低。同时网络的带宽对消息 + 的发送没有影响。 + 我们来做一个简单的计算。假设有一个1Gib的网络,客户端与服务器间往返时间为0.25ms。 + 这样,在阻塞方式的情况下,客户端最大的消息发送速度为 1000/ 0.25 = + 4000 消息每秒。 + 如果每个消息的大小< 1500字节,而且网络的最大传输单元(MTU)是1500字节。那么理论上1GiB的网络 + 最大的传输速率是 (1024 * 1024 * 1024 / 8) / 1500 = 89478 消息每秒!尽管这不是一个精确的工程计算但 + 你可以看出阻塞式的发送对性能的影响会有多大。 + 为了解决这个问题,HornetQ提供了一种新的功能,称为异步发送通知。 + 它允许消息以非阻塞的方式发送,同时从另一个连接流中异步地接收服务器的通知。这样就使得消息的发送与通知分开来, + 避免了阻塞方式带来的缺点。在保证消息可行发送到服务器的同时提高了呑吐量。 + 参数用来定义消息发送通知的窗口大小。它属于连接工厂或客户会话工厂。参见 + 以获取更多的相关信息。 +
+ 异步发送通知 + 如果使用核心API,你需要实现org.hornetq.api.core.client.SendAcknowledgementHandler接口并将一个实例设置到 + ClientSession中。 + 然后使用这个ClientSession发送消息。当消息到达服务器后,服务器向客户端异步地发送通知, + 并在客户端调用你的SendAcknowledgementHandler实例的sendAcknowledged(ClientMessage message)方法。其中传入的参数就是发送的消息的引用。 + 为了使异步发送通知正常工作你必须确保confirmation-window-size的值为一个正整数,例如 10MiB + 相关的例子请参见 +
+
+
diff --git a/docs/user-manual/zh/thread-pooling.xml b/docs/user-manual/zh/thread-pooling.xml new file mode 100644 index 0000000000..8c21b18331 --- /dev/null +++ b/docs/user-manual/zh/thread-pooling.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + 线程管理 + 本章讲述HornetQ如何使用线程池以及如何管理线程。 + 首先我们讨论在服务器端线程是如何被管理的,然后我们再讨论客户端的情况。 +
+ 服务器端线程的管理 + 每个HornetQ服务器都有一个线程池作为一般线程使用,另外还有一个可计划线程池。Java的可计划线程池不能作为 + 标准的线程池使用,因此我们采用了两个单独的线程池。 + 当使用旧的(阻塞)IO时,使用了一个单独的线程池来处理连接。但是旧的IO要求一个线程配一个连接,所以如果你 + 的应用有很多并发的连接,这个线程池会很快用光所有的线程,造成服务器出现“挂起”现象。因此,对于大量并发连接 + 的应用,一定要使用NIO。 + 如果使用NIO,默认情况下HornetQ会使用系统中处理器内核(或超线程)数量三倍的线程来处理接收的数据包。 + 内核的数量是通过调用Runtime.getRuntime().availableProcessors()来得到 + 的。如果你想改变这个数量,可以设置传输层配置参数nio-remoting-threads。 + 参见 + 另外在其它一些地方直接使用了线程,没有用线程池。我们将对这些线程作出解释。 +
+ 服务器端可计划线程池 + 服务器可计划线程池可以定期地或延迟地执行所交给的任务,它用来完成HornetQ中绝大部分这样的任务。 + 它内部使用的是一个 java.util.concurrent.ScheduledThreadPoolExecutor实例。 + 最大线程数可以在hornetq-configuration.xml文件中进行配置,参数名是scheduled-thread-pool-max-size。默认值是5。 + 通常这个线程池不需要很大数量的线程。 +
+
+ 服务器通用线程池 + 服务器端绝大部分的异步操作都是由这个线程池来完成的。在它的内部使用了一个java.util.concurrent.ThreadPoolExecutor的实例。 + 这个线程池的最大线程数在hornetq-configuration.xml文件中配置,相应的参数名为thread-pool-max-size + 如果将参数设为-1则表示该线程池没有线程限制。也就是说当线程不够用时,线程池就 + 会创建新的线程。当任务不多时,空闲的线程将会超时并被关闭。 + 如果这个参数的值是一个大于零的整数n,则该线程池的线程数是有限的。当所有线程都 + 处于忙的状态并且线程数已经达到n时,任何新的请求都将被阻塞直到有线程空闲为止。在设置线程上限时,我们建议 + 要非常谨慎。因为如何线程数量过低会造成死锁情况的发生。 + thread-pool-max-size的默认值是30 + 参见J2SE javadoc有关无边界(缓存)和有边界(固定)线程池的解释。 +
+
+ 过期回收线程 + HornetQ使用一个单独的线程来扫描队列中过期的消息。由于这个线程需要自己的优先级配置,所以不能使用上述的 + 任何一个线程池。 + 关于回收线程的配置请参阅 +
+
+ 异步IO + HornetQ使用一个线程池来进行异步IO的操作,包括事件的接收和发送。这些线程的名字都是以 + HornetQ-AIO-poller-pool为开头。每个打开的日志文件都对应有一个线程为其服务(通常只有 + 一个)。 + 还有一个单独的线程用于向libaio发送写请求。这样做是为了避免上下文转换带来的性能下降。该 + 线程的名字以HornetQ-AIO-writer-pool开头。 +
+
+
+ 客户端线程管理 + 在客户端HornetQ有一个静态的可计划线程池和一个静态的通用线程池,它们在一个JVM中由同一个classloader装载的所有客户端 + 共同使用。 + 静态的可计划的线程池的最大线程数为 5,通用线程池则没有线程数限制。 + 如果需要还可以配置一个ClientSessionFactory实例以使它拥有自己的可计划与通用线程池。通过这个工厂创建的会话都 + 将使用这些线程池。 + 要想配置ClientSessionFactory使用自己的线程池,只要调用它相应的方法取出可,如: + ClientSessionFactory myFactory = HornetQClient.createClientSessionFactory(...); +myFactory.setUseGlobalPools(false); +myFactory.setScheduledThreadPoolMaxSize(10); +myFactory.setThreadPoolMaxSize(-1); + 如果使用JMS,你可以先用同样的参数设置ClientSessionFactory,然后再用这样工厂创建ConnectionFactory的实例。如: + ConnectionFactory myConnectionFactory = HornetQJMSClient.createConnectionFactory(myFactory); + 如果你使用JNDI来创建HornetQConnectionFactory + 实例,你还可以在hornetq-jms.xml文件中进行配置。如: + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + <entry name="XAConnectionFactory"/> + </entries> + <use-global-pools>false</use-global-pools> + <scheduled-thread-pool-max-size>10</scheduled-thread-pool-max-size> + <thread-pool-max-size>-1</thread-pool-max-size> +</connection-factory> +
+
diff --git a/docs/user-manual/zh/transaction-config.xml b/docs/user-manual/zh/transaction-config.xml new file mode 100644 index 0000000000..232d35cfd4 --- /dev/null +++ b/docs/user-manual/zh/transaction-config.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + 配置资源管理器(Resource Manager) + HornetQ有自己的资源管理器来管理JTA事务。当一个事务开始时,资源管理器就得到通知并记录下该事务和它的状态。 + 有的时候一个事务开始后,最終被忘记。有时客户端崩溃并且再也不能恢复,这样的话该事务就一直存在下去。 + 为了解决这个问题,可以配置HornetQ来扫描过期的事务,并且将它们回滚。默认值是3000000毫秒(5分钟)。 + 它表示任何超过5分钟的事务都将被删除。这个超时对应的参数是transaction-timeout,它在配置文件hornetq-configuration.xml中(单位毫秒)。 + 参数transaction-timeout-scan-period定义了HornetQ扫描过期事务的间隔。 + 注意HornetQ不会单方面回滚一个已经处于准备状态的XA事务。如果你认为这些事务永远不会被事务管理器(transaction manager) + 来处理的话,你必须通过管理接口来进行回滚。 + diff --git a/docs/user-manual/zh/undelivered-messages.xml b/docs/user-manual/zh/undelivered-messages.xml new file mode 100644 index 0000000000..a5fb827680 --- /dev/null +++ b/docs/user-manual/zh/undelivered-messages.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + 消息再传递及未传递的消息 + 消息有可能传递失败(比如相关的事务发生回滚)。失败的消息将退回到队列中准备重新传递。这样就会出现 + 一种情况,就是同一个消息会被反复的传递而总不成功,以至于使系统处于忙的状态。 + 对于这样的消息我们有两种处理方法: + + + 延迟再传递 + 这种方法是让消息再次传递时有一定的时间延迟,这样客户端就有机会从故障中恢复,同时网络连接和CPU资源 + 也不致于被过度占用。 + + + 死信(Dead Letter)地址 + 这种方法是规定一个死信地址,如果消息再被反复传递达到一定次数时,就会从原有队列中删除,转到这个 + 死信地址中。这样消息就不会永远地重复传递了。 + + + 以上两种方法可以合理搭配使用,使解决方案更加灵活。 +
+ 延迟再传递 + 延迟再传递对于时常出现故障或回滚的客户端十分有用。如果没有延迟,整个系统可能会处于一种”疯狂“的状态。 + 就是消息被传递、回滚、再传递,这样反复不间断地进行着,将宝贵的CPU和网络资源占用。 +
+ 延迟再传递的配置 + 延迟再传递的配置在地址设定内(address-setting): + + <!-- delay redelivery of messages for 5s --> + <address-setting match="jms.queue.exampleQueue"> + <redelivery-delay>5000</redelivery-delay> + </address-setting> + + 如果定义了redelivery-delay,HornetQ在再传递之前等待所定义的时间。 + 默认是没有延时的(即redelivery-delay的值是0)。 + 可以使用通配符为一组地址定义再传递的延迟(参见)。 + +
+
+ 例子 + 参见 。这是一个JMS应用中配置延迟再传递的例子。 +
+
+
+ 死信地址 + 通过定义一个死信地址也可以防止同一个消息被无休止地传递: + 当一个消息被重复传递一定次数后,就会从队列中删除并传递到定义好的死信地址中。 + 这些死信中的消息之后可以转发到某个队列中,以供系统管理员分析处理。 + 每个HornetQ的地址可以有一个死信地址。当一个消息被反复传递达一定次数时,它就会被从队列中删除并送到 + 死信地址。这些死信消息可以被接收进行分析处理。 +
+ 配置死信地址 + 死信地址定义在地址设定中(address-setting): + + <!-- undelivered messages in exampleQueue will be sent to the dead letter address + deadLetterQueue after 3 unsuccessful delivery attempts + --> + <address-setting match="jms.queue.exampleQueue"> + <dead-letter-address>jms.queue.deadLetterQueue</dead-letter-address> + <max-delivery-attempts>3</max-delivery-attempts> + </address-setting> + + 如果没有定义dead-letter-address,消息在经过 + max-delivery-attempts次重复传递后被删除。 + 默认的重复传递次数为10。将max-delivery-attempts设定为-1 + 表示无限次重复传递。 + 例如,对一组地址设置了一个通用的死信地址后,再将其中某个地址的max-delivery-attempts + 设定为-1时,那么只有这个地址的再传递次数是无限的。 + 可以使用通配符对一组地址设定死信地址(参见)。 +
+
+ 死信的属性 + 从死信地址接收到的消息有以下属性: + + + _HQ_ORIG_ADDRESS + 这是一个字符串属性,它是该死信消息的原始地址 + + +
+
+ 例子 + 参见。这个例子给出了在JMS应用中死信的配置与使用。 +
+
+
+ 传递计数的持久化 + 通常情况下HornetQ在一个消息被回滚之前并不更新持久的传递计数(即在消息传递到接收者之前不会更新传递计数)。 + 大多数情况下消息被接收、通知、然后被忘掉。这样对每一个消息的传递都要更新一次持久的 + 传递计数,会显著降低系统的性能。 + 介是如果在消息传递之前不进行持久传递计数的更新,服务器一旦发生故障而崩溃,就会造成消息可能被传递出去而传递 + 计数却没有正确反映出传递的結果。在恢复阶段,服务器将错误地将该消息的redelivered设为 + false而不是true + 这样是不符合严格的JMS要求的。因此HornetQ允许在消息传递前更新传递计数。但是默认不这样做,目的是优先考虑 + 了它对性能的影响。 + 要想打开传递计数更新功能,将hornetq-configuration.xml文件中的 + persist-delivery-count-before-delivery设为true即可: + +<persist-delivery-count-before-delivery>true</persist-delivery-count-before-delivery> + +
+
diff --git a/docs/user-manual/zh/using-core.xml b/docs/user-manual/zh/using-core.xml new file mode 100644 index 0000000000..53172e664f --- /dev/null +++ b/docs/user-manual/zh/using-core.xml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + 使用HornetQ内核 + HornetQ内核是一个与JMS无关的消息系统,它有一套自己的API。我们称它为内核API. + 你可以直接使用内核API。使用内核API可以完成JMS同样的功能,只是比起JMS API使用更加简单方便。另外,内核API + 还提供了JMS不具有的额外的功能。 +
+ 内核消息系统的相关概念 + 内核消息系统中有许多概念是与JMS相似的,但有些方面是不同的。总的来说内核消息系统的接口相对简单。这是因为 + 在内核中没有队列(queue)、话题(topic)和订阅(subscription)的概念。下面我们就内核消息中的概念作逐一介绍。 + 但是每个API的详细说明还是要参见相应的javadoc。 +
+ 消息 + + + 一个消息就是客户端与服务器传递信息的单位数据。 + + + 一个消息有一个消息体(body),即一个缓存用以写入数据或从中读取数据。 + + + 一个消息有一个属性集,这个属性集实际上包含的是主键-值的集合。每个属性的主键是一个字符串,值可 + 以是一个整数(integer)、长整数(long)、短整数(short)、字节(byte)、字节数组(byte[])、 + 字符串(String),双精度值(double)、浮点数(float)或是布尔值(boolean)。 + + + 每个消息都有一个地址(address)做为它的目的地。当一个消息被发到 + 服务器上时,它会被路由到与该地址绑定的所有队列中(queue)。如果queue配置了过滤器(filter), + 那么只有与过滤器相匹配的消息才会被路由到该queue。一个地址可以绑定多个queue,也可以一个也不 + 绑定。注意这里所说的queue是内核的概念,不是JMS的queue。除了queue之外,还有其它一些实体可以 + 绑定到某一地址上。比如divert(转发器) + + + 消息可以是持久的(durable)或非持久的(non-durable)。持久的消息不会因为服务器故障或重启而丢失。 + 非持久消息则会因为服务器的故障或重启而丢失。 + + + 消息具有优先级。优先级的值为从0到9的整数。0代表最低优先级,9代表最高优先级。HornetQ总 + 会尝试先传送优先级高的消息。 + + + 消息还有一个可选的失效时间。如果一个消息过了失效时间,HornetQ将不再传送它。 + + + 消息还有一个可选的时间戳(timestamp)。这个时间戳表示的是消息被发送的时间。 + + + HornetQ还支持大消息的发送。它可以处理大到内存装不下的超大消息。 + + +
+
+ 地址(Address) + HornetQ服务器保存有地址和queue的映射集。一个地址对应零个或多个queue。每个queue还可以拥有消息 + 过滤器(filter)。当一个消息在服务器内进行路由时,它将会被送往与其地址相绑定的所有的queue中。但是 + 如果其中某个queue有过滤器,那么只有与其过滤器相匹配的消息才会被发到这个queue中。 + 其它的实体如diverts也可以与一地址进行绑定,消息也会被同样 + 路由到相应的实体中。 + + 在内核中,没有Topic的概念。只有地址(address) 和 + queue + 假如想在内核实现JMS topic的功能,只要将一地址绑定到多个queue即可。其中的每一个queue就相当 + 于一个订阅(subscription)。类似地,一个JMS queue则可以通过一个地址与一个queue的绑定来实现。 + +
+
+ Queue + Queue可以的持久的。意思是如果queue中的消息是持久的,那么当发生服务器故障或重启时,这些消息不会丢失。 + Queue也可是非持久的,这意谓着如果服务器发的故障或重启,queue中的消息将会丢失,不管消息是不是持久的。 + Queue也可以是临时的,意思是临时的queue在客户端断开连接时,它将会被删除。 + Queue可以有一个过滤器表达式。服务器在向这样的queue路由消息时,先判定消息是否与过滤器表达式相匹配, + 只有匹配的消息才会被发到该queue。 + 一个地址可以绑定多个queue、。但是一个queue只能被绑定到一个地址上。 +
+
+ ClientSessionFactory + 客户端使用 ClientSessionFactory 类的实例创建 ClientSession 实例。 ClientSessionFactory + 知道如何连接到服务器并创建会话(session)。它是可以根据不同需要灵活配置的。 + ClientSessionFactory实例是通过 HornetQClient 工厂类创建的。 +
+
+ ClientSession + 客户端使用ClientSession来发送和接收消息,并控制事务的使用。ClientSession可以支持事务性 + 和非事务性的应用。它还提供了一个 XAResource 接口,因些它可以加入到一个JTA + 交易中。 + ClientSession 管理着ClientConsumers和ClientProducers。 + ClientSession 实例可以注册一个可选的 SendAcknowledgementHandler。每当消息被送达HornetQ服务器中时, + HornetQ就用它来异步地发出通知。有了这个独特的功能,客户可以不必阻塞在每次消息的发送操作上来保证 + 消息安全到达服务器。如果采用阻塞的方法,那么每一个消息的发送都要包括往返两次的网络传递操作,开销 + 是很大的。有了这个异步方式就可以避免这种开销,建立真正的异步的端到端间的系统。这是标准的JMS接口 + 无法做到的。参见 了解相关的更详细的信息。 +
+
+ ClientConsumer + 客户端使用 ClientConsumer 实例来接收来自queue的消息。HornetQ的内核同时支持 + 同步与异步的消息接收。ClientConsumer 实例可以配置有可选的过滤器。它只接收与过滤 + 器相匹配的消息。 +
+
+ ClientProducer + 客户端使用ClientSession创建 ClientProducer 实例 + 来向服务器发送消息。ClientProducer可以指定一个地址,用来向其发送消息。或者不指定地址,消息在发送时 + 再指定地址。 +
+ + 请注意 ClientSession、 ClientProducer和ClientConsumer 实例是可以被 + 重用的。 + 在每次发送或接收一个消息时都创建新的 ClientSession, ClientProducer 和 ClientConsumer是不符合 + 设计模式的要求的。这样做会导致性能低下。在中我们会做进一步的讨论。 + +
+
+ 一个内核的应用实例 + 下面是一个非常简单的使用内核API来发送的接收消息的实例: + +ClientSessionFactory factory = HornetQClient.createClientSessionFactory( + new TransportConfiguration( + InVMConnectorFactory.class.getName())); + +ClientSession session = factory.createSession(); + +session.createQueue("example", "example", true); + +ClientProducer producer = session.createProducer("example"); + +ClientMessage message = session.createMessage(true); + +message.getBodyBuffer().writeString("Hello"); + +producer.send(message); + +session.start(); + +ClientConsumer consumer = session.createConsumer("example"); + +ClientMessage msgReceived = consumer.receive(); + +System.out.println("message = " + msgReceived.getBodyBuffer().readString()); + +session.close(); +
+
diff --git a/docs/user-manual/zh/using-jms.xml b/docs/user-manual/zh/using-jms.xml new file mode 100644 index 0000000000..254a787a21 --- /dev/null +++ b/docs/user-manual/zh/using-jms.xml @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + 使用JMS + 很多用户喜欢使JMS,因此HornetQ提供了JMS服务。 + JMS是一个普遍使用API标准,绝大多数的消息系统都提供JMS接口。如果你对JMS还不熟悉,建议你先参考一下 + Sun的 + JMS 教程 + HornetQ还提供了许多的JMS的示例程序(examples)。比如简单的JMS Queue和Topic的示例,就很适合初学者做为了 + 解HornetQ JMS的起点。对这些示例作了详细的说明。 + 下面我们将带领读者一步步地配置HornetQ的JMS服务,并创建一个简单的JMS程序。我们还将展示如何在没有JNDI的情况下 + 来使用HornetQ中的JMS。 +
+ 一个简单的订购系统 + 本章我们将用一个简单的订购系统做为一个例子。尽管它十分简单,但是它能够很好地向大家展示JMS的设置和使用。 + 本例中有一个名为 OrderQueueJMS队列,还将有一个 MessageProducer + 用来向队列发送订购消息。发送到队列的消息由一个 MessageConsumer 来接收。 + 我们所用的队列是持久(durable)的队列,也就是说这个队列不受服务器故障的影响。当服务器 + 发生故障重新启动后,这个队列仍然存在。我们需要把这个队列事先部署好。办法就是将队列写到JMS的配置文件中。当服务启动 + 时将配置文件中的队列自动部署好。 +
+
+ JMS服务的配置 + hornetq-jms.xml文件包含了需要创建与部署的JMS Queue,Topic和ConnectionFactory + 的实例。该文件必须要指定在classpath中。从这个文件中部署好的对象都可以用JNDI来找到。 + JMS客户端可以利用JMS ConnectionFactory对象来创建与服务器的连接。ConnectionFactory中有关于服务器地址的 + 信息以及各种参数。通常使用这些参数的默认值即可。 + 这里我们将要在服务器端部署一个JMS队列和一个JMS ConnectionFactory (连接工厂)。当然完全可以部署多个JMS对象。 + 下面给出了具体的配置内容: + +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq ../schemas/hornetq-jms.xsd "> + + <connection-factory name="ConnectionFactory"> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + </connection-factory> + + <queue name="OrderQueue"> + <entry name="queues/OrderQueue"/> + </queue> + +</configuration> + + 在本文件中我们部署了一个名为 ConnectionFactory 的一个连接工厂,并且将其绑定到 + JNDI中。如果需要可以将一个连接工厂绑定为多个名称。只需要将绑定的名字加入到 entry + 中即可。 + + 在JMS ConnectionFactory的配置中引用了一个名为 nettyconnector。 + 它实际上指向的是HornetQ核心中部署的一个连接器(connector)。它的配置在HornetQ的核心配置文件 + hornetq-configuration.xml 中。它定义了采用何种传输与服务器连接。 + +
+
+ 连接工厂的类型 + 在JMS API文档中有几种不同类型的连接工厂供用户使用。HornetQ为用户提供了配置连接工厂类型的参数。用户可以通过 + 配置连接工厂的”signature"属性和"xa"参数来得到想要的类型。“singature"属性是字符串类型,它有三个可选值: + genericqueuetopic; + xa是一个布尔型参数。下表给出了不同类型连接工厂对应的配置值: + + 连接工厂类型的配置 + + + + + + + signature + xa + 连接工厂的类型 + + + + + generic (默认) + false (默认) + javax.jms.ConnectionFactory + + + generic + true + javax.jms.XAConnectionFactory + + + queue + false + javax.jms.QueueConnectionFactory + + + queue + true + javax.jms.XAQueueConnectionFactory + + + topic + false + javax.jms.TopicConnectionFactory + + + topic + true + javax.jms.XATopicConnectionFactory + + + +
+ 下面的例子配置了一个XAQueueConnectionFactory: + +<configuration xmlns="urn:hornetq" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="urn:hornetq ../schemas/hornetq-jms.xsd "> + + <connection-factory name="ConnectionFactory" signature="queue"> + <xa>true</xa> + <connectors> + <connector-ref connector-name="netty"/> + </connectors> + <entries> + <entry name="ConnectionFactory"/> + </entries> + </connection-factory> +</configuration> + +
+
+ JNDI的配置 + 当客户端使用JNDI时需要定义一些JNDI的参数。这些参数主要用来确定JNDI服务的地址。这些参数通常保存在 + 一个名为 jndi.properties 的文件中。这个文件需要在客户端的classpath中。或者你 + 可以在创建JNDI的InitialContext时将这些参数传进去。想了解全面的JNDI知识,可以参见 Sun JNDI 教程 + 。 + 要与JBoss的JNDI Server进行通迅,需要指定以下的JNDI参数: + +java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory +java.naming.provider.url=jnp://myhost:1099 +java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces + + 其中的 myhost 是 JNDI server的主机名或IP地址。 1099是端口号,根据不同的配置, + 端口号也可能不同。 + 在默认的单独方式(standalone)配置中,JNDI服务端口等参数定义在hornetq-beans.xml + 文件中的 JNDIServer bean下,如: + +<bean name="JNDIServer" class="org.jnp.server.Main"> + <property name="namingInfo"> + <inject bean="Naming"/> + </property> + <property name="port">1099</property> + <property name="bindAddress">localhost</property> + <property name="rmiPort">1098</property> + <property name="rmiBindAddress">localhost</property> +</bean> + + + 如果你的JNDI服务器与客户端不在同一台机器上,一定不要忘记将bindAddress改成相应的地址, + 千万不能用localhost + + + 只有当HornetQ作为独立服务器运行时 + 才可以配置JNDIServer bean。当HornetQ运行于JBoss应用服务器中时,由于JBOSS服务器已经提供了 + JNDI服务,所以就不需要再进行配置了。 + +
+
+ 程序代码 + 下面给出的例子中的代码: + 首先我们创建一个JNDI的Initial Context: + InitialContext ic = new InitialContext(); + 下面我们查找 connection factory: + ConnectionFactory cf = (ConnectionFactory)ic.lookup("/ConnectionFactory"); + 然后查找 Queue: + Queue orderQueue = (Queue)ic.lookup("/queues/OrderQueue"); + 接下来用拿到的ConnectionFactory建立JMS连接: + Connection connection = cf.createConnection(); + 再创建一个非事务的、AUTO_ACKNOWLEDGE方式的JMS Session: + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + 创建一个 MessageProducer 以向队列发送订单消息: + MessageProducer producer = session.createProducer(orderQueue); + 创建一个 MessageConsumer 以从队列中接收订单消息: + MessageConsumer consumer = session.createConsumer(orderQueue); + 要启动连接,以使消息能传递给接收者: + connection.start(); + 发送一个简单的TextMessage: + TextMessage message = session.createTextMessage("This is an order"); +producer.send(message); + 之后接收这个消息: + TextMessage receivedMessage = (TextMessage)consumer.receive(); +System.out.println("Got order: " + receivedMessage.getText()); + + 看起来就是这么简单。 在HornetQ有发布包中有很多各种各样的JMS例子供用户参考。 + + 请注意,JMS的连接(connection)、会话(session)、生产者(producer)和消费者(consumer) + 对象是可以重用的。 + 如果每发送或接收一个消息都要重新创建这些JMS对象,是不符合设计模式的要求的。这样做会造成应用程序 + 的性能很差。这方面的内容在中将会进一步的讨论。 + +
+
+ 不使用JNDI而直接创建JMS的对象 + 尽管采用JNDI对 JMS 的各种管理对象(Administered + Objects) (即JMS Queue, Topic and ConnectionFactory)是很常用的方法,但在有些 + 情况时JNDI不可用,或者你不需要用JNDI时,如何还能正常使用JMS呢? + HornetQ允许你不通过JNDI也能使用JMS。HornetQ支持直接创建JMS的各种对象而无需JNDI的存在。 + 中包括有这样的例子供读者参考。 + 下面我们就将上述那个简单的例子重写,以抛开对JNDI的依赖: + 我们通过HornetQJMSClient类来方便地创建JMS的ConnectionFactory。注意这里要提供各种连接参数和定义 + 所用的传输方式。有关连接器(connector)的信息参见 + +TransportConfiguration transportConfiguration = + new TransportConfiguration(NettyConnectorFactory.class.getName()); +ConnectionFactory cf = HornetQJMSClient.createConnectionFactory(transportConfiguration); + + 同样利用HornetQJMSClient类创建JMS Queue对象: + Queue orderQueue = HornetQJMSClient.createQueue("OrderQueue"); + 然后用连接工厂创建 JMS 连接: + Connection connection = cf.createConnection(); + 还有非事务的\AUTO_ACKNOWLEDGE方式的 JMS 会话(session): + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + 以及用于发送消息的MessageProducer: + MessageProducer producer = session.createProducer(orderQueue); + 和接收消息的 MessageConsumer: + MessageConsumer consumer = session.createConsumer(orderQueue); + 启动连接: + connection.start(); + 创建一个简单的 TextMessage 并将其发送到队列: + TextMessage message = session.createTextMessage("This is an order"); +producer.send(message); + 接收消息: + TextMessage receivedMessage = (TextMessage)consumer.receive(); +System.out.println("Got order: " + receivedMessage.getText()); + +
+
+ Client ID的设置 + 在建立持久的订阅(subscription)时,JMS客户需要有一个客户ID (client id)。我们可以通过配置 + connection factory来定义它。(其中的 client-id项)。这样所有通过这个 + connection factory来创建的连接都具有这个客户ID。 +
+
+ 设置DUPS_OK的Batch Size + 如果JMS的通知模式为DUPS_OK,我们可以配置接收者(consumer)以使得它以批为单位 + 发送通知,而不是一个一个地发通知。这样做可以节省很多带宽,效率高。配置的方法是设置connection factory下 + 的dups-ok-batch-size项。单位是字节(byte)。默认值是1024 * 1024 bytes = 1 MiB。 +
+
+ 设置事务(Transaction)的Batch Size + 当在一个事务内接收消息时,可能通过配置使接收者采用批量的方式发送通知,而不是一个一个的发送。这样也可以节省带宽。 + 配置方法是设置connection factory下的transaction-batch-size项。 单位是字节(byte)。默认值是1024 * + 1024。 +
+
diff --git a/docs/user-manual/zh/using-server.xml b/docs/user-manual/zh/using-server.xml new file mode 100644 index 0000000000..1264e302fa --- /dev/null +++ b/docs/user-manual/zh/using-server.xml @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + 使用HornetQ服务 + 本章将介绍如何使用HornetQ服务。 + 其中的内容包括服务器的位置,如何启动和停止HornetQ服务器。本章还将解释HornetQ的目录结构,其中的文件及其用途。 + 本章中所提到的HornetQ服务器是指HornetQ默认配置的独立服务器,包含JMS服务和JNDI服务。 + 对于运行于JBoss应用服务器中的HornetQ,其基本结构是一样的,只是有一些小的差别。 +
+ 服务的启动和停止 + 在HornetQ的安装目录下bin子目录中包含有一个unit/linux脚本run.sh和对应的Windows批处理文件run.bat。 + 如果你是在Unix/Linux环境,在bin目录下运行./run.sh + 如果是在Windows环境,则在bin目录下运行 run.bat + 这个脚本文件会设置classpath以及各种JVM参数,并启动JBoss Microcontainer。JBoss Microcontainer是一个轻量级的容器。 + 它被用来部署HornetQ的POJO对象。 + 要停止服务,运行其中的相应脚本:在Unix/Linux环境下,运行 stop.sh。 + 在Windows环境,运行 run.bat + 注意HornetQ需要在Java 6及以上版本才能正常运行。 + 启动和停止脚本在默认条件下读取config/stand-alone/non-clustered目录下的配置文件。 + 如果要指向其他目录,可以在命令行实现,例如: ./run.sh ../config/stand-alone/clustered。 + 这一方法同样适用于Windows批处理文件。 +
+
+ 服务器端JVM参数的设置 + 在启动脚本run.shrun.bat中设置了一些JVM参数, + 这些参数主要是调整Java 6的运行环境及拉圾回收的策略。我们建议采用并行拉圾回收的方法。 + 这种方法可以将拉圾回收所造成的延时进行平均分配,有效减少由于拉圾回收引起的长时间暂停的情况。 + 默认条件下HornetQ需要最大1GB的内存空间。通过-Xms-Xmx可以调整Java程序内存的使用。 + 你可以向启动脚本中添加其它的参数或修改已有的参数,已满足你的需要。 +
+
+ 服务器端的classpath + HornetQ在其classpath中寻找配置文件。 + classpath被定义在run.shrun.bat脚本中。在HornetQ的发布中,启动脚本将非集群的配置文件目录加进了classpath中。该目录包括了一组配置文件,可以让HornetQ以基本的非集群方式运行。它的具体位置是在HornetQ发布根目录下 config/stand-along/non-clustered/ 子目录。 + 在HornetQ的发布包中包括了一组标准的配置目录,它们是: + + + 非集群方式的独立服务器配置 + + + 集群方式的独立服务器配置 + + + 非集群方式运行于JBoss应用服务器 + + + 集群方式运行于JBoss应用服务器 + + + 当然你可以创建自己定义的配置文件目录。要注意的是将你的目录加到classpath中以便HornetQ能正确找到并加载。 +
+
+ Library Path + 如果要在Linux上使用异步IO的日志(Asynchronous IO Journal), + 你需要在java选项中指定java.library.pathrun.sh脚本可以自动完成这一步。 + 如果没有指定java.library.path,JVM将使用LD_LIBRARY_PATH环境变量。 +
+
+ 系统变量 + HornetQ命令行可以接受系统变量来配置日志(logging)。有关logging配置的具体信息参见 +
+
+ 配置文件 + 配置文件的路径定义在 run.shrun.bat 脚本中的classpath里。该路径下可以包含以下文件: + + + hornetq-beans.xml (如果是运行在JBoss应用服务器内,则为 hornetq-jboss-beans.xml)。这是JBoss Microcontainer的bean配置文件。其中定义了HornetQ的 + 各种bean,以及它们之间的依赖关系。HornetQ的bean都是一些POJO。是JBoss Microcontainer保证了这些bean的正确装载和运行。 + + + hornetq-configuration.xml。这个是HornetQ的主要的配置文件。 + 其中的所有参数在中给出了解释. 在 也有更多的相关信息。 + + + hornetq-queues.xml。这个文件里包含了预定义的queue以及它们的配置,包括安全设置。 + 这是一个可选的文件,里面所有的内容都可以放在 hornetq-configuration.xml文件中。 + 在默认的配置文件目录下并没有这个文件。HornetQ之所以提供这个文件是为了用户便于管理他们的queue。在classpath中 + 允许包含多个 hornetq-queues.xml 文件。所有的这些文件都会被加载。 + + + hornetq-users.xml。用户信息文件。HornetQ本身实现了一个基本的 + 安全管理器(security manager),它从这个文件内读取用户的安全信息,如用户名,密码和角色。 + 想了解更多关于安全的信息,参见 + + + hornetq-jms.xml。这个文件包含有JMS对象。HornetQ的默认配置中包含有JMS服务, + 它从这个文件中读取JMS Queue,Topic和ConnectionFactory并将它们部署到JNDI服务中。如果你不使用JMS, + 或者你不需要部署这些JMS对象,那么你就不需要这个文件。有关JMS的使用详见 + + + logging.properties 这个文件用于配置logging + handlers。详见 + + + log4j.xml。 这是 Log4j handler的配置文件。 + + + + 如果在hornetq-configuration.xml文件中将file-deployment-enabled 参数 + 定义为false,则HornetQ将不会加载其它的配置文件。这个参数的默认值是true。 + + 所有配置文件中的参数都可以用系统变量来定义其值。以下用一个connector的配置来说明: + <connector name="netty"> + <factory-class>org.hornetq.integration.transports.netty.NettyConnectorFactory + </factory-class> + <param key="host" value="${hornetq.remoting.netty.host:localhost}" type="String"/> + <param key="port" value="${hornetq.remoting.netty.port:5445}" type="Integer"/> +</connector> + 在上面的配置中我们定义了两个系统变量 hornetq.remoting.netty.hosthornetq.remoting.netty.port。它们的值会被相应的系统变量的值(如果定义了的话)所替代。 + 如果没有定义这些系统变量,它们的默认值将分别为 localhost 及 5445。也可以不给出默认值,但如果这样就 + 必须要定义相应的系统变量。 +
+
+ JBoss Microcontainer Beans 文件 + HornetQ的POJO对象是由 JBoss Microcontainer + 进行加载和运行的。JBoss Microcontainer是一个轻量级的加载工具。 + + 如果是在JBoss应用服务器内运行,HornetQ同样需要一个bean的配置文件来将其部署到JBoss中。但是这与单独运行时的配置文件略有不同。 + 这是因为应用服务器内已经部署了一些服务,如安全服务等。所以在HornetQ中这些服务就不需要再部署了。 + + 让我们看一个HornetQ作为单独服务器时的一个配置文件例子: + + <?xml version="1.0" encoding="UTF-8"?> + +<deployment xmlns="urn:jboss:bean-deployer:2.0"> + +<bean name="Naming" class="org.jnp.server.NamingBeanImpl"/> + +<!-- JNDI server. Disable this if you don't want JNDI --> +<bean name="JNDIServer" class="org.jnp.server.Main"> + <property name="namingInfo"> + <inject bean="Naming"/> + </property> + <property name="port">1099</property> + <property name="bindAddress">localhost</property> + <property name="rmiPort">1098</property> + <property name="rmiBindAddress">localhost</property> +</bean> + +<!-- MBean server --> +<bean name="MBeanServer" class="javax.management.MBeanServer"> + <constructor factoryClass="java.lang.management.ManagementFactory" + factoryMethod="getPlatformMBeanServer"/> +</bean> + +<!-- The core configuration --> +<bean name="Configuration" class="org.hornetq.core.config.impl.FileConfiguration"> +</bean> + +<!-- The security manager --> +<bean name="HornetQSecurityManager" + class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl"> + <start ignored="true"/> + <stop ignored="true"/> +</bean> + +<!-- The core server --> +<bean name="HornetQServer" class="org.hornetq.core.server.impl.HornetQServerImpl"> + <start ignored="true"/> + <stop ignored="true"/> + <constructor> + <parameter> + <inject bean="Configuration"/> + </parameter> + <parameter> + <inject bean="MBeanServer"/> + </parameter> + <parameter> + <inject bean="HornetQSecurityManager"/> + </parameter> + </constructor> +</bean> + +<!-- The JMS server --> +<bean name="JMSServerManager" + class="org.hornetq.jms.server.impl.JMSServerManagerImpl"> + <constructor> + <parameter> + <inject bean="HornetQServer"/> + </parameter> + </constructor> +</bean> + +</deployment> + + 我们从上可以看出HornetQ的单独服务器(以及核心服务器)包括了一些POJO对象: + + + JNDIServer + 很多客户端需要JNDI来获取JMS的对象,因此我们提供了一个JNDI服务来满足它们。如果不需要JNDI,可以在配置 + 文件中将它们注释掉。 + + + MBeanServer + 这个对象提供了JMX管理接口。它是一个MBean服务器,可管理的对象可以注册到这个服务器上。 + 通常这就是一个JVM内部的默认的平台MBean服务器。如果不需要些服务,可以在配置文件中将其注释或删除。 + + + Configuration + 这是HornetQ的Configuration对象。默认时它是一个FileConfiguration对象。它可以从文件系统中读取 + 配置信息。有些情况下(如嵌入式HornetQ)你可以将它定义为其它对象,以便用其它方法获得配置信息。 + + + Security Manager. 可配置的安全管理器。默认的安全管理器使用 hornetq-users.xml 文件中的配置信息。 + 它也可以配置为一个JAAS的安全管理器。当HornetQ运行于JBoss应用服务器中时,它还可以配置为JBoss的安全管理器,以达到更紧密的集成。 + 如果不需要安全管理,你也可以将它删除。 + + + HornetQServer + 这是HornetQ的核心服务对象,几乎所有的核心功能都在这里。 + + + JMSServerManager + 这个对象将hornetq-jms.xml文件中定义的JMS的对象进行部署,比如JMS Queues, Topics + 以及ConnectionFactory。它还提供一套简单的管理接口以方便地对这些JMS对象进行管理。通常它只是将工作代理给 + 核心服务器。如果你不需要在服务器端进行JMS对象的部署与管理,可以将它从配置中去掉。 + + +
+
+ JBoss AS4 MBean 服务 + + 本节只讨论在JBoss AS 4上配置HornetQ。其与JBoss Microcontainer的配置很相似。 + + + <?xml version="1.0" encoding="UTF-8"?> +<server> + + <mbean code="org.hornetq.service.HornetQFileConfigurationService" + name="org.hornetq:service=HornetQFileConfigurationService"> + </mbean> + + <mbean code="org.hornetq.service.JBossASSecurityManagerService" + name="org.hornetq:service=JBossASSecurityManagerService"> + </mbean> + + <mbean code="org.hornetq.service.HornetQStarterService" + name="org.hornetq:service=HornetQStarterService"> + <!--let's let the JMS Server start us--> + <attribute name="Start">false</attribute> + + <depends optional-attribute-name="SecurityManagerService" + proxy-type="attribute">org.hornetq:service=JBossASSecurityManagerService</depends> + <depends optional-attribute-name="ConfigurationService" + proxy-type="attribute">org.hornetq:service=HornetQFileConfigurationService</depends> + </mbean> + + <mbean code="org.hornetq.service.HornetQJMSStarterService" + name="org.hornetq:service=HornetQJMSStarterService"> + <depends optional-attribute-name="HornetQServer" + proxy-type="attribute">org.hornetq:service=HornetQStarterService</depends> + </mbean> + +</server> + + + 这个jboss-service.xml包含在hornetq-service.sar文件中,它用来配置AS4中嵌入运行的HornetQ。 + 在这个配置文件中我们启动了以下几个服务: + + + HornetQFileConfigurationService + 这个MBean服务的任务是管理 FileConfiguration POJO的生命周期。 + + + JBossASSecurityManagerService + 这个MBean服务管理着 JBossASSecurityManager POJO的生命周期。 + + + HornetQStarterService + 这个MBean服务管理着HornetQServer POJO。它依赖于 JBossASSecurityManagerService 和 + HornetQFileConfigurationService 这两个MBean。 + + + HornetQJMSStarterService + 这个MBean服务管理着 JMSServerManagerImpl POJO对象。如果不需要JMS,可以去掉这个服务。 + + + JMSServerManager + 用于启动JMSServerManager。 + + +
+
+ 主配置文件 + HornetQ 核心服务的配置保存在 hornetq-configuration.xml文件中。 +         FileConfiguration bean 读取这个文件来对消息服务器进行配置。 + HornetQ有很多的配置参数。采用默认的配置在绝大多数情况下可以很好的运行。事实上每一个参数都有默认的处理,因此一个只包含有一个空 + 的configuration的配置文件是一个有效的文件。对各个参数的解释贯穿于本手册。你还可参参照 + 这里来查找你想看的参数。 +
+
diff --git a/docs/user-manual/zh/wildcard-routing.xml b/docs/user-manual/zh/wildcard-routing.xml new file mode 100644 index 0000000000..1be82241cf --- /dev/null +++ b/docs/user-manual/zh/wildcard-routing.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + 使用通配符实现消息路由 + HornetQ支持使用带通配符的地址对消息路由。 + 例如,当创建一个队列时使用了地址queue.news.#,那么它就能接收 + 所有和这个地址通配符相配的每一个地址的消息。这样的地址如 queue.news.europequeue.news.usaqueue.news.usa.sport等。这样一个消息接收者可以接收一组相关 + 的地址的消息,而不是只能指定一个具体的地址。 + + 用JMS的术语来说,这个功能就是允许创建“话题组”(topic hierarchy)。 + + 要使用本功能需要将wild-card-routing-enabled属性设置为true。 + 这个属性在 hornetq-configuration.xml 文件中。默认值是true + 关于通配符的语法参见 章及 + diff --git a/docs/user-manual/zh/wildcard-syntax.xml b/docs/user-manual/zh/wildcard-syntax.xml new file mode 100644 index 0000000000..e527d7af1d --- /dev/null +++ b/docs/user-manual/zh/wildcard-syntax.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + 了解 HornetQ 通配符的语法 + HornetQ使用了一种专门的通配符语法来配置安全、地址及接收者(consumer)的创建。 + 这种语法与 AMQP所用的语法相似。 + 一个HornetQ的通配符表达式是由一些由“.”分隔的单词组成。 + 特殊字符“#”和“*”在表达式中可作为一个单词,它们代表 + 特殊的意义。 + 字符“#”表示“零或多个单词的任意排列”。 + 字符“*”表示“一个单词”。 + 因此,通配符表达式“news.europe.#”可以匹配“news.europe”、“news.europe.sport”、 + “news.europe.politics”以及“news.europe.politics.regional”,但是与“news.usa”、 + “news.usa.sport” 及 “entertainment”不相匹配。 + 通配符“news.*”与“news.europe”匹配,但不与“news.europe.sport”匹配。 + 通配符“news.*.sport”与“news.europe.sport”及“news.usa.sport”匹配,但与 + “news.europe.politics”不匹配。 + diff --git a/etc/IDEA-style.jar b/etc/IDEA-style.jar new file mode 100644 index 0000000000..06e3baaa61 Binary files /dev/null and b/etc/IDEA-style.jar differ diff --git a/etc/checkstyle.xml b/etc/checkstyle.xml new file mode 100644 index 0000000000..7a420f42b5 --- /dev/null +++ b/etc/checkstyle.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/etc/findbugs-exclude.xml b/etc/findbugs-exclude.xml new file mode 100644 index 0000000000..f2be1b75ca --- /dev/null +++ b/etc/findbugs-exclude.xml @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/etc/license-header.txt b/etc/license-header.txt new file mode 100644 index 0000000000..7af0bc0773 --- /dev/null +++ b/etc/license-header.txt @@ -0,0 +1,11 @@ +Copyright ${copyrightYear} Red Hat, Inc. +Red Hat licenses this file to you under the Apache License, version +2.0 (the "License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied. See the License for the specific language governing +permissions and limitations under the License. + diff --git a/etc/org.eclipse.jdt.core.prefs b/etc/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..eb99f0b1d9 --- /dev/null +++ b/etc/org.eclipse.jdt.core.prefs @@ -0,0 +1,305 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes= +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=optimize out +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.processAnnotations=enabled +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=82 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=16 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=82 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=18 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=82 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=82 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=82 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=82 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=82 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=18 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=0 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=next_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=do not insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=100 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=3 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=3 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=3 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=true +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=true +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=3 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=false +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/etc/org.eclipse.jdt.ui.prefs b/etc/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000000..f68cb8d1c5 --- /dev/null +++ b/etc/org.eclipse.jdt.ui.prefs @@ -0,0 +1,119 @@ +#Thu Nov 10 13:53:54 CET 2011 +cleanup.add_default_serial_version_id=false +cleanup.add_generated_serial_version_id=true +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_serial_version_id=true +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=true +cleanup.correct_indentation=true +cleanup.format_source_code=true +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=false +cleanup.make_parameters_final=true +cleanup.make_private_fields_final=true +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=true +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=true +cleanup.qualify_static_field_accesses_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=true +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=true +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=true +cleanup.use_this_for_non_static_field_access=true +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=true +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +cleanup_profile=_HornetQ profile +cleanup_settings_version=2 +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_'HornetQ' +formatter_settings_version=12 +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;com;org; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.ondemandthreshold=9999 +org.eclipse.jdt.ui.overrideannotation=true +org.eclipse.jdt.ui.staticondemandthreshold=9999 +org.eclipse.jdt.ui.text.custom_code_templates=