为什么需要MQ???

异步处理:

场景:

用户注册后,需要发注册邮件和注册短信,传统的做法有两种 1.串行的方式 2.并行的方式`

用户注册-发送注册邮箱-发送注册短信都完成之后才结束返回给客户端

邮件,短信并不是必须的,它只是一个通知,而这种做法让客户端等待没有必要等待的东西.

耗时150ms

并行:

将注册信息写入数据库后,发送邮件的同时,发送短信,以上三个任务完成后,返回给客户端,并行的方式能提高处理的时间

耗时100ms

消息队列:

假设三个业务节点分别使用50ms,串行方式使用时间150ms,并行使用时间100ms。虽然并行已经提高的处理时间,但是,

前面说过,邮件和短信对我正常的使用网站没有任何影响,客户端没有必要等着其发送完成才显示注册成功,应该是写入
数据库后就返回.
`消息队列`: 引入消息队列后,把发送邮件,短信不是必须的业务逻辑异步处理

应用解耦:

场景:

双11是购物狂节,用户下单后,订单系统需要通知库存系统,传统的做法就是订单系统调用库存系统的接口

注意:当库存系统出现故障时,订单就会失败。订单系统和库存系统高耦合

引入消息队列

`订单系统:`用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。

库存系统:`订阅下单的消息,获取下单消息,进行库操作。  就算库存系统出现故障,消息队列也能保证消息的可靠投递,
不会导致消息丢失.

流量削峰:

场景:

秒杀活动,一般会因为流量过大,导致应用挂掉,为了解决这个问题,一般在应用前端加入消息队列。  

1.用户的请求,服务器收到之后,首先写入消息队列,加入消息队列长度超过最大值,则直接抛弃用户请求或跳转到错误页面.

2.秒杀业务根据消息队列中的请求信息,再做后续处理.


 起到的作用就是:

1.可以控制活动人数,超过此一定阀值的订单直接丢弃
2.可以缓解短时间的高流量压垮应用(应用程序按自己的最大处理能力获取订单)

springboot- 配置文件:

spring.application.name=springboot_rabbitmq
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=quan
spring.rabbitmq.password=admin
spring.rabbitmq.virtual-host=quan
server.port=9898

RabbitMQ介绍

https://www.cnblogs.com/java-quan/p/13560266.html

第一种模型:直连

生产者:

   @Autowired
RabbitTemplate template; @Test
void producer1() {
template.convertAndSend("hello","hello-rabbit");
}

消费者:

@Component
@RabbitListener(queuesToDeclare = @Queue("hello"))
public class Customer {
@RabbitHandler
public void remsg(String msg){
System.out.println("message== "+msg);
}
}

第二种模型:任务模型(work quene)

producer;

    @Autowired
