zoukankan      html  css  js  c++  java
  • RabbitMQ学习总结

    RabbitMQ

    1.MQ引言

    1.1什么是MQ

    MQ(Message Quene): 翻译为消息队列,通过典型的生产者和消费者模型,生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的,而且只关心消息的发送和接收,没有业务逻辑的侵入,轻松的实现系统间解耦。别名为"消息中间件",通过利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。
    

    1.2MQ种类

    当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴巴自主开发`RocketMQ`等。
    

    1.3不同MQ的特点

    1.ActiveMQ
    ActiveMQ是Apache出品,是最流行的,能力强劲的开源消息总线。它是一个完全支持JMS规范的的消息中间件。丰富的API,多种集群架构模式让ActiveMQ在业界成为老牌的消息中间件,在中小型企业颇受欢迎!
    
    2.Kafka
    Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。
    
    3.RocketMQ
    RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。
    
    4.RabbitMQ
    RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
    
    tip:RabbitMQ比Kafka可靠,Kafka更适合IO高吞吐的处理,一般应用在大数据日志处理或对实时性(少量延迟),可靠性(少量丢数据)要求稍低的场景使用,比如ELK日志收集。
    		
    

    2.RabbitMQ的安装(省略)

    3.RabbitMQ常用模型

    消息模型总览:

    img

    img

    3.1直连模型

    img

    在上图的模型中,有以下概念:
    P:生产者,也就是要发送消息的程序
    C:消费者:消息的接受者,会一直等待消息到来。
    queue:消息队列,图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。
    

    3.2work queue模型

    img

    Work queues,也被称为(Task queues),任务模型。当消息处理比较耗时的时候,可能生产消息的速度会远远大于消息的消费速度。长此以往,消息就会堆积越来越多,无法及时处理。此时就可以使用work模型:让多个消费者绑定到一个队列,共同消费队列中的消息。队列中的消息一旦消费,就会消失,因此任务是不会被重复执行的。
    参与角色:
    P:生产者:任务的发布者
    C1:消费者-1,领取任务并且完成任务,假设完成速度较慢
    C2:消费者-2:领取任务并完成任务,假设完成速度快
    

    3.3fanout模型

    fanout 扇出 也称为广播
    

    img

    在广播模式下,消息发送流程是这样的:
    可以有多个消费者;
    每个消费者有自己的queue(队列);
    每个队列都要绑定到Exchange(交换机);
    生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定;
    交换机把消息发送给绑定过的所有队列;
    队列的消费者都能拿到消息。实现一条消息被多个消费者消费;
    

    3.4Routing-Direct(直连)

    img

    在fanout模式中,一条消息,会被所有订阅的队列都消费。但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。
    
    在Direct模型下:
    队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key)
    消息的发送方在向Exchange发送消息时,也必须指定消息的RoutingKey。
    Exchange不再把消息交给每一个绑定的队列,而是根据消息的RoutingKey进行判断,只有队列的Routingkey与消息的Routing key完全一致,才会接收到消息。
    
    P:生产者,向Exchange发送消息,发送消息时,会指定一个routing key。
    X:Exchange(交换机),接收生产者的消息,然后把消息递交给 与routing key完全匹配的队列
    C1:消费者,其所在队列指定了需要routing key 为 error 的消息
    C2:消费者,其所在队列指定了需要routing key 为 info、error、warning 的消息
    

    3.4Routing-Topic(动态路由/按主题划分)

    Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key的时候使用通配符!这种模型Routingkey一般都是由一个或多个单词组成,多个单词之间以”.”分割,例如:item.insert
    

    img

    # 统配符
    		* (star) can substitute for exactly one word.    //匹配不多不少恰好1个单词
    		# (hash) can substitute for zero or more words.  //匹配一个或多个单词
    # 如:
    		audit.#   //匹配audit.irs.corporate或者 audit.irs 等
             audit.*   //只能匹配 audit.irs
    

    4.springboot集成RabbitMQ

    4.1 搭建初始环境

    4.1.1导入依赖
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    
    4.1.2配置yml文件
    spring:
      application:
        name: springboot_rabbitmq
      rabbitmq:
        host: 10.15.0.9 //虚拟机或服务器ip
        port: 5672	//默认端口
        username: ems //自己创建的用户
        password: 123 //自己创建的密码
        virtual-host: /ems  //自己创建的virtual-host
    
    4.1.3hello world模型示例
    //生产者
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Test
    public void testHello(){
      rabbitTemplate.convertAndSend("hello","hello world");
    }
    
    
    //消费者
    @Component
    @RabbitListener(queuesToDeclare = @Queue("hello"))
    public class HelloCustomer {
    
    @RabbitHandler
    public void receive1(String message){
    System.out.println("message = " + message);
    	}
    }
    

    5.MQ应用场景

    5.1异步处理

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

    img

    串行方式: 将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个任务全部完成后才返回给客户端。这有一个问题是,邮件,短信并不是必须的,它只是一个通知,而这种做法让客户端等待没有必要等待的东西。
    

    img

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

    img

    消息队列方式:假设三个业务节点分别使用50ms,串行方式使用时间150ms,并行使用时间100ms。虽然并行已经提高的处理时间,但是,前面说过,邮件和短信对我正常的使用网站没有任何影响,客户端没有必要等着其发送完成才显示注册成功,应该是写入数据库后就返回。消息队列: 引入消息队列后,把发送邮件,短信不是必须的业务逻辑异步处理。
    
    由此可以看出,引入消息队列后,用户的响应时间就等于写入数据库的时间+写入消息队列的时间(可以忽略不计),引入消息队列后处理后,响应时间是串行的3倍,是并行的2倍。
    

    5.2应用解耦

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

    img

    这种做法有一个缺点:当库存系统出现故障时,订单就会失败。订单系统和库存系统高耦合。
    

    img

    使用消息队列后:
    订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。
    库存系统:订阅下单的消息,获取下单消息,进行库操作。就算库存系统出现故障,消息队列也能保证消息的可靠投递,不会导致消息丢失.
    

    5.3流量削峰

    场景: 秒杀活动,一般会因为流量过大,导致应用挂掉,为了解决这个问题,一般在应用前加入消息队列。 
    作用:
    1.可以控制活动人数,超过此一定阀值的订单直接丢弃。
    2.可以缓解短时间的高流量压垮应用(应用程序按自己的最大处理能力获取订单) 
    

    img

    1.用户的请求,服务器收到之后,首先写入消息队列,加入消息队列长度超过最大值,则直接抛弃用户请求或跳转到错误页面.  
    2.秒杀业务根据消息队列中的请求信息,再做后续处理.
    

    6分布式集群架构(省略)

    参考原文

    参考B站视频

  • 相关阅读:
    为何没有.aspx.designer.cs文件?
    ItemDataBound的用法
    DataList控件 属性全攻略
    给LinkButton添加href、target属性
    给文本框添加灰色提示文字
    转载::深入研究DataList分页方法
    WCF 第六章 序列化与编码 保留引用和循环引用
    WCF 第六章 序列化和编码之NetDataContractSerializer
    WCF 第六章 序列化与编码 比较WCF序列化选项
    WCF 第六章 序列化和编码 使用代理序列化类型
  • 原文地址:https://www.cnblogs.com/apex-wzw/p/14676795.html
Copyright © 2011-2022 走看看