03:入门案例(狂神说RabbitMQ)

RabbitMQ入门案例 - Simple 简单模式

https://www.bilibili.com/video/BV1dX4y1V73G?p=44

实现步骤

  1. jdk1.8
  2. 构建一个 maven工程
  3. 导入 rabbitmq的 maven依赖
  4. 启动 rabbitmq-server服务
  5. 定义生产者
  6. 定义消费者
  7. 观察消息的在 rabbitmq-server服务中的进程

构建一个maven工程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xujgT7Cn-1615906714899)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210315175432636.png)]

导入依赖

java原生依赖

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.10.0</version>
</dependency>

第一种模型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f4gBVwbl-1615906714907)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210315191015917.png)]

在上图的模型中,有以下概念:

  1. 生产者,也就是要发送消息的程序
  2. 消费者:消息的接受者,会一直等待消息到来。
  3. 消息队列:图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。

生产者

//简单模式
public class Producer{
    //1.创建连接工厂
    ConnectionFactory connectionFactory = new ConnectionFactory();
    connectionFactory.setHost("10.15.0.9");
    connectionFactory.setPort(5672);
    connectionFactory.setUsername("admin");
    connectionFactory.setPassword("admin");
    connectionFactory.setVirtualHost("/");
    Connection connection = connectionFactory.newConnection("生产者");
    //2.创建通道
    Channel channel = connection.createChannel();
    //3.通过创建交换机,声明队列,绑定关系,路由key,发送消息和接受消息
    /*参数1: 是否持久化,非持久化消息会存盘吗?会存盘,但是会随着重启服务器而丢失
      参数2:是否独占队列 
      参数3:是否自动删除,随着最后一个消费者消息完毕消息以后是否把队列自动删除
  	  参数4:携带附属属性
    */
    String queueName = "queue1";
    channel.queueDeclare(queueName,false,false,false,null);
    //4.发送消息给队列queue
    /*参数1: 交换机
      参数2:队列、路由key
      参数3:消息的状态控制
  	  参数4:消息主题
    */
    //面试题:可以存在没有交换机的队列吗?不可能,虽然没有指定交换机但是一定会存在一个默认的交换机
    String message = "Hello";
    channel.basicPublish("",message, null,message.getBytes());
    //5.关闭
    channel.close();
    connection.close();
}

消费者

//简单模式
public class Consumer{
    //1.创建连接工厂
    ConnectionFactory connectionFactory = new ConnectionFactory();
    connectionFactory.setHost("10.15.0.9");
    connectionFactory.setPort(5672);
    connectionFactory.setUsername("admin");
    connectionFactory.setPassword("admin");
    connectionFactory.setVirtualHost("/");
    Connection connection = connectionFactory.newConnection("生产者");
    //2.创建通道
    Channel channel = connection.createChannel();
	//3.接受内容
    channel.basicConsume("queue1",true,new DefaultConsumer(){
        public void handle(String consumerTag, Delivery message) throws IOException {
          System.out.println(new String("收到消息是" + new String(meassage.getBody()),"UTF-8"));
        },new CancelCallback(){
            public void handle(String consumerTag) throws IOException {
                System.out.println("接受失败了");
        }
      });
    //4.关闭
    channel.close();
    connection.close();
}

什么是AMQP

什么是AMQP

AMQP全称:Advanced Message Queuing Protocol(高级消息队列协议)。是应用层协议的一个开发标准,为面向消息的中间件设计

AMQP生产者流转过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-78cQpQXh-1615906714913)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210315201857946.png)]

AMQP消费者流转过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JN1ruNmm-1615906714917)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210315201931747.png)]

RabbitMQ的核心组成部分

RabbitMQ的核心组成部分

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vNnCgBXe-1615906714921)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210315202655024.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RkPA3zzO-1615906714924)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210315202716740.png)]

RabbitMQ整体架构是什么样子的?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uDhG4Fcd-1615906714926)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210315203502277.png)]

