RabbitMQ学习资源来源于(蚂蚁课堂)
RabbitMQ高级队列(发布订阅)
生产者先投递消息给交换机,交换机根据路由策略RoutingKey 转发不同的队列服务器中存放。队列服务器再以推送或者拉起形式给消费者进行消费。
这个可能是消息队列中最重要的队列了,其他的都是在它的基础上进行了扩展。
功能实现:一个生产者发送消息,多个消费者获取消息(同样的消息),包括一个生产者,一个交换机,多个队列,多个消费者。
思路解读(重点理解):
(1)一个生产者,多个消费者
(2)每一个消费者都有自己的一个队列
(3)生产者没有直接发消息到队列中,而是发送到交换机
(4)每个消费者的队列都绑定到交换机上
(5)消息通过交换机到达每个消费者的队列
该模式就是Fanout Exchange(扇型交换机)将消息路由给绑定到它身上的所有队列
以用户发邮件案例讲解
注意:交换机没有存储消息功能,如果消息发送到没有绑定消费队列的交换机,消息则丢失。
RabbitMQ交换机的作用:
生产者发送消息不会向传统方式直接将消息投递到队列中,而是先将消息投递到交换机中,在由交换机转发到具体的队列,队列在将消息以推送或者拉取方式给消费者进行消费,这和我们之前学习Nginx有点类似。
交换机的作用根据具体的路由策略分发到不同的队列中,交换机有四种类型。
Direct exchange(直连交换机)是根据消息携带的路由键(routing key)将消息投递给对应队列的
Fanout exchange(扇型交换机)将消息路由给绑定到它身上的所有队列
Topic exchange(主题交换机)队列通过路由键绑定到交换机上,然后,交换机根据消息里的路由值,将消息路由给一个或多个绑定队列
Headers exchange(头交换机)类似主题交换机,但是头交换机使用多个消息属性来代替路由键建立路由规则。通过判断消息头的值能否与指定的绑定相匹配来确立路由规则。
发布订阅模式-生产者代码:
package com.google.util.config;
/**
* @author wk
* @Description:
* @date 2019/12/10 11:47
**/
public class Config {
//扇形交换机
public static final String FANOUT_EXCHANGE = "FANOUT_EXCHANGE";
//路由
public static final String DIRECT_EXCHANGE = "DIRECT_EXCHANGE";
//主题模式
public static final String TOPIC_EXCHANGE = "TOPIC_EXCHANGE";
public static class exchangeType {
public static final String fanout = "fanout";
public static final String direct = "direct";
public static final String topic = "topic";
}
}
package com.google.util.pubsub;
import com.google.util.config.Config;
import com.google.util.MQConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author wk
* @Description:RabbitMQ发布订阅生产者
* @date 2019/12/10 11:45
**/
public class FanoutProducer {
public static void main(String[] args) throws IOException, TimeoutException {
//建立连接
Connection connection = MQConnectionUtils.newConnection();
//创建通道
Channel channel = connection.createChannel();
//生产者绑定交换机 (交换机名称,交换机类型)
channel.exchangeDeclare(Config.FANOUT_EXCHANGE, Config.exchangeType.fanout);
System.out.println("发布订阅-生产者启动!");
String msg = "RabbitMQ发布订阅的消息22222";
System.out.println(msg);
//发送消息
channel.basicPublish(Config.FANOUT_EXCHANGE, "", null, msg.getBytes());
//关闭通道和连接
channel.close();
connection.close();
}
}
创建短信消费者、邮件消费者:
package com.google.util.pubsub;
import com.google.util.config.Config;
import com.google.util.MQConnectionUtils;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author wk
* @Description:扇形交换机 邮件消费者
* @date 2019/12/10 14:21
**/
public class ConsumerEmailFanout {
public static final String EMAIL_QUEUE = "EMAIL_QUEUE";
public static void main(String[] args) throws IOException, TimeoutException {
System.out.println("邮件消费者启动!");
//建立连接
Connection connection = MQConnectionUtils.newConnection();
//创建通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(EMAIL_QUEUE, false, false, false, null);
//消费者绑定交换机
channel.queueBind(EMAIL_QUEUE, Config.FANOUT_EXCHANGE, "");
DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("邮件消费者获取生产者的消息:" + new String(body, "UTF-8"));
}
};
//自动应答
channel.basicConsume(EMAIL_QUEUE, true, consumer);
}
}
package com.google.util.pubsub;
import com.google.util.config.Config;
import com.google.util.MQConnectionUtils;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author wk
* @Description:扇形交换机 消费者
* @date 2019/12/10 14:11
**/
public class ConsumerSmsFanout {
public static final String SMS_QUEUE = "SMS_QUEUE";
public static void main(String[] args) throws IOException, TimeoutException {
System.out.println("短信消费者启动!");
//建立连接
Connection connection = MQConnectionUtils.newConnection();
//创建通道
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(SMS_QUEUE, false, false, false, null);
//消费者队列绑定交换机
channel.queueBind(SMS_QUEUE, Config.FANOUT_EXCHANGE, "");
//消费监听消息
DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String msg = new String(body, "UTF-8");
System.out.println("短信消费者获取生产者消息:" + msg);
}
};
//自动应答
channel.basicConsume(SMS_QUEUE, true, consumer);
}
}