画布 1
AMQP
  什么是AMQP
    Advanced Message Queuing Protocol 高级消息队列协议，是面向消息中间件提供的应用层协议。基于此协议的消息提供者和接受者可实现消息的交互传递，且不受平台语言限制。
  什么是消息队列
    消息是指在应用程序间传递的数据，消息可以是普通的文本字符串，也可以是复杂的对象。
    消息队列是存储和收发消息的应用程序，它保证了应用程序间消息传递的可靠性。
  为什么需要MQ / MQ使用场景
    系统解耦
      系统间通过MQ传递消息，而无需关心其他系统的处理
    流量削峰
      MQ可以缓解短时间内的流量高峰，减少对服务器的压力
    日志处理
      复杂的系统架构必然需要处理大量日志，使用MQ可以传输日志
    广播
      在分布式系统中，可以通过MQ将消息广播到各个节点中
  MQ模型
    所有的MQ的模型抽象出来都是一样的: 消费者(订阅者)订阅某个消息队列，生产者(发布者)发布消息到消息队列，最后消息队列将消息发送给消费者。
  RabbitMQ
    什么是RabbitMQ
      RabbitMQ是使用Erlang语言编写的支持AMQP协议的高性能消息队列,目前由Pivotal(开发Spring的那个公司)公司在维护。RabbitMQ最初起源于金融系统，被用于在分布式系统种存储和转发消息，具有较好的易用性，可扩展性和并发性等优点。
    RabbitMQ基本概念
      Message消息
        消息即需要发送的数据，由消息体和消息头组成。消息体是消息的内容，消息头则是对消息体的描述，由许多Property属性组成，如路由键，优先级，持久化等等组成。
      Producer 生产者
        生产者即发布者，它是发布消息的一方，可以是一个RabbitMQ客户端应用程序。
      Consumer 消费者
        消费者即订阅者，他是接受消息的一方，也可以是一个RabbitMQ客户端应用程序
      Exchange 交换机
        交换机用于接受 生产者发布的消息，并按消息的路由规则将消息发送到指定的消息队列。
      Binding 绑定
        绑定一种规则，它将Exchange交换机与Queue消息队列 按照路由规则绑定起来
      Routing-Key 路由键
        路由键即路由规则， Exchange交换机根据Routing Key将消息投递到指定的消息队列
      Queue 消息队列
        消息队列是消息容器，用于存储和收发消息。一个消息可以投递到一个或多个消息队列中，直到Consumer将消息消费
      Connection 网络连接
        无论是发布消息还是订阅消息，都需要通过TCP连接来完成
      Channel 信道
        对于计算机服务器来说，网络是非常宝贵的资源，如果每次发布消息或订阅消息都需要建立连接，那就太耗费Connection资源了，所以引入了Channel信道的概念。发布消息和订阅消息通过Channel信道来完成，而多个Channel可以共享一条Connection，这样就节约了很多Connection资源
      Virtual Host 虚拟主机
        虚拟主机是一个虚拟概念。 在Redis中，一个Redis服务器实例可以被分为16个库，但不是说这16个库的大小就是相等的，比如1个库也可以占9g内存，其他15个库可以共占1g内存。虚拟主机也是如此，它可以看做是一个独立的rabbitmq服务器实例，它包含了属于他的一系列的Exchange，Queue等内容
      Broker
        Broker 即RabbitMQ服务实例
    RabbitMQ工作模型
      Simple Queue
        简单模式。它是最简单的消息收发模型，生产者和消费者直接通过Queue进行消息的收发。
      Work Queue
        工作模式 。工作模式与简单模式非常相似，但工作模式允许多个消费者争抢的消费同一个队列的消息
      Publisher / Subscriber (fanout)
        发布者 / 订阅者模式 。 发布者/订阅者模式可以说是真正意义上的RabbitMQ的工作模型。 发布者不直接将消息发布到Queue，而是将消息发送到Exchange交换机，再由交换机将消息广播到与此交换机绑定的每个队列中，订阅者也只需要监听它自己的队列就行了
      Routing (direct)
        路由模式。 发布者在发布消息的时候可以指定一个Routing Key路由键，接受者也会与其消息队列绑定一个路由键。 当消息被发送到Exchange后，Exchange根据路由键，将消息发送到拥有相同路由键的消息队列。
      Topic (topic)
        主题模式。主题模式是一种特殊的路由模式，与路由模式不同的是: 主题模式的路由键支持通配符，可以做到更加多样化的路由键匹配。
    RabbitMQ Exchange的类型
      fanout
        fanout即发布者 / 订阅者模式 ， 发布者将消息发送到fanout类型的Exchange，Exchange再将消息广播给与此交换机绑定的Queue
      direct
        direct即路由模式,Exchange根据Routing Key，将消息发送到匹配的队列中
      topic
        topic 也属于路由模式，不过它支持 *和#通配符进行路由
    如何避免消息被重复消费
      消息被重复消费即消息的发送者发送了多次相同的消息给接受者，从而导致接受者出现业务上的问题。这是一个非幂等的问题。我们知道在Http协议中，GET请求是幂等的，即多次相同的GET请求并不会对服务器的资源造成影响。而POST请求或PUT请求 (在POST和PUT请求的语义为 添加 的情况下) 是非幂等的，多次相同的POST请求或PUT请求可能在服务器上创建多个资源。
        对于 发布者来说， 在它发送消息给MQ服务器后，MQ服务器收到消息后，响应一个ACK给发布者代表它收到了发布者的消息。 如果MQ响应的ACK由于网络原因丢失了，那么发布者会再次发送消息给服务器，这就造成了服务器收到了多次相同的消息的问题。
        对于 MQ服务器来说， 当它发送消息给 Consumer客户端时，Consumer收到消息后响应ACK给MQ服务器，代表它接收到了MQ服务器的消息。如果Consumer响应的ACK由于网络原因丢失了，那么MQ会再次发送消息给Consumer客户端，这也造成了Consumer多次消费相同的消息的问题。
        无论是MQ服务器还是Consumer消费端，它们都需要判断消息的唯一性，如果判断消息已经接受过了，那么可以选择不再处理相同的消息。解决办法是可以给消息添加全局唯一的标识，如唯一ID，用于保证消息的全局唯一性。
    如何保证消息传递的可靠性
      消息传递不可靠的情况主要有: 发布者丢失消息，Broker丢失消息，Consumer丢失消息
        Producer丢失消息有2种解决方案: 1. transaction 2. confirm
          transaction事务
            如果消息发送成功，则提交事务。如果在发送消息的过程中出现了异常，那么事务就会回滚。虽然事务可以保证Producer发送消息的可靠性，但是会降低吞吐量，所以更推荐使用confirm机制保证Producer发送消息的可靠性
          confirm机制
            当消息被发送给消息队列后，Broker会响应一个ACK给Producer。如果Broker无法处理该消息，则返回一个NACK给Producer，Producer可以根据返回的NACK再做处理。
        Broker丢失消息
          Broker丢失消息一般是MQ服务器宕机或出现其它较为严重的问题，所以Broker丢失消息的问题，可以通过持久化解决。
        Consumer丢失消息
          Consumer接受到消息队列的数据后，会自动回复Broker，Broker就会删除这条消息，
但如果Consumer在此时处理消息的过程中，发生了意外，消息就丢失了。
Consumer可以在处理完消息后再手动回复Broker，这样即使发生了意外，Broker也能重新发送消息给Consumer
作者: qsjzwithguang19forever
作者微信: yg1446125917
作者邮箱: 2196927727@qq.com
作者github: github.com/guang19
本xmind归属于qsjzwithguang19forever的开源项目:framework-learning。
framework-learning旨在为Java方向的开发者提供较为全面，通俗的知识梳理。
项目地址: github.com/guang19/framework-learning
如若转载，请声明来源。