简单模式:
- 一个生产者,一个队列,一个消费者
Config:
/**
* @author Fly_Roushan
* @date 2021/8/23
*/
@Configuration
public class RabbitConfig {
/**
* 简单模式不需要绑定交换机
*
* @return
*/
@Bean
public Queue simpleQueue() {
return new Queue(RabbitConst.SIMPLE_QUEUE, true);
}
}
Producer:
/**
* @author Fly_Roushan
* @date 2021/8/23
*/
@Component
public class Producer {
private static final Logger LOGGER = LoggerFactory.getLogger(Producer.class);
@Autowired
private AmqpTemplate amqpTemplate;
/**
* Simple Mode
*
*/
public void sendMessage() {
String data = "Simple Test";
LOGGER.info("[Producer] Send: {}", data);
amqpTemplate.convertAndSend(RabbitConst.SIMPLE_QUEUE, data);
}
}
Consumer:
/**
* @author Fly_Roushan
* @date 2021/8/23
*/
@Component
public class Consumer {
private static final Logger LOGGER = LoggerFactory.getLogger(Consumer.class);
@RabbitListener(queues = RabbitConst.SIMPLE_QUEUE)
@RabbitHandler
public void simpleConsumer(String data, Channel channel, Message message) {
LOGGER.info("[Consumer] Consume: {}", data);
}
}
结果:
工作模式:
- 一个生产者,一个队列,多个消费者
- 消费时采用轮询的方式
Config:
/**
* 工作模式不需要绑定交换机
*
* @return
*/
@Bean
public Queue workQueue() {
return new Queue(RabbitConst.WORK_QUEUE, true);
}
Producer:
/**
* Work Mode
*/
public void workMessage() {
String data = "Work Test";
LOGGER.info("[Producer] Send: {}", data);
amqpTemplate.convertAndSend(RabbitConst.WORK_QUEUE, data);
}
Consumer:
@RabbitListener(queues = RabbitConst.WORK_QUEUE)
@RabbitHandler
public void workConsumer1(String data, Channel channel, Message message) {
LOGGER.info("[Consumer] Consume 1: {}", data);
ack(channel, message);
}
@RabbitListener(queues = RabbitConst.WORK_QUEUE)
@RabbitHandler
public void workConsumer2(String data, Channel channel, Message message) {
LOGGER.info("[Consumer] Consume 2: {}", data);
ack(channel, message);
}
结果:
订阅模式(fanout):
- 一个生产者,一个交换机,多个队列,多个消费者
- 一个队列,可以使用多个消费者来进行轮询消费
- 所有的队列都会接受到生产者的消息
Config:
/**
* 用于绑定fanout交换机
*
* @return
*/
@Bean
public Queue fanoutQueue() {
return new Queue(RabbitConst.FANOUT_QUEUE, true);
}
/**
* 订阅模式需要声明特别的交换机
*
* @return
*/
@Bean
public FanoutExchange fanoutExchange() {
return new FanoutExchange(RabbitConst.FANOUT_EXCHANGE);
}
/**
* 根据实际需求绑定到fanout交换机
*
* @return
*/
@Bean
public Binding bandwidthFanout() {
return BindingBuilder.bind(fanoutQueue()).to(fanoutExchange());
}
Producer:
/**
* Fanout Mode
* 这里不用指定队列,也就是RoutingKey,只需要指定对哪个交换机发送消息即可
*/
public void fanoutMessage() {
String data = "Fanout Test";
LOGGER.info("[Producer] Send: {}", data);
amqpTemplate.convertAndSend(RabbitConst.FANOUT_EXCHANGE, null, data);
}
Consumer:
/**
* 简单说一下,这里使用的是随机队列。
* 队列在有消费者声明的时候存在,没有就会自动消失。
*
* @param data
* @param channel
* @param message
*/
@RabbitListener(bindings = @QueueBinding(value = @Queue(), exchange = @Exchange(value = RabbitConst.FANOUT_EXCHANGE, type = ExchangeTypes.FANOUT)))
@RabbitHandler
public void fanoutConsumer1(String data, Channel channel, Message message) {
LOGGER.info("[Consumer] Fanout Consume 1: {}", data);
ack(channel, message);
}
@RabbitListener(bindings = @QueueBinding(value = @Queue(), exchange = @Exchange(value = RabbitConst.FANOUT_EXCHANGE, type = ExchangeTypes.FANOUT)))
@RabbitHandler
public void fanoutConsumer2(String data, Channel channel, Message message) {
LOGGER.info("[Consumer] Fanout Consume 2: {}", data);
ack(channel, message);
}
@RabbitListener(queues = RabbitConst.FANOUT_QUEUE)
@RabbitHandler
public void fanoutConsumer3(String data, Channel channel, Message message) {
LOGGER.info("[Consumer] Fanout Consume 3: {}", data);
ack(channel, message);
}
结果:
路由模式(direct):
- 一个生产者,一个交换机,多个队列
- 消息发送给完全匹配RoutingKey的队列
- 一个队列可以绑定多个RoutingKey
Config:
/**
* 一个平平无奇的Queue
*
* @return
*/
@Bean
public Queue directQueue1() {
return new Queue(RabbitConst.DIRECT_QUEUE_1);
}
/**
* 一个平平无奇的Queue
*
* @return
*/
@Bean
public Queue directQueue2() {
return new Queue(RabbitConst.DIRECT_QUEUE_2);
}
/**
* 声明对应交换机
*
* @return
*/
@Bean
public DirectExchange directExchange() {
return new DirectExchange(RabbitConst.DIRECT_EXCHANGE);
}
/**
* 绑定三连
* 一个Queue, 一个Routing Key
*
* @return
*/
@Bean
public Binding directBinding1() {
return BindingBuilder.bind(directQueue1()).to(directExchange()).with(RabbitConst.DIRECT_KEY_1);
}
/**
* 一个Queue, 两个Routing Key
* 队列相同,with方法那里的RoutingKey不同
*
* @return
*/
@Bean
public Binding directBinding2() {
return BindingBuilder.bind(directQueue2()).to(directExchange()).with(RabbitConst.DIRECT_KEY_2);
}
@Bean
public Binding directBinding3() {
return BindingBuilder.bind(directQueue2()).to(directExchange()).with(RabbitConst.DIRECT_KEY_3);
}
Producer:
/**
* Direct Mode
*
* @param routingKey
*/
public void directMessage(String routingKey) {
String data = "Direct Test " + routingKey;
LOGGER.info("[Producer] Send: {}", data);
amqpTemplate.convertAndSend(RabbitConst.DIRECT_EXCHANGE, routingKey, data);
}
Consumer:
@RabbitListener(queues = RabbitConst.DIRECT_QUEUE_1)
@RabbitHandler
public void directConsumer1(String data, Channel channel, Message message) {
LOGGER.info("[Consumer] Direct Consume 1: {}", data);
ack(channel, message);
}
@RabbitListener(queues = RabbitConst.DIRECT_QUEUE_2)
@RabbitHandler
public void directConsumer2(String data, Channel channel, Message message) {
LOGGER.info("[Consumer] Direct Consume 2: {}", data);
ack(channel, message);
}
结果:
主题模式(topic):
- 一个生产者,一个交换机,多个队列
- 消息发送给满足匹配规则的队列
- 一个队列可以绑定多个RoutingKey
Config:
/**
* 平平无奇的队列
*/
@Bean
public Queue topicQueue() {
return new Queue(RabbitConst.TOPIC_QUEUE);
}
/**
* with输入匹配规则
* 匹配规则:
* *代表一个单词
* #代表一个或多个单词
* *和#都可以代表任意字符或空
* 多个字符用.连接
*
* eg.
* TOPIC.*.TEST 可以匹配 TOPIC.TEST TOPIC.AA.TEST 不能匹配TOPIC.AA.BB.TEST
* TOPIC.#.TEST 可以匹配 TOPIC.TEST TOPIC.AA.TEST TOPIC.AA.BB.TEST
*
* @return
*/
@Bean
public Binding topicBinding() {
return BindingBuilder.bind(topicQueue()).to(topicExchange()).with("TOPIC.#.TEST");
}
Producer:
/**
* Topic Mode
*
* @param routingKey
*/
public void topicMessage(String routingKey) {
String data = "Topic Test " + routingKey;
LOGGER.info("[Producer] Send: {}", data);
amqpTemplate.convertAndSend(RabbitConst.TOPIC_EXCHANGE, routingKey, data);
}
Consumer:
@RabbitListener(queues = RabbitConst.TOPIC_QUEUE)
@RabbitHandler
public void topicConsumer(String data, Channel channel, Message message) {
LOGGER.info("[Consumer] Topic Consume: {}", data);
ack(channel, message);
}
结果:
总结:
- 在我看来,工作模式和简单模式更像是针对队列的处理,在其他模式中也适用,广播时,也可以为一个队列来准备多个消费者分担压力。
- 传递对象链接:https://blog.csdn.net/qq_43010427/article/details/119827784
如有不准确之处,欢迎大家指出~