ActiveMQ (13): Cluster of ActiveMQ

Keywords: Java Session JDBC network Database

I. Brief Introduction

1.1 Queue consumer clusters

ActiveMQ supports consumers'load-balanced consumption of highly reliable messages, and if a Consumer dies, the message is forwarded to other Queue s consumed by Constumer.

If a Consumer gets news faster than other consumers, he will get more news.

Therefore, it is recommended that Broker and Client of ActiveMQ configure links in the form of failover://transport.


1.2 Broker clusters

In most cases, a series of Brokers and Clients are used to link together. If a Broker dies, Client can automatically link to other Brokers.

To achieve the above behavior, we need to use failover protocol as Client.


If multiple brokers are started, Client can easily link directly from one broker to another using static or Dynamic discovery.


In this way, if there is no Consumer on a broker, its message will not be consumed, but the broker will send the message to other brokers through storage and forwarding strategies.


Special attention should be paid to:

  ActiveMQ defaults to two brokers, which are unidirectional after a static link. broker-A can access messages consuming broker-B. To support two-way communication, you need to

  When netWorkConnector is configured, set duplex=true.


Operation, Server Sets up Static Network Connection and Message Backflow

Message 1:

public void test1() throws Exception {
    ConnectionFactory cf = new ActiveMQConnectionFactory("liuy","123456","tcp://192.168.175.13:61676");
    Connection connection = cf.createConnection();
    connection.start();
		
    final Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
    Destination destination = session.createQueue("my-queue");
    for (int i = 0; i < 1; i++) {
        MessageConsumer consumer = session.createConsumer(destination);
        consumer.setMessageListener(new MessageListener() {
	    @Override
	    public void onMessage(Message message) {
	        TextMessage m = (TextMessage) message;
	        try {
	            System.out.println("===Received 11111111111:" + m.getText());
		    session.commit();
	        } catch (JMSException e) {
	            e.printStackTrace();
	        }    
	    }
	});
    }
}

Messager 2:

public void test1() throws Exception {
    ConnectionFactory cf = new ActiveMQConnectionFactory("liuy","123456","tcp://192.168.175.13:61616");
    Connection connection = cf.createConnection();
    connection.start();
		
    final Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
    Destination destination = session.createQueue("my-queue");
    for (int i = 0; i < 1; i++) {
        MessageConsumer consumer = session.createConsumer(destination);
        consumer.setMessageListener(new MessageListener() {
	    @Override
	    public void onMessage(Message message) {
	        TextMessage m = (TextMessage) message;
	        try {
	            System.out.println("===Received 22222222222:" + m.getText());
		    session.commit();
	        } catch (JMSException e) {
	            e.printStackTrace();
	        }    
	    }
	});
    }
}

Producer:

public void test1() throws Exception {
    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("liuy","123456","failover:(tcp://192.168.175.13:61616,tcp://192.168.175.13:61676)");
    Connection connection = connectionFactory.createConnection();
    connection.start();
    Session session = connection.createSession(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);
    Destination destination = session.createQueue("my-queue");
    MessageProducer producer = session.createProducer(destination);
    for (int i = 0; i < 30; i++) {
        TextMessage message = session.createTextMessage("message--" + i);
	Thread.sleep(1000);
	producer.send(message);
    }
    session.commit();
    session.close();
    connection.close();
}

Effect:

    


Master Slave

In version 5.9, Pure Master Slave was abolished and currently supports:

  1: Shared File System Master Slave:

    Master-Slave Based on Shared Storage: Multiple broker instances use one storage file. The master who gets the file lock is the master. The others are in the standby state if the master hangs up.

    A slave that grabs a file lock becomes master

  2: JDBC Master Slave: JDBC-based Master-Slave: Using the same database, the broker who gets the write lock of the LOCK table becomes master.

  3: Replicated LevelDB Store: Master-Slave mechanism based on ZooKeeper replicating LevelDB storage, which is new to 5.9


Specific can go to the official inspection: http://activemq.apache.org/masterslave.html 


Note: There is no static connection and backflow.


2.1 JDBC Master Slave

2.1.1 Brief Introduction

Using database as data source, we adopt Master/Slave mode, in which Master first acquires unique locks at startup, while other Slaves Broker wait to acquire unique locks.

It is recommended that clients use Failover to link Brokers.


As shown in the following figure:

  

Master Failure

  If Master fails, it releases the unique lock, the other Slavers acquire the unique lock, and the other Slavers immediately acquire the unique lock, then it becomes Master and starts all transmission links.

  At the same time, Client links Master before stopping links and polling links to other available Broker s, the new Master. As shown in the figure above.

Master Restart

  Start a new Broker at any time, that is, join the cluster as a new Slave, as shown in the right-hand figure above.


2.1.2 Configuration of JDBC Master Slave

Using < JDBC Persistence Adapter /> to configure message persistence automatically uses JDBC Master Slave.

Reference resources: ActiveMQ Message Storage Persistence jdbc

Remove static connections: reference ActiveMQ static network link

Remove reflux: reference Message Backflow Function in Cluster


Note: When configuring JDBC, be careful to configure useDatabaseLock="true", as follows

    <jdbcPersistenceAdapter dataSource="#mysql-ds" useDatabaseLock="true" />

Necessary settings, otherwise the primary key duplication exception will be reported when the data is saved


2.1.3 Test

Produce 30 news:

public void test1() throws Exception {
    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("liuy","123456","failover:(tcp://192.168.175.13:61616,tcp://192.168.175.13:61676)");
    Connection connection = connectionFactory.createConnection();
    connection.start();
    Session session = connection.createSession(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);
    Destination destination = session.createQueue("my-queue");
    MessageProducer producer = session.createProducer(destination);
    for (int i = 0; i < 30; i++) {
        TextMessage message = session.createTextMessage("message--" + i);
	Thread.sleep(1000);
	producer.send(message);
    }
    session.commit();
    session.close();
    connection.close();
}

  


Consumption 3 news:

public void test1() throws Exception {
    ConnectionFactory cf = new ActiveMQConnectionFactory("liuy","123456","failover:(tcp://192.168.175.13:61616,tcp://192.168.175.13:61676)");
    Connection connection = cf.createConnection();
    connection.start();
		
    final Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
    Destination destination = session.createQueue("my-queue");
    MessageConsumer consumer = session.createConsumer(destination);
    int i=0;
    while(i<3) {
        i++;
	TextMessage message = (TextMessage) consumer.receive();
	session.commit();
	System.out.println("Receiving and eliminating Interest:" + message.getText());
    }
    session.close();
    connection.close();
}

  


Then close the 61616 mq and enter the 61676 interface:

   



Posted by dcro2 on Fri, 05 Jul 2019 13:16:38 -0700