Rabbitmq五种工作模式(二)
目录
1.生产端:准备消息数据msg,准备发送的目的地routingKey(队列名称),发送
2.交换机:路由模式交换机,根据队列名称routingKey将消息发送传递给queue
3.消费端:多个消费者监听同一个队列,形成一批资源的争抢结果;
一.工作模式(资源争抢)
1工作模式结构
1.生产端:准备消息数据msg,准备发送的目的地routingKey(队列名称),发送
2.交换机:路由模式交换机,根据队列名称routingKey将消息发送传递给queue
3.消费端:多个消费者监听同一个队列,形成一批资源的争抢结果;
应用场景: 抢红包. 资源调度系统
2.消息队列的确认逻辑
1.默认:
消息队列中的数据传给消费者,必须在消费返回执行成功信息,才可以销毁队列中的数据,防止消费者,发生异常,重新获取不到数据
channel.basicConsume("simple01", consumer);
消费的消费端绑定需要制定一个参数,autoAct(自动确认),消费逻辑在拿到消息后,直接确认的,没有经过消费逻辑的计算,true表示自动确认,false表示手动根据消费逻辑的执行发送确认需要调用确认的方法,返回确认的消息属性.
queue没有限制空闲繁忙的判断,没有限制一次性发送的消息数量;不关心消费端是否回执ack,都会发送消息;需要一种执行传递消息给消费者的逻辑:在繁忙时不发送消息,在空闲时间(处理完一条之后)才继续传递消息;
3代码(Rabbitmq启动)
1.代码模板
1.生产者
/**
* 一个生产端多个消费端(2个)
* @author TEDU
*
*/
public class WorkMode {
//拿到连接对象
//连接工厂的创建,返回需要使用的conncetion,channel;
public Channel getChannel(){
//创建一个连接从长
ConnectionFactory factory=new ConnectionFactory();
//需要将连接属性信息,交给连接工厂使用,ip,port,user,password,virturHost
factory.setHost("10.42.60.249");
factory.setPort(5672);
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
try{
//从连接工厂获取长连接.
Connection conn = factory.newConnection();
//从长连接中获取信道对象
return conn.createChannel();
}catch(Exception e){
throw new RuntimeException(e.getMessage());
}
}
private static final String queue_name="work01";
//因为work01多次使用,用一个常量来使用
@Test
public void productor() throws Exception{
Channel channel = getChannel();
//获取一个连接,调用方法发送消息到队列work01
channel.queueDeclare(queue_name, false, false, false, null);
//发送消息
for(int i=0;i<100;i++){
String msg="work mode msg "+i;
channel.basicPublish("", queue_name, null, msg.getBytes());
System.out.println("生产端发送到第:"+i+"条消息");
}
}
}
2.消费者 多个消费者,把名字改下就可以了
/**
* 消费者其一
* @author TEDU
*
*/
public class WrokRec01 {
private static final String queue_name="work01";
//监听同一个队列
public static void main(String[] args) throws Exception {
//创建一个连接从长
ConnectionFactory factory=new ConnectionFactory();
//需要将连接属性信息,交给连接工厂使用,ip,port,user,password,virturHost
factory.setHost("10.42.60.249");
factory.setPort(5672);
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
//从连接工厂获取长连接.
Connection conn = factory.newConnection();
//从长连接中获取信道对象
Channel channel=conn.createChannel();
channel.basicQos(1);//当消费端繁忙时,拿到消息还没有回执确认时,最多
//只传递给消费者1条消息
//省略声明队列的过程;
//生成消费者,绑定队列
QueueingConsumer cons=new QueueingConsumer(channel);
channel.basicConsume(queue_name, false, cons);
//监听获取消息 一个消费者代码
while(true){
Delivery deli=cons.nextDelivery();
Thread.sleep(100);
System.out.println("consumer01 receive: "+new String(deli.getBody()));
//手动返回 必须在消费逻辑执行完在返回
/*deliveryTag:Long 类型,标识的是当前delivery对象
*multiple:Boolean类型,true标识一次返回确认多天,false表示1条
*/
channel.basicAck(deli.getEnvelope().getDeliveryTag(),
false);
}
}
}
2.生产者测试代码
3.测试结果
4.消费者测试代码
5.测试结果
明显,02 我设置睡眠为50MS 所以20获取的大约是01的一倍左右
总结
1.生产端:准备消息数据msg,准备发送的目的地routingKey(队列名称),发送
2.交换机:路由模式交换机,根据队列名称routingKey将消息发送传递给queue
3.消费端:多个消费者监听同一个队列,形成一批资源的争抢结果;
4.channel.basicQos(1);//当消费端繁忙时,拿到消息还没有回执确认时,最多只传递给消费者1条消息
5.channel.basicAck(deli.getEnvelope().getDeliveryTag(), false);手动返回 必须在消费逻辑执行完在返回