Rabbitmq Java implementation of work queue

Keywords: Java RabbitMQ

The previous blog has realized the configuration of RabbitMQ in java and the implementation of simple queues. This blog will introduce the work queues in RabbitMQ in combination with the actual situation.

 

Work queue - a single producer corresponds to multiple consumers

Create a new producer class, work queue send class. Suppose a message is generated every 20ms

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class workQueue_Send {
    private final static String QUEUE_NAME = "work_queue";
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        Connection connection = utils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        for(int i=0;i<50;i++)//Send 50 messages
        {
            String msg="msg"+i;
            channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
            Thread.sleep(20);//Suppose that the message is sent every 20ms
            System.out.println("send:"+ msg);
        }
        channel.close();
        connection.close();
    }
}

Two new consumer classes, work queue receive and work queue receive, are created, and their message processing speeds are 2s and 1s respectively

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class workQueue_Receive {
    private final static String QUEUE_NAME = "work_queue";
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = utils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [1] Waiting for messages.");

        DefaultConsumer defaultConsumer= new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                String msg = new String(body,"UTF-8");
                System.out.println("[1]receive:"+ msg);
                try {
                    Thread.sleep(2000);//Assume that the processing time of consumer 1 is 2s
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    System.out.println("[1]done:"+ msg);
                }
            }
        };

        channel.basicConsume(QUEUE_NAME,defaultConsumer);

    }

}
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class workQueue_Receive_2 {
    private final static String QUEUE_NAME = "work_queue";
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = utils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [2] Waiting for messages.");

        DefaultConsumer defaultConsumer= new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                String msg = new String(body,"UTF-8");
                System.out.println("[2]receive:"+ msg);
                try {
                    Thread.sleep(1000);//Assume that the processing time of consumer 2 is 1s
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    System.out.println("[2]done:"+ msg);
                }
            }
        };

        channel.basicConsume(QUEUE_NAME,defaultConsumer);

    }
}

In general, work queue receive 2 should be able to process more messages, but the result is different from our imagination. Two consumers process the same number of messages, and consumer 1 processes odd sequence number messages, and consumer 2 processes even sequence number messages.

     

This happens because work queue uses round robin by default

 

Here's how to use fair dispatch

First set prefetchCount = 1 in the Send class

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class workQueue_Send {
    private final static String QUEUE_NAME = "work_queue";
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        Connection connection = utils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        //Before each consumer sends a confirmation message, the message queue does not send the next message to the consumer, that is, only one message is processed at a time
        int prefetchCount = 1;
        channel.basicQos(prefetchCount);
        for(int i=0;i<50;i++)//Send 50 messages
        {
            String msg="msg"+i;
            channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
            Thread.sleep(20);//Suppose that the message is sent every 20ms
            System.out.println("send:"+ msg);
        }
        channel.close();
        connection.close();
    }
}
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class workQueue_Receive {
    private final static String QUEUE_NAME = "work_queue";
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = utils.getConnection();
        final Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        channel.basicQos(1);//Ensure that only one is distributed at a time
        System.out.println(" [1] Waiting for messages.");

        DefaultConsumer defaultConsumer= new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                String msg = new String(body,"UTF-8");
                System.out.println("[1]receive:"+ msg);
                try {
                    Thread.sleep(2000);//Assume that the processing time of consumer 1 is 2s
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    System.out.println("[1]done:"+ msg);
                    //Manual receipt
                    channel.basicAck(envelope.getDeliveryTag(),false);
                }
            }
        };
        boolean autoack=false;
        channel.basicConsume(QUEUE_NAME,autoack,defaultConsumer);

    }

}
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class workQueue_Receive_2 {
    private final static String QUEUE_NAME = "work_queue";
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = utils.getConnection();
        final Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        channel.basicQos(1);//Ensure that only one is distributed at a time
        System.out.println(" [2] Waiting for messages.");

        DefaultConsumer defaultConsumer= new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                String msg = new String(body,"UTF-8");
                System.out.println("[2]receive:"+ msg);
                try {
                    Thread.sleep(1000);//Assume that the processing time of consumer 2 is 1s
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    System.out.println("[2]done:"+ msg);
                    //Manual receipt
                    channel.basicAck(envelope.getDeliveryTag(),false);
                }
            }
        };

        boolean autoack=false;
        channel.basicConsume(QUEUE_NAME,autoack,defaultConsumer);

    }
}

Let's look at the results. In the fair distribution mode, work queue receive 2 processes more information, which is in line with expectations

  

 

For more details, please refer to the official documents

https://www.rabbitmq.com/tutorials/tutorial-two-java.html

155 original articles published, 31 praised, 20000 visitors+
Private letter follow

Posted by cheesehead on Thu, 30 Jan 2020 06:18:10 -0800