- RabbitMQ教程2:一个生产者和多个消费者
- 代码基础: 易学笔记-RabbitMQ教程1:一个生产者和一个消费者
- 新建生产者类:
package OneProductMulConsume; import java.io.IOException; import java.util.concurrent.TimeoutException; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.Connection; import com.rabbitmq.client.Channel; import com.rabbitmq.client.MessageProperties; public class OneProductSend { private static final String TASK_QUEUE_NAME = "task_queue"; public static void main(String[] argv) throws java.io.IOException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("192.168.65.129"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); /** * 第二个参数为true表示队列持久化 */ channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null); for (int i = 0; i < 10; i++) { String message = "X"; for (int j = 0; j < i; j++) { message += "."; } message = message + "(" + i + ")"; /** * MessageProperties.PERSISTENT_TEXT_PLAIN:表示消息持久化 */ channel.basicPublish("", TASK_QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes()); System.out.println(" [x] Sent '" + message + "'"); } channel.close(); connection.close(); } // ... }
- 消息持久化
/**
* MessageProperties.PERSISTENT_TEXT_PLAIN:表示消息持久化
*/
channel.basicPublish("", TASK_QUEUE_NAME,
MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
/**
* 第二个参数为true表示队列持久化
*/
channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);
- 消息持久化
- 新建消费者类:
package OneProductMulConsume; import com.rabbitmq.client.*; import java.io.IOException; public class MulConsumeRecv { private static final String TASK_QUEUE_NAME = "task_queue"; public static void main(String[] argv) throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("192.168.65.129"); final Connection connection = factory.newConnection(); final Channel channel = connection.createChannel(); channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null); System.out.println(" [*] Waiting for messages. To exit press CTRL+C"); /** * 表示每次只从消息队列中获取一条消息,等处理完成后通知服务端再发送下一条消息 */ channel.basicQos(1); final Consumer consumer = new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String message = new String(body, "UTF-8"); System.out.println(" [x] Received '" + message + "'"); try { doWork(message); } finally { System.out.println(" [x] Done"); /** * 处理完成后通知服务端 */ channel.basicAck(envelope.getDeliveryTag(), false); } } }; /** * 第二个参数为false表示处理完成后通知服务端,以便服务端进行确认 */ boolean autoAck = false; channel.basicConsume(TASK_QUEUE_NAME, autoAck, consumer); } private static void doWork(String task) { for (char ch : task.toCharArray()) { if (ch == '.') { try { Thread.sleep(1000); } catch (InterruptedException _ignored) { Thread.currentThread().interrupt(); } } } } }
- 设置消费者返回明确的处理结果标志
/**
* 第二个参数为false表示处理完成后通知服务端,以便服务端进行确认
*/
boolean autoAck = false;
channel.basicConsume(TASK_QUEUE_NAME, autoAck, consumer);
- 消费者返回结果处理标识
/**
* 处理完成后通知服务端
*/
channel.basicAck(envelope.getDeliveryTag(), false);
/**
* 表示每次只从消息队列中获取一条消息,等处理完成后通知服务端再发送下一条消息
*/
channel.basicQos(1);
- 设置消费者返回明确的处理结果标志
- 测试
- 循环分发:两个工作者循环获取消息并处理(总共10个消息)
- 先启动工作者1:处理了8个消息
[*] Waiting for messages. To exit press CTRL+C
[x] Received 'X(0)'
[x] Done
[x] Received 'X.(1)'
[x] Done
[x] Received 'X..(2)'
[x] Done
[x] Received 'X...(3)'
[x] Done
[x] Received 'X....(4)'
[x] Done
[x] Received 'X.....(5)'
[x] Done
[x] Received 'X.......(7)'
[x] Done
[x] Received 'X.........(9)'
[x] Done
- 后启动工作者2:处理了2个消息
[*] Waiting for messages. To exit press CTRL+C
[x] Received 'X......(6)'
[x] Done
[x] Received 'X........(8)'
[x] Done
- 先启动工作者1:处理了8个消息
- 循环分发:两个工作者循环获取消息并处理(总共10个消息)