RabbitMQ-消息中间件

一、介绍

什么是MQ
MQ(Message Queue)消息队列,通过典型的 生产者 和 消费者 模型,生产者向消息队列中生产信息,消费者不断地从队列中获取信息,它们是异步的。

主流的MQ有RabbitMQ、ActiveMQ、kafka、阿里巴巴开发的RocketMQ等

默认端口号:15672

二、工作模式

**第一种模型(直连)——直连模式
**
在这里插入图片描述
P:生产者,也就是要发送消息的程序

C:消费者,消息的接受者,会一直等待消息到来

queue:消息队列,图中红色部分,可以缓存消息,生产者向其投递消息,消费者从其取出消息

第二种模型(work queue)(平均分配)——work模式
在这里插入图片描述
P:生产者,任务的发布者

C1:消费者1,领取任务并完成任务,假设完成速度较慢

C2:消费者2,领取任务并完成任务,假设完成速度较快

也可以

生产者将消息放入队列
消费者1,消费者2同时监听同一个队列,C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息
隐患:高并发情况下,默认会产生某一个消息被多个消费者共同使用,可以设置一个开关(syncronize) 保证一条消息只能被一个消费者使用

第三种模型(fanout 广播)——订阅模式
在这里插入图片描述
可以有多个消费者

每个消费者有自己的 queue(队列)

每个队列要绑定 exchange(交换机)

生产者发送消息到交换机,由交换机将消息发送给绑定过的所有队列(由交换机决定

第四种模型(Routing)——路由模式

在这里插入图片描述
P:生产者,向交换机发送消息,指定一个 RoutingKey

X:交换机,接收生产者消息,然后把消息传递给相应 RoutingKey 的队列

C1:消费者1,其所在队列指定了需要 RoutingKey 为 error 的消息

C2:消费者2,其所在队列制定了需要RoutingKey 为 info, error, warning 的消息
(生产者在生产好消息的时候,拿RoutingKey来锁定之后分配给哪个消费者 )

第五种——通配符模式
在这里插入图片描述
将路由键和某模式进行匹配,此时队列需要绑定在一个模式上,“#”匹配一个词或多个词,“*”只匹配一个词

第六种模式——RPC模式

在这里插入图片描述
首先客户端通过RPC向服务端发出请求

我这里有一堆东西需要你给我处理一下,correlation_id:这是我的请求标识,erply_to:你处理完过后把结果返回到这个队列中。

服务端拿到了请求,开始处理并返回

correlation_id:这是你的请求标识 ,原封不动的给你。 这时候客户端用自己的correlation_id与服务端返回的id进行对比。是我的,就接收。

三、在SpringBoot中使用

3.1 准备与配置

第一步:在pom.xml文件中添加依赖

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

第二步:配置application.yml

spring:
  rabbitmq:
    host: 192.168.115.100
    port: 5672
    username: prod
    password: 123456
    virtual-host: /prod

3.2 第一种模式——直连
生产者

@SpringBootTest(classes = RabbitmqSpringbootApplication.class)
@RunWith(SpringRunner.class)
public class TestRabbitMQ {

    // 注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    // HelloWorld模型测试
    @Test
    public void test(){
        rabbitTemplate.convertAndSend("hello","hello world"); // 队列名 消息
    }
}

消费者

@Component  // 默认持久化 非独占 不自动删除队列
@RabbitListener(queuesToDeclare = @Queue(value = "hello",durable = "false",autoDelete = "true"))
public class HelloConsumer {
    @RabbitHandler
    public void receive(String message){
        System.out.println("message:"+message);
    }
}

第二种模式——work模式

生产者

// work模型测试
@Test
public void testWork(){
    for(int i=1; i<=10; i++){
        rabbitTemplate.convertAndSend("work","work模型"+i);
    }
}

消费者

@Component
public class WorkConsumer {

    // 第一个消费者
    @RabbitListener(queuesToDeclare = @Queue("work"))
    public void receive1(String message){
        System.out.println("message1:"+message);
    }

    // 第二个消费者
    @RabbitListener(queuesToDeclare = @Queue("work"))
    public void receive2(String message){
        System.out.println("message2:"+message);
    }

}

第三种模式——fanout广播(订阅模式)

生产者

// fanout 广播模型测试
@Test
public void testFanout(){   // 交换机名 路由Key 消息
    rabbitTemplate.convertAndSend("logs","","Fanout模型发送的消息");
}

消费者

@Component
public class FanoutConsumer {
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue, // 创建临时队列 或者指定@Queue("name")
                    exchange = @Exchange(value = "logs",type = "fanout")// 绑定的交换机
            )
    })
    public void receive1(String message){
        System.out.println("message1:"+ message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue, // 创建临时队列 或者指定@Queue("name")
                    exchange = @Exchange(value = "logs",type = "fanout")// 绑定的交换机
            )
    })
    public void receive2(String message){
        System.out.println("message2:"+ message);
    }
}

第四种模型(Routing)——路由模式

生产者

// route 路由模式
@Test
public void testRoute(){
    rabbitTemplate.convertAndSend("direct_exchange","info","发送路由key为info的信息");
}

消费者

@Component
public class RouteConsumer {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue, // 创建临时队列
                    exchange = @Exchange(value = "direct_exchange", type = "direct"), // 指定交换机名称与类型
                    key = {"info","error","warning"} // 路由key
            )
    })
    public void receive1(String message){
        System.out.println("message1:"+message);
    }
}

第五种模型(Routing)——通配符模式

生产者

// Topic 动态路由 订阅模式
@Test
public void testTopic(){
    rabbitTemplate.convertAndSend("topic_exchange","banana.book","banana.book路由信息");
}

消费者

@Component
public class TopicConsumer {
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(type = "topic",name = "topic_exchange"),
                    key = {"banana.*"}
            )
    })
    public void receive1(String message){
        System.out.println(message);
    }
}

四、应用场景

4.1 异步处理

例如:用户注册后,利用消息队列分发任务(无需等待返回结果),同时发送邮件和短信验证(并行方式),提高处理的效率

4.2 应用解耦

例如:用户网购下单,订单系统通知库存系统,传统方式为订单系统直接调用库存系统接口。

但是如果库存系统出现故障,下单会失败。

为了这两个系统之间解耦,可以引入消息队列,订单系统向队列写入消息,库存系统向队列订阅消息。

这样一来,就算系统故障,也能保证消息不会丢失。

4.3 流量削峰

例如:秒杀商品活动,容易因为流量过大导致应用宕机。

可以在秒杀业务系统前加入消息队列,超过消息队列长度最大值的用户请求直接跳转到错误界面。

最后,系统根据消息队列中的请求信息再做处理。

来源: https://www.515code.com/posts/b6u1c1x0/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值