读书笔记 2 -- 《rabbitMq 实战指南》

消息中间件的作用:
    1、解耦
    2、冗余(存储)
    3、扩展性(增加生产者/消费者)
    4、削峰
    5、异步处理
    6、保证顺序

消息通信标准:    
    1、JMS(Java Message Service):隐藏单独MQ产品提供商的实际接口。针对API编程,选择合适的MQ驱动(该驱动实现了JMS接口规范)即可随意切换MQ。
        ActiveMQ就是JMS的一种实现。
    2、AMQP(Advanced Message Queuing Protocol,高级消息队列协议)
        特性:使用协议就可以对队列和交换器这样的资源进行配置。
    
RabbitMq
    1、AMQP(Advanced Message Queuing Protocol,高级消息队列协议)
    2、特性:
        2.1、可靠性:持久化、传输确认、发布确认。
        2.1、灵活的路由:在消息进入队列之前,通过交换器来路由消息。
        2.3、扩展性:集群。
        2.4、高可用:副本镜像。
        2.5、多种协议:原生支持AMQP协议,还支持STOMP、MQTT等多种消息中间件协议。
        2.6、多语音客户端、管理界面、插件机制等。

第二章:
    1、概念介绍
        1、队列(Queue):用于存储消息。
            多个消费者可以订阅同一个队列,此时队列中的消息会被平均分摊(Round-Robin,即轮询),给多个消费者进行处理。
        2、交换器、路由键、绑定
            Exchange:交换器。负责交换的动作。
            RoutingKey:路由键。用于将消息路由到对应的队列。
            Binding:绑定。将队列和交换器关联起来。
            消息 -》Exchange -> 根据RoutingKey路由到对应的队列 -> 存入队列
        3、交换器类型
            1、fanout:发送到该交换机的消息路由到所有与该交换机绑定的队列中。
            2、direct:把消息路由到BindingKey和RoutingKey完全匹配的队列。
            3、topic:模糊匹配的direct。用“.”来分割,“*”:模糊匹配一个单词;“#”:模糊匹配多个单词。
            4、headers:不依赖路由键的规则来路由消息。根据发送的消息内容中的headers属性进行匹配。(性能差,基本不用)
        4、运转流程
            生产者流程:
                1、建立链接 Connection , 开启通道 Channel 
                2、声明交换器,设置交换器相关属性,如交换器类型、是否持久化等。
                3、声明一个队列,并设置相关属性,如是否排他、是否持久化、是否自动删除等。
                4、用路由键将交换器和队列绑定。
                5、生产者发送消息到RabbitMq Broker,其中包含路由键、交换器等信息。
                6、Broker的交换器根据路由键查找相匹配的队列。
                7、找到匹配队列,则将消息存入队列中。
                8、没有找到匹配的队列,则根据生产者的属性将消息丢弃或者回退给生产者。
                9、关闭通道。
                10、关闭链接。
            消费者流程:
                1、消费者链接到Broker,建立Connection,开启通道Channel。
                2、消费者向Broker请求消费相应队列中的消息,可能会 设置相应的回调函数。
                3、等待Broker回应并投递相应队列中的消息,消费者接收消息。
                4、消费者确认接到消息。(ack)
                5、RabbitMq从队列中删除被确认的消息。
                6、关闭通道。
                7、关闭链接。
        5、链接、通道
            一个TCP链接,多个通道。(NIO,TCP链接复用)
            NIO中有一个很有名的Reactor模式。
            一个Connection对应多个Channel,当流量很大时,需要多开几个Connection。
    2、AMQP协议
        协议分为三层
        1、Module Layer:协议最高层,定义了一些供客户端调用的命令。如:声明队列,订阅队列。
        2、Session Layer:协议中间层,负责将客户端的命令发送给服务器,再将服务端的应答返回给客户端。处理客户端和服务器之间的通信,同步机制和错误处理。
        3、Transport Layer:协议最底层,主要传输二进制数据流,提供帧的处理,信道复用,错误检测和数据标识等。
        AMQP说到底还是一个通信协议,通信协议都会涉及到报文交互。