RabbitTemplate template; @Test
void producer2() {
for (int i = 0;i<10;i++){
template.convertAndSend("work",i+"hello-rabbit");
System.out.println(i);
}

customer:

@Component
public class Customer2 {
@RabbitListener(queuesToDeclare = @Queue("work"))
public void receive1(String msg){
System.out.println("work-msg1= " +msg);
} @RabbitListener(queuesToDeclare = @Queue("work"))
public void receive2(String msg){
System.out.println("work-msg2= " +msg);
}
}

结果:

     * work-msg1= 1hello-rabbit
* work-msg2= 0hello-rabbit
* work-msg1= 5hello-rabbit
* work-msg2= 4hello-rabbit
* work-msg1= 9hello-rabbit
* work-msg2= 8hello-rabbit
默认在Spring AMQP实现中Work这种方式就是公平调度,如果需要实现能者多劳需要额外配置`

第三种模型--广播

producer:

    @Autowired
RabbitTemplate template; @Test
void producer3() {
template.convertAndSend("logs2","","广播广播");
}

customer:

@Component
public class Customer3 {
@RabbitListener(bindings = @QueueBinding(
value = @Queue,
exchange = @Exchange(name = "logs2",type = "fanout")
)
)
public void receive1(String msg){
System.out.println("msg1= " +msg);
} @RabbitListener(bindings = @QueueBinding(
value = @Queue,//c创造临时队列
exchange = @Exchange(name = "logs2",type = "fanout")//绑定交换机类型
)
)
public void receive2(String msg){
System.out.println("msg2= " +msg);
}
}

结果:

//        msg2= 广播广播
// msg1= 广播广播

第四种模式:Routing-订阅模式中的-直连(direct)

producer:

    @Autowired
RabbitTemplate template; @Test
void producer4() {
template.convertAndSend("directs","error","广播广播");
template.convertAndSend("directs","info","广播广播");
template.convertAndSend("directs","debug","广播广播");
}

customer:

@Component
public class Customer4 {
@RabbitListener(bindings = @QueueBinding(
value = @Queue,
key = {"info","error","debug"},
exchange = @Exchange(name = "directs",type = "direct")
)
)
public void receive1(String msg){
System.out.println("msg1-info-error-debug= " +msg);
} @RabbitListener(bindings = @QueueBinding(
value = @Queue,//c创造临时队列
key = {"info"},
exchange = @Exchange(name = "directs",type = "direct")//绑定交换机类型
)
)
public void receive2(String msg){
System.out.println("msg2-info= " +msg);
} @RabbitListener(bindings = @QueueBinding(
value = @Queue,//c创造临时队列
key = {"error"},
exchange = @Exchange(name = "directs",type = "direct")//绑定交换机类型
)
)
public void receive3(String msg){
System.out.println("msg3-error= " +msg);
} }

结果:

/**
* msg3-error= 广播广播
* msg2-info= 广播广播
* msg1-info-error-debug= 广播广播
* msg1-info-error-debug= 广播广播
* msg1-info-error-debug= 广播广播
*/

Routing的订阅模式--topic:

producer

 @Test
void producer5() {
template.convertAndSend("topics", "user.quan", "user.quan广播广播");
template.convertAndSend("topics", "user.quan.all", "user.quan.all广播广播"); }

customer

@Component
public class Customer5 {
@RabbitListener(bindings = @QueueBinding(
value = @Queue,
key = {"user.*"},
exchange = @Exchange(name = "topics",type = "topic")
)
)
public void receive1(String msg){
System.out.println("msg1-info-error-debug= " +msg);
} @RabbitListener(bindings = @QueueBinding(
value = @Queue,//c创造临时队列
key = {"user.#"},
exchange = @Exchange(name = "topics",type = "topic")//绑定交换机类型
)
)
public void receive2(String msg){
System.out.println("msg2-info= " +msg);
} }

结果:

        /**
* msg2-info= user.quan广播广播
* msg1-info-error-debug= user.quan广播广播
* msg2-info= user.quan.all广播广播
*/

spring-boot-learning-RabbitMQ的更多相关文章

  1. 85. Spring Boot集成RabbitMQ【从零开始学Spring Boot】

    这一节我们介绍下Spring Boot整合RabbitMQ,对于RabbitMQ这里不过多的介绍,大家可以参考网络上的资源进行安装配置,本节重点是告诉大家如何在Spring Boot中使用Rabbit ...

  2. Spring Boot (十三): Spring Boot 整合 RabbitMQ

    1. 前言 RabbitMQ 是一个消息队列,说到消息队列,大家可能多多少少有听过,它主要的功能是用来实现应用服务的异步与解耦,同时也能起到削峰填谷.消息分发的作用. 消息队列在比较主要的一个作用是用 ...

  3. Spring Boot 集成 RabbitMQ 实战

    Spring Boot 集成 RabbitMQ 实战 特别说明: 本文主要参考了程序员 DD 的博客文章<Spring Boot中使用RabbitMQ>,在此向原作者表示感谢. Mac 上 ...

  4. Spring Boot 整合 rabbitmq

    一.消息中间件的应用场景 异步处理 场景:用户注册,信息写入数据库后,需要给用户发送注册成功的邮件,再发送注册成功的邮件. 1.同步调用:注册成功后,顺序执行发送邮件方法,发送短信方法,最后响应用户 ...

  5. Spring Boot 实现 RabbitMQ 延迟消费和延迟重试队列

    本文主要摘录自:详细介绍Spring Boot + RabbitMQ实现延迟队列 并增加了自己的一些理解,记录下来,以便日后查阅. 项目源码: spring-boot-rabbitmq-delay-q ...

  6. spring boot整合RabbitMQ(Direct模式)

    springboot集成RabbitMQ非常简单,如果只是简单的使用配置非常少,springboot提供了spring-boot-starter-amqp项目对消息各种支持. Direct Excha ...

  7. spring boot集成RabbitMQ

    原文:https://www.jianshu.com/p/e1258c004314 RabbitMQ作为AMQP的代表性产品,在项目中大量使用.结合现在主流的spring boot,极大简化了开发过程 ...

  8. Spring boot集成RabbitMQ(山东数漫江湖)

    RabbitMQ简介 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出 ...

  9. Spring Boot 集成RabbitMQ

    在Spring Boot中整合RabbitMQ是非常容易的,通过在Spring Boot应用中整合RabbitMQ,实现一个简单的发送.接收消息的例子. 首先需要启动RabbitMQ服务,并且add一 ...

  10. Spring Boot整合Rabbitmq

    Spring Boot应用中整合RabbitMQ,并实现一个简单的发送.接收消息的例子来对RabbitMQ有一个直观的感受和理解. 在Spring Boot中整合RabbitMQ是一件非常容易的事,因 ...

随机推荐

  1. 攻防世界-Crypto高手进阶区部分Writeup

    1.flag_in_your_hand && flag_in_your_hand1 下载,解压后 打开index文件,直接点击get flag错误,输入其他点击也同样 打开js文件,在 ...

  2. 一文带你盘点市场上主流的BI产品主要有哪些

    ​随着时代的发展,商业智能使数据分析和数据可视化的门槛不断降低,使得企业各级人员都能进行数据分析,从而加深业务洞察,推动企业发展.而在数据分析领域,BI产品发挥了十分重要的作用. 市场需求变化日益频繁 ...

  3. Java刷题时常用的标准库数据结构和相应算法

    目录 一.线性表(广义的数组) 1. 数组 一维数组的定义和初始化 二维数组的定义和初始化 Arrays工具类的一些常用方法 2. List接口容器 对象的构建 读写和插入删除数据 排序 反转数组 二 ...

  4. 【C#基础概念】程序集清单

    .NET Core 程序集(模块)还包含描述程序集本身的元数据,我们称之为清单.清单记录了当前程序集正常运行所需的所有外部程序集.程序集的版本号.版权信息.模块 .资源(图片 xml等)等.与类型元数 ...

  5. 【C#基础概念】函数参数默认值和指定传参和方法参数

    函数参数默认值和指定传参 最近在编写代码时发现介绍C#参数默认值不能像PL/SQL那样直接设置default,网上也没有太多详细的资料,自己琢磨并试验后整理成果如下: C#允许在函数声明部分定义默认值 ...

  6. Java:Path与Paths

    0.说明 用于读Path操作的接口(Path)与实现类(Paths) 1.模块:java.nio.file.Path.java.nio.file.Paths 2.方法 2.1.Paths 只有两个静态 ...

  7. Leaflet:Map类属性及方法

    1.初始化 L.map(<String> id , options ?) //用地图div的id创建 L.map(<HTMLElement>el , options?) //用 ...

  8. SQL Server--插入一天数据返回ID值

    这里将该功能写成了一个存储过程, 本来只写Insert的话,返回1,即影响的行数,该数据没太大应用意义. 想在Insert的基础上,返回新添加的这条数据的ID,两种方法: 1 .添加第17行的Sele ...

  9. go RWMutex 的实现

    Overview go 里面的 rwlock 是 write preferred 的,可以避免写锁饥饿. 读锁和写锁按照先来后到的规则持有锁,一旦有协程持有了写锁,后面的协程只能在写锁被释放后才能得到 ...

  10. mysql中MyISAM与InooDB存储引擎的区别

    MyISAM存储引擎特点 不支持事务 表级锁定 读写相互阻塞,写入不能读,读时不能写 只缓存索引 不支持外键约束 不支持聚簇索引 读取数据较快,占用资源较少 不支持MVCC(多版本并发控制机制)高并发 ...