RabbitMQ的运行流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QncWY0yx-1615906714928)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210315203556034.png)]

RabbitMQ支持的消息模型

在这里插入图片描述

在这里插入图片描述

  1. 简单模式 Simple
  2. 工作模式 Work
  3. 发布订阅模式
  4. 路由模式
  5. 主题 Topic模式
  6. 参数模式

RabbitMQ入门案例 - fanout 模式

RabbitMQ的模式之发布订阅模式

图解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GDumDZgf-1615906714931)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210315214316617.png)]

发布订阅模式的具体实现

  1. web操作查看视频
  2. 类型:fanout
  3. 特点:Fanout - 发布与订阅模式,是一种广播机制,它是没有路由 key的模式

生产者

//简单模式
public class Producer{
    //1.创建连接工厂
    ConnectionFactory connectionFactory = new ConnectionFactory();
    connectionFactory.setHost("10.15.0.9");
    connectionFactory.setPort(5672);
    connectionFactory.setUsername("admin");
    connectionFactory.setPassword("admin");
    connectionFactory.setVirtualHost("/");
    Connection connection = connectionFactory.newConnection("生产者");
    //2.创建通道
    Channel channel = connection.createChannel();
    //3.通过创建交换机,声明队列,绑定关系,路由key,发送消息和接受消息
    /*参数1: 是否持久化,非持久化消息会存盘吗?会存盘,但是会随着重启服务器而丢失
      参数2:是否独占队列 
      参数3:是否自动删除,随着最后一个消费者消息完毕消息以后是否把队列自动删除
  	  参数4:携带附属属性
    */
    String queueName = "queue1";
    channel.queueDeclare(queueName,false,false,false,null);
    //4.发送消息给队列queue
    /*参数1: 交换机
      参数2:队列、路由key
      参数3:消息的状态控制
  	  参数4:消息主题
    */
    //面试题:可以存在没有交换机的队列吗?不可能,虽然没有指定交换机但是一定会存在一个默认的交换机
    String message = "Hello";
    //5.准备交换机
    String exchangeName = "fanout-exchange";
    //6.定义路由key
    String routeKey = "";
    //7.指定交换机的类型
    String type = "fanout";
    channel.basicPublish(exchangeName,routeKey, null,message.getBytes());
    //8.关闭
    channel.close();
    connection.close();
}

消费者

代码一样,使用线程启动测试而已!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uud19sfq-1615906714934)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210315222738258.png)]

此处没有通过代码去绑定交换机和队列,而是通过可视化界面去绑定的!

RabbitMQ入门案例 - Direct 模式

//6.定义路由key
String routeKey = "email";
//7.指定交换机的类型
String type = "direct";
channel.basicPublish(exchangeName,routeKey, null,message.getBytes());

RabbitMQ入门案例 - Topic 模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dV1z3Um9-1615906714937)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210315223544793.png)]

//6.定义路由key
String routeKey = "com.order.test.xxx";
//7.指定交换机的类型
String type = "direct";
channel.basicPublish(exchangeName,routeKey, null,message.getBytes());

代码创建及绑定

//5.准备交换机
String exchangeName = "direct_message_exchange";
String exchangeType = "direct";
//如果你用界面把queue和exchange的关系先绑定话,代码就不需要在编写这些声明代码可以让代码变得更简洁
//如果用代码的方式去声明,我们要学习一下
//6.声明交换机 所谓的持久化就是指,交换机会不会随着服务器重启造成丢失
channel.exchangeDeclare(exchangeName,exchangeType,true);

//7.声明队列
channel.queueDeclare("queue5",true,false,false,null);
channel.queueDeclare("queue6",true,false,false,null);
channel.queueDeclare("queue7",true,false,false,null);

//8.绑定队列和交换机的关系
channel.queueBind("queue5",exchangeName,"order");
channel.queueBind("queue6",exchangeName,"order");
channel.queueBind("queue7",exchangeName,"course");

