SpringBoot互联网项目开发(十一):RabbitMQ消息队列

1.为什么使用消息队列?
  • 系统解耦:在分布式环境中,可能有A、B、C、D….等多个系统,A直接调用B提供的服务接口,当A系统修改时,可能需要B也跟着修改,这样耦合性比较强。MQ可以解耦这样的场景
  • 流量销峰:在电商抢购活动中,商品可能几秒钟就被抢购完,但是系统或数据库无法在几秒内处理所有请求,大量请求或许会让数据库直接崩溃,把请求压到队列中,消费者有序的处理队列中的请求
  • 稳定性:队列有确认机制,当消费者进程异常时,也就是该消息还没有被确认消费,那么其他消费进程可再次处理该消息
2.RabbitMQ 特点
  • 可靠性:RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认
  • 消息集群:多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker
  • 高可用:队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。
  • 多语言客户端:RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等
  • 管理界面:RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面

消息默认存储在磁盘上,磁盘的处理能力是有限,对于大流量、高并发场景,RabbitMQ有内存模式,内存可以高速处理消息,但是需要磁盘模式配合,防止消息丢失,关于RabbitMQ集群方面的,请参考 RabbitMQ + Haproxy 高可用队列集群

3.RabbitMQ 中的概念模型

生产者(producer)创建消息,然后发布到队列(queue)中,消费者(consumer)订阅某个队列,最后将消息发送到监听的消费者,可以有多个消费者,消息会被平均分摊给多个消费者进行处理
这里写图片描述

RabbitMQ有 4 个重要概念,分别为:虚拟主机,交换机,队列,和绑定。

  • 虚拟主机:一个虚拟主机持有一组交换机、队列和绑定。为什么需要多个虚拟主机呢?很简单,RabbitMQ当中,用户只能在虚拟主机的粒度进行权限控制。 因此,如果需要禁止A组访问B组的交换机/队列/绑定,必须为A和B分别创建一个虚拟主机。每一个RabbitMQ服务器都有一个默认的虚拟主机“/”。
  • 交换机:Exchange 用于转发消息,但是它不会做存储 ,如果没有 Queue bind 到 Exchange 的话,它会直接丢弃掉 Producer 发送过来的消息。
    这里有一个比较重要的概念:路由键 。消息到交换机的时候,交互机会转发到对应的队列中,那么究竟转发到哪个队列,就要根据该路由键。
  • 绑定:也就是交换机需要和队列相绑定,这其中如上图所示,是多对多的关系。

RabbitMQ常用的交换机Exchange Type有四种:fanout、direct、topic、headers。

  fanout:广播模式,一对多关系,转发消息到所有绑定队列。

  direct:发布订阅模式,一对一关系,把消息投递到那些binding key与routing key完全匹配的队列中。

  topic:发布订阅模式,一对一关系,按规则转发消息,将消息路由到binding key与routing key模式匹配的队列中。

  headers:设置header attribute参数类型的交换机。
3.SrpingBoot集成 RabbitMQ

1).添加引用依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2).添加配置,rabbitmq的安装地址、端口以及账户信息,没有rabbitmq环境的可以参考 RabbitMQ安装教程

spring.rabbitmq.host=192.168.68.128
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin
spring.rabbitmq.virtual-host=zy_host

3).队列配置

@Configuration
public class RabbitConfig {
    //定义一个名称为hello的队列
    @Bean
    public Queue HelloQueue(){
        return new Queue("hello");
    }
}

4).生产者,AmqpTemplate是springboot 提供的默认实现

@Component
public class HelloSender {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send(String queueName, String message){
        rabbitTemplate.convertAndSend(queueName,message);
    }
}

5).消费者,监听队列,处理消息

@Component
@RabbitListener(queues = "hello")
public class HelloReceiver {

    @RabbitHandler
    public void process(String context){
        System.out.println("Receiver : " + context);
    }
}

6).测试,生产者与消费者的queue name必须一致,不然无法接收

@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitMQTest {
    @Autowired
    private HelloSender helloSender;

    @Test
    public void sendMessage(){
        helloSender.send("hello","你好,我要向队列发送消息1...");
    }
}

运行测试方法时,可以在rabbitmq管理后台看到,hello队列会自动创建

扫描二维码关注公众号,回复: 2660289 查看本文章

这里写图片描述

这里写图片描述

还可以测试一对多,多对多关系,看队列是怎么消费的
多个生成者

@Test
public void sendManyMessage(){
    for (int i=0;i<5;i++){
        helloSender.send("hello","你好,我要向队列发送消息1..."+i);
        helloSender.send("hello","你好,我要向队列发送消息2..."+i);
    }
}

多个消费者,监听 hello 队列
这里写图片描述

运行,查看结果:多个消费者均匀的消费多个消息
这里写图片描述

本篇是抛砖引玉,介绍了一些概念和简单使用,它的高级使用,请参考下面:
centos7下RabbitMQ安装教程
RabbitMQ + Haproxy 高可用队列集群
RabbitMQ 延迟队列的实现

猜你喜欢

转载自blog.csdn.net/zhuyu19911016520/article/details/81532434
今日推荐