Document directory
- Configuration parameters
- Pipeline subscription)
- Duplex networkconnector)
- Specify and limit destination
- Stuck message
- Other Instructions
Activemq cluster: Network ctor
Kimmking@163.com
2012-12-26
Network Connection Mode)
Activemq provides the cluster function in the network connection mode for the horizontal scalability required by massive messages and the high availability of the system. Simply put, multiple broker instances are connected together to provide external services as a whole, thus improving the overall messaging service capability. In this way, broker instances connected together can share the queue and consumer list to achieve the purpose of distributed queue.
Topology
Several different activemq deployment topologies (embedding, master-slave replication, and network connection ):
Configuration example
Add the following content to the broker node of activemq. xml:
<Networkconnectors>
<Networkconnectoruri = "static :( TCP: // localhost: 62001)"/>
</Networkconnectors>
Uri can also be used in the following two ways:
1. multicast://default
2. masterslave:(tcp://host1:61616,tcp://host2:61616,tcp://..)
Among them, the first URL of the masterslave method must be the master, and the other is the slave.
You can configure multiple networkctor ctor s in a broker instance. If more than two networkctor ctor s direct to the same broker, you must explicitly specify the name.
Static URI Configuration
You can specify multiple URLs in the static URI mode. networkconnector connects to each broker.
<networkConnectors>
<networkConnector uri="static:(tcp://host1:61616,tcp://host2:61616,tcp://..)"/>
</networkConnectors>
Several attributes of Uri:
Attribute |
Default Value |
Description |
Initialreconnectdelay |
1000 |
Time waiting before reconnection (MS) (if useexponentialbackoff is false) |
Maxreconnectdelay |
30000 |
Maximum waiting time (MS) before Reconnection) |
Useexponentialbackoff |
True |
Whether to increase the wait time when each reconnection fails |
Backoffmultiplier |
2 |
Increase the wait time coefficient |
Networkconnector configuration parameters
Attribute |
Default Value |
Description |
Name |
Bridge |
Name |
Dynamiconly |
False |
If this parameter is set to true, the corresponding network persistent subscription is created only when the persistent subscription is activated. It is activated at startup by default. |
Decreasenetworkconsumerpriority |
False |
If it is true, the consumer priority of the network is reduced to-5. If it is false, the default value is 0, which is the same as that of the local consumer. |
Networkttl |
1 |
Number of brokers used by messages and subscriptions on the network |
Conduitsubscriptions |
True |
Whether multiple network consumers are treated as one consumer. |
Excludeddestinations |
Empty |
Destination not forwarded through the network |
Dynamicallyincludeddestinations |
Empty |
Destinations forwarded through the network. Note that the empty list indicates that all objects are forwarded. |
Staticallyincludeddestinations |
Empty |
All matches will be forwarded through the network-even if there is no corresponding consumer |
Duplex |
False |
If true, messages can be consumed and sent to the network broker. |
Prefetchsize |
1000 |
Set the prefetch size parameter of the Network consumer. The value must be greater than 0 because the network consumer cannot round the message by himself. |
Suppressduplicatequeuesubscriptions |
False |
(From version 5.3) if it is true, duplicate subscription relationships are blocked once they are generated. |
Bridgetempdestinations |
True |
Whether to broadcast advisory messages to create a temporary destination. |
Alwayssyncsend |
False |
(From version 5.6) if it is true, non-persistent messages will also be sent to the remote broker using the request/reply method instead of the oneway method. |
Staticbridge |
False |
(Starting from version 5.6) if true, only destination configured in staticallyincludeddestinations can be processed. |
Networkconnector is implemented based on activemq's advisorymessage mechanism (see here ). What happens when broker2 points to broker1 through networkconnector and duplex?
If broker1 is started, broker2 starts to start.
1. broker2 first start its own Connector
2. Then use a VM connector to create a connection and use itself as a client to connect to broker1.
3. subscribe to the advisory message to obtain the consumer and the corresponding queue list.
So far, the two sides have established a relationship.
Then, through broker1 forwarding, the consumers on broker1 can consume messages on queue of broker2. This process can be seen as a message that has been consumed twice. broker1, as a consumer, consumes messages on broker2, and broker1, as a broker, delivers messages to actual consumers.
Pipeline subscription)
The choice of conductor subscriptions determines the proportion of network consumers among all consumers. Assume that there are two network consumers on the same remote broker1 and a local consumer of broker2.
1. If conducting subscriptions is true, then two network consumers are equivalent to only one consumer, and broker1 only registers one consumer on broker2. At this time, 300 messages are sent to broker2. Each of the two network consumers receives 75 messages, and each local consumer receives 150 messages.
2. If conducting subscriptions is false, the three consumers divide all messages equally. broker1 registers two consumers on broker2. At this time, 300 messages are sent to broker2. The two network consumers receive 100 messages each, just like the local consumers.
Duplex networkconnector)
By default, networkconnector is a one-way connection to forward messages. When duplex is set to true, it becomes a two-way connection. At this time, the duplex networkconnector configured to direct to broker1 on broker2 is equivalent to configuring
The network connection from broker2 to broker1 is also configured with the network connection from broker1 to broker2. (No matter whether broker1 agrees or not, they are all kidnapped .) Of course, configuration on broker1 only has the same effect.
Note: You can create more than two-way network connections between two brokers to increase throughput or partition the topic/queue by specifying different names.
Specify and limit destination
If networkconnector shares too many destinations, many advisory messages will be transmitted, and the topology of the system will become very complex. There are multiple ways to restrict these destination configurations:
1. dynamicallyincludeddestinations
Ü destination matched here will be forwarded as needed
2. excludeddestinations
Ü the destination matched here will not be forwarded.
3. staticallyincludeddestinations
Ü if staticbridge is specified as true, only the destination matching here can be forwarded. In this case, the local broker is completely represented by other brokers. In addition, this broker does not subscribe to advisorymessage from other brokers, nor obtain any remote consumer information.
Wildcards can be used for these configurations, such as ">". For details, see wildcard.
Sample Code:
<networkConnectors>
<networkConnector uri="static:(tcp://localhost:61617)"
name="bridge"
conduitSubscriptions="true"
decreaseNetworkConsumerPriority="false">
<dynamicallyIncludedDestinations>
<queue physicalName="include.test.foo"/>
<topic physicalName="include.test.bar"/>
</dynamicallyIncludedDestinations>
<excludedDestinations>
<queue physicalName="exclude.test.foo"/>
<topic physicalName="exclude.test.bar"/>
</excludedDestinations>
<staticallyIncludedDestinations>
<queue physicalName="always.include.queue"/>
<topic physicalName="always.include.topic"/>
</staticallyIncludedDestinations>
</networkConnector>
</networkConnectors>
In addition, from version 5.6, you can set destinationfilter on networkconnector to specify that the advisory message you are interested in will be propagated.
<networkConnector uri="static:(tcp://host)" destinationFilter="Queue.include.test.foo,ActiveMQ.Advisory.Consumer.Topic.include.test.bar">
<dynamicallyIncludedDestinations>
<queue physicalName="include.test.foo"/>
<topic physicalName="include.test.bar"/>
</dynamicallyIncludedDestinations>
</networkConnector>
Stuck message
An interesting scenario is that broker1 and broker2 are connected through networkconnector. Some consumers connect to broker1 to consume messages on broker2. The message is first consumed by broker1 from broker2 and then forwarded to these consumers. Unfortunately, broker1 restarts when some messages are forwarded. These consumers found that broker1 connection failed and went up through failover to broker2, however, some of the messages they have not consumed have been distributed to broker1. These messages seem to have disappeared unless a consumer reconnects to broker1 for consumption. What should we do?
The method is to add the replaywhennoconsumers option from destinationpolicy of version 5.6. This option enables broker1 to return messages to its original broker when there are messages to be forwarded but no consumers. At the same time, enableaudit is set to false to prevent duplicated messages from being distributed after message reflux.
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry queue="TEST.>" >
<conditionalNetworkBridgeFilterFactory replayWhenNoConsumers="true" enableAudit="false"/>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
For more details, see here:
Http://tmielke.blogspot.de/2012/03/i-have-messages-on-queue-but-they-dont.html
Other Instructions
1. networkconnector is based on the advisorymessage mechanism. If the advisorysupport Type Selection of the broker is disabled, networkconnector will not work.
2. In the broker used for forwarding, only the data forwarded by the broker is recorded.
3. Data in the same queue of the remote broker cannot be seen in the broker used for forwarding (the Browse message list is empty, and the queuesize is 0 ).
Example
Download activemq 5.7 with the example of static network connector.
That is, the profile activemq-static-network-broker1.xml and activemq-static-network-broker2.xml.
They respectively use the TCP: // localhost: 61616 and TCP: // localhost: 61618 ports.
Static Network connector in the second file.
Start broker1 and broker2 respectively using these two configuration files ).
On the broker2 console, you can see:
Info | establishing network connection fromvm: // static-broker2? Async = false & Network = true to TCP: // localhost: 61616
Info | connector VM: // static-broker2 started
Info | Network connector discoverynetworkconnector: NC: brokerservice [static-broker2] started
Info | Apache activemq 5.7.0 (static-broker2, ID: kimmking-2270-1356502079016-0: 1) started
Info | for help or more information please see: http://activemq.apache.org
Info | network connection between Vm: // static-broker2 #0 andtcp: // localhost/127.0.0.1: 61616 @ 2271 (static-broker1) has been established.
On the broker1 console, you can see:
Info | Network Connection betweenvm: // static-broker1 #0 and TCP: // 127.0.0.1: 1710 @ 61616 (static-broker2) has beenestablished.
Enter jconsole in the command line and connect to the JMX console through the following URLs to manage the broker:
Ü service: JMX: RMI: // JNDI/RMI: // localhost: 1099/jmxrmi
Ü service: JMX: RMI: // JNDI/RMI: // localhost: 1100/jmxrmi
You can also configure jetty in the two XML files to view and manage them on the Web console.
Then, you can use the code to access messages in two brokers through static network connector.
Test code:
package org.qsoft.activemq.test;import java.util.concurrent.atomic.AtomicInteger;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.MessageProducer;import javax.jms.Queue;import javax.jms.QueueConnection;import javax.jms.QueueConnectionFactory;import javax.jms.QueueReceiver;import javax.jms.QueueSession;import javax.jms.Session;import javax.jms.TextMessage;import org.apache.activemq.ActiveMQConnectionFactory;import org.apache.activemq.command.ActiveMQQueue;public class TestReceiver {/** * @param args */public static void main(String[] args) {try {// init connection factory with activemqQueueConnectionFactory factoryA = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");// specify the destinationQueue queueB = new ActiveMQQueue("kk.b");// create connection,session,consumer and receive messageQueueConnection connA = factoryA.createQueueConnection();connA.start();// first receiver on broker1QueueSession sessionA1 = connA.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);QueueReceiver receiverA1 = sessionA1.createReceiver(queueB);final AtomicInteger aint1 = new AtomicInteger(0);MessageListener listenerA1 = new MessageListener(){public void onMessage(Message message) {try {System.out.println(aint1.incrementAndGet()+" => A1 receive from kk.b: " + ((TextMessage)message).getText());} catch (JMSException e) {e.printStackTrace();}}};receiverA1.setMessageListener(listenerA1 );// second receiver on broker1QueueSession sessionA2 = connA.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);QueueReceiver receiverA2 = sessionA2.createReceiver(queueB);final AtomicInteger aint2 = new AtomicInteger(0);MessageListener listenerA2 = new MessageListener(){public void onMessage(Message message) {try {System.out.println(aint2.incrementAndGet()+" => A2 receive from kk.b: " + ((TextMessage)message).getText());} catch (JMSException e) {e.printStackTrace();}}};receiverA2.setMessageListener(listenerA2 );// a fake one on broker1QueueReceiver receiverA3 = sessionA2.createReceiver(queueB);final AtomicInteger aint3 = new AtomicInteger(0);MessageListener listenerA3 = new MessageListener(){public void onMessage(Message message) {try {System.out.println(aint3.incrementAndGet()+" => A3 receive from kk.b: " + ((TextMessage)message).getText());} catch (JMSException e) {e.printStackTrace();}}};receiverA3.setMessageListener(listenerA3 );QueueConnectionFactory factoryB = new ActiveMQConnectionFactory("tcp://127.0.0.1:61618");Queue queueB1 = new ActiveMQQueue("kk.b");QueueConnection connB = factoryB.createQueueConnection();connB.start();// one receiver on broker2QueueSession sessionB1 = connB.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);QueueReceiver receiverB1 = sessionB1.createReceiver(queueB);final AtomicInteger bint1 = new AtomicInteger(0);MessageListener listenerB1 = new MessageListener(){public void onMessage(Message message) {try {System.out.println(bint1.incrementAndGet()+" => B1 receive from kk.b: " + ((TextMessage)message).getText());} catch (JMSException e) {e.printStackTrace();}}};receiverB1.setMessageListener(listenerB1 );// producer on broker2QueueSession sessionBp = connB.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);MessageProducer producer = sessionBp.createProducer(queueB1);int index = 0;while(index++<300){TextMessage message = sessionBp.createTextMessage(index + " from kk.b on broker2");producer.send(message);}} catch (Exception e) {e.printStackTrace();System.exit(1);}}}