channel.basicPublish(exchangeName,course, null,message.getBytes());

RabbitMQ入门案例 - Work模式

Work模式轮询模式(Round-Robin)

图解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SIuV8TNN-1615906714938)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210316085612814.png)]

当有多个消费者时,我们的消息会被哪个消费者消费呢,我们又该如何均衡消费者消费信息的多少呢?

主要有两种模式:

  1. 轮询模式的分发:一个消费者一条,按均分配
  2. 公平分发:根据消费者的消费能力进行公平分发,处理快的处理的多,处理慢的处理的少;按劳分配

生产者

跟简单模式一样!

消费者

创建两个一样的!

Work模式公平分发模式

生产者

跟简单模式一样!

消费者

//简单模式
public class Consumer{
	//3.接受内容
    //指标定义出来
    channel.basicQos(1);
    channel.basicConsume("queue1",false,new DefaultConsumer(){
        public void handle(String consumerTag, Delivery message) throws IOException {
          System.out.println(new String("收到消息是" + new String(meassage.getBody()),"UTF-8"));
          //改成手动应答
          channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
        },new CancelCallback(){
            public void handle(String consumerTag) throws IOException {
                System.out.println("接受失败了");
        }
      });
    //4.关闭
    channel.close();
    connection.close();
}

创建两个一样的!

RabbitMQ使用场景

解耦、削峰、异步

同步异步的问题(串行)

串行方式:将订单信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AGZTYLFK-1615906714941)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210316142034691.png)]

public void makeOrder(){
    //1.发送订单
    //2.发送短信服务
    //3.发送email服务
    //4.发送app服务
}

并行方式 异步线程池

并行方式:将订单信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pIt2MO27-1615906714943)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210316142350905.png)]

public void test(){
    //异步
    theadpool.submit(new Callable<Object>{
        //1.发送短信服务
    })
    //异步
    theadpool.submit(new Callable<Object>{
        //2.
    })
    //异步
    theadpool.submit(new Callable<Object>{
        //3.
    })
    //异步
    theadpool.submit(new Callable<Object>{
        //4.
    })
}

存在问题

  1. 耦合度高
  2. 需要自己写线程池自己维护成本太高
  3. 出现了消息可能会丢失,需要你自己做消息补偿
  4. 如何保证消息的可靠性你自己写
  5. 如果服务器承载不了,你需要自己去写高可用

异步消息队列的方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UAtvuZLE-1615906714945)(C:\Users\VULCAN\AppData\Roaming\Typora\typora-user-images\image-20210316142702780.png)]

好处:

  1. 完全解耦,用 MQ建立桥接
  2. 有独立的线程池和运行模型
  3. 出现了消息可能会丢失,MQ有持久化功能
  4. 如何保证消息的可靠性,死信队列和消息转移等
  5. 如果服务器承载不了,你需要自己去写高可用,HA镜像模型高可用

按照以上约定,用户的响应时间相当于是订单信息写入数据库的时间,也就是50毫秒。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50毫秒。因此架构改变后,系统的吞吐量提高到每秒20QPS。比串行提高了3倍,比并行提高了两倍

高内聚,低耦合

在这里插入图片描述

好处:

  1. 完全解耦,用 MQ建立桥接
  2. 有独立的线程池和运行模型
  3. 出现了消息可能会丢失,MQ有持久化功能
  4. 如何保证消息的可靠性,死信队列和消息转移等
  5. 如果服务器承载不了,你需要自己去写高可用,HA镜像模型高可用

按照以上约定,用户的响应时间相当于是订单信息写入数据库的时间,也就是50毫秒。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50毫秒。因此架构改变后,系统的吞吐量提高到每秒20QPS。比串行提高了3倍,比并行提高了两倍

高内聚,低耦合

[外链图片转存中…(img-kyL4Icya-1615906714948)]

[外链图片转存中…(img-bqSYfEx2-1615906714950)]

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值