- 优先级队列
RabbitMQ3.5以后已经集成了rabbitmq_priority_queue
引用
验证方式: 触发为及时消费场景,常用场景与Qos结合使用
1、可先发送消息,再进行消费
2、开启手动应答、设置Qos。若为1,在一个消费者存在的情况下,除第一个消息外均按优先级进行消费(第一个消息被及时消费掉了)
3、可在方式二的基础上不断增加消费者,也符合优先调用规则
- 注意要点
为消息设置优先级别:
//随机设置消息优先级 Builder properties=new BasicProperties.Builder(); int priority=new Random().nextInt(10); properties.priority(priority);//建议0~255,超过貌似也没问题 channel.basicPublish(exchange_name, "", properties.build(), SerializationUtils.serialize(_mes));
为队列创建优先级别:
//设置队列的优先级,消息的优先级大于队列的优先级,以较小值为准(例如:队列优先级5、消息优先级8,消息实际优先级为5) Map<String, Object> args=new HashMap<String, Object>(); args.put("x-max-priority", 10);//队列优先级只能声明一次,不可改变(涉及到硬盘、内存存储方式) channel.queueDeclare(queueName, false, false, false, args);
队列、消息上均要设置优先级才可生效,以较小值为准
队列优先级只能声明一次,不可改变(涉及到硬盘、内存存储方式)
优先级队列在内存、硬盘、cpu会有成本消耗,不建议创建大量的优先级别(数量、级别种类、大级别,理解混乱,英文理解困难...)
- 优先队列测试消息发送类
package com.demo.mq.rabbitmq.example10; import java.io.IOException; import java.io.Serializable; import java.util.Random; import java.util.concurrent.TimeoutException; import org.apache.commons.lang3.SerializationUtils; import com.demo.mq.rabbitmq.MqManager; import com.rabbitmq.client.AMQP.BasicProperties; import com.rabbitmq.client.AMQP.BasicProperties.Builder; import com.rabbitmq.client.BuiltinExchangeType; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; /** * 优先队列测试消息发送类 * @author sheungxin * */ public class PrioritySend { private static String exchange_name="priority_direct"; public static void prioritySend(Serializable mes) throws IOException, TimeoutException{ Connection conn=MqManager.newConnection(); Channel channel=conn.createChannel(); channel.exchangeDeclare(exchange_name, BuiltinExchangeType.DIRECT); //发送10条消息 for(int i=0;i<10;i++){ //随机设置消息优先级 Builder properties=new BasicProperties.Builder(); int priority=new Random().nextInt(10); properties.priority(priority);//建议0~255,超过貌似也没问题 String _mes=mes.toString()+i; channel.basicPublish(exchange_name, "", properties.build(), SerializationUtils.serialize(_mes)); System.out.println(priority+" "+_mes); } channel.close(); conn.close(); } public static void main(String[] args) throws IOException, TimeoutException { prioritySend("priority send:hello world!"); } }
- 优先队列测试消息接收类
package com.demo.mq.rabbitmq.example10; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeoutException; import org.apache.commons.lang3.SerializationUtils; import com.demo.mq.rabbitmq.MqManager; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.BuiltinExchangeType; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; public class PriorityRecv { private static String exchange_name="priority_direct"; private static String queueName="priority_queue"; /** * 只有当消费者不足,不能及时进行消费的情况下,优先级队列才会生效 * 验证方式: * 1、可先发送消息,再进行消费 * 2、开启手动应答、设置Qos。若为1,在一个消费者存在的情况下,除第一个消息为均按优先级进行消费(第一个消息被及时消费掉了) * 3、可在方式二的基础上不断增加消费者,也符合优先调用规则 * 注意要点: * 1、队列、消息上均要设置优先级才可生效,以较小值为准; * 2、队列优先级只能声明一次,不可改变(涉及到硬盘、内存存储方式) * 3、优先级队列在内存、硬盘、cpu会有成本消耗,不建议创建大量的优先级别(数量、级别种类、大级别,理解混乱,英文理解困难...) * @throws IOException * @throws TimeoutException */ public static void priorityRecv() throws IOException, TimeoutException{ Connection conn=MqManager.newConnection(); Channel channel=conn.createChannel(); channel.exchangeDeclare(exchange_name, BuiltinExchangeType.DIRECT); //设置队列的优先级,消息的优先级大于队列的优先级,以较小值为准(例如:队列优先级5、消息优先级8,消息实际优先级为5) Map<String, Object> args=new HashMap<String, Object>(); args.put("x-max-priority", 10);//队列优先级只能声明一次,不可改变(涉及到硬盘、内存存储方式) channel.queueDeclare(queueName, false, false, false, args); channel.queueBind(queueName, exchange_name, ""); channel.basicQos(1);//需要开启手动应答模式,否则无效 channel.basicConsume(queueName, false, new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body) throws IOException{ String mes=SerializationUtils.deserialize(body); System.out.println(properties.getPriority()+":priority Received :'"+mes+"' done"); channel.basicAck(envelope.getDeliveryTag(), false); } }); } public static void main(String[] args) throws IOException, TimeoutException { priorityRecv(); } }