第三章:
    重点:连接、交换器/队列的创建与绑定、发送消息、消费消息、消费消息的确认、关闭链接。
    1、连接RabbitMQ
        Connection开启多个Channel。
        Connection可以多线程共享,Channel不可以多线程共享。
    2、交换器和队列
        1、交换器初始化参数解析
            1、durable:设置是否持久化。Broker重启,持久化的交换器会恢复。
            2、autoDelete:设置是否自动删除。交换器与队列之间的绑定关系。
            3、noWait:不需要服务器返回。(创建交换器不需要服务器应答,弊端:不确定交换器是否创建成功。)
        2、队列初始化参数解析
            1、durable:设置是否持久化。服务重启消息还在。
            2、exclusive:设置是否排他。排他:仅首次声明队列的连接可见,断开连接时自动删除。基于连接可见的(非通道,意思连接下的多个通道可以使用该队列)
            3、autoDelete:设置是否自动删除。消费者连接到这个队列,当所有的消费者都断开连接时,删除队列。
        3、发送消息
            1、mandatory:确保消息到达。
    3、消息消费
        1、推模式:Basic.Consume
            参数详解:
                consumerTag:消费者标签,用来区分多个消费者。
                noLocal:true表示不能将同一个Connection中生产者的消息给同一个Connection中的消费者消费。                
        2、拉模式:Basic.Get
    4、消息的确认与拒绝
        1、确认
            自动确认:消息推送给消费者后,就删除消息。不管消息是否真的被消费。
            手动确认:等待消费者显式地回复确认信号后,才从内存/磁盘中移除消息。(先标记为删除,之后再删除。)
                队列中消息分成两个部分:一部分是等待投递给消费者的消息,另外一部分是已经投递给消费者,等待消费者确认的消息。
                如果RabbitMQ一直没有收到消费者的确认信号,并且消费此消息的消费者已经断开连接,则RabbitMQ会安排该消息重新进入队列,等待投递给下一个消费者。
        2、拒绝
            requeue,拒绝的消息是否重新入队列。
            死信队列:存放requeue=false的信息

第四章:
    1、消息丢弃策略
        mandatory:(强制的)true 找不到队列,返回给生产者。
                  false 丢弃。
        immediate:(立即的)true 队列上不存在消费者,那么该消息不存入队列。当所有的队列都不匹配时,消息将会返回。
                  false 存入队列。
        备份交换器:(Alternate-Exchange)
            如果不想消息被丢弃,那么需要设置mandatory,但是这样的处理方式需要生产者添加ReturnListener监听,增加了生产者的复杂性。因此引入备胎交换器。
    2、过期时间(TTL, Time to Live)
        1、设置消息的TTL
            1、通过队列属性设置,队列中所有的消息都有一样的过期时间。
            2、仅对某条消息设置过期时间。
            3、以上两点,那个时间短,用谁的。
    3、死信队列(DLX , Dead-Letter-Exchange 死信交换器)
        1、死信的原因
            1、消息被消费者拒绝。
            2、消息过期。
            3、队列达到最大长度。
        2、死信队列绑定到正常的队列上,当该队列有死信消息,就发送该消息到死信队列上。
    4、延迟队列
        使用场景:
            1、订单系统中,用户下单之后通常有30分钟的时间进行支付,如果超过30分钟,那么订单将进行失效处理。
            2、支付的异步通知。
            3、在半夜(系统不繁忙的时间段)轮询数据库,将要今天内处理的事情,发送到延迟队列。等待消费者进行处理。
        实现方式:
            使用TTL和DLX实现。
    5、优先级队列
        1、设置队列的x-max-priority参数来实现。
        2、存在消息堆积,才有意义。
        3、优先级高的消息,优先被消费。
    6、持久化(弊端:内存的速度当然快于硬盘的速度)
        1、交换器持久化:durable=true
        2、队列持久化:durable=true
        3、消息持久化:BasicProperties的deliveryMode=2
    7、生产者确认    
        1、通过事务机制实现
            1、channel.txSelect 用于将当前的通道设置为事务模式。
            2、channel.txCommit 用于提交事务。
            3、channel.txRollback 用于事务回滚。
            (缺点,性能差。推荐下面的方式)        
        2、通过发送方确认(publisher confirm)机制实现。
                生产者将通道设置成confirm(确认)模式,通道发布消息时会被指派一个唯一的ID(从1开始),一旦消息投递到对应的队列后,RabbitMQ会发送一个确认给生产者(确认的消息包含ID),
            通过该方式确保消息到达。
    8、消费端要点介绍
        1、消息分发
            1、默认用轮询的方式接收。(由于机器性能不一,需要做额外的处理)
            2、channel.basicQos(); 允许限制通道上的消费者所能保持的最大未确认消息的数量。
        2、消息顺序性
            消费者消费的消息和发送者发送的消息顺序是一致的。
            RabbitMQ不保证消息的顺序性。
            如果需要顺序消息,需要开发者自己处理。(在消息体内添加全局有序标识)
        3、弃用 QueueingConsumer 
    9、消息传输保证
        1、最多一次。
        2、最少一次。
        3、恰好一次:无法保证。


未完,待续。

 

posted @ 2020-03-27 19:23  陈标  阅读(258)  评论(0编辑  收藏  举报