[list][*][b]优先级队列[/b][/list]
[color=red]只有当消费者不足,不能及时进行消费的情况下,优先级队列才会生效[/color]
RabbitMQ3.5以后已经集成了rabbitmq_priority_queue
[quote][url]http://www.rabbitmq.com/community-plugins.html[/url][/quote]
验证方式:[color=blue]触发为及时消费场景[/color],常用场景与Qos结合使用
1、可先发送消息,再进行消费
2、开启手动应答、设置Qos。若为1,在一个消费者存在的情况下,除第一个消息外均按优先级进行消费(第一个消息被及时消费掉了)
3、可在方式二的基础上不断增加消费者,也符合优先调用规则
[list]
[*][b]注意要点[/b]
[/list]
[i]为消息设置优先级别[/i]:
//随机设置消息优先级
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));
[i]为队列创建优先级别[/i]:
//设置队列的优先级,消息的优先级大于队列的优先级,以较小值为准(例如:队列优先级5、消息优先级8,消息实际优先级为5)
Map<String, Object> args=new HashMap<String, Object>();
args.put("x-max-priority", 10);//队列优先级只能声明一次,不可改变(涉及到硬盘、内存存储方式)
channel.queueDeclare(queueName, false, false, false, args);
[i][color=blue]队列、消息上均要设置优先级才可生效,以较小值为准[/color][/i]
[i]队列优先级[color=blue]只能声明一次[/color],不可改变(涉及到硬盘、内存存储方式)[/i]
[i]优先级队列在内存、硬盘、cpu会有成本消耗,[color=blue]不建议创建大量的优先级别[/color](数量、级别种类、大级别,理解混乱,英文理解困难...)[/i]
[list]
[*][b]优先队列测试消息发送类[/b]
[/list]
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!");
}
}
[list]
[*][b]优先队列测试消息接收类[/b]
[/list]
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();
}
}