Rabbitmq 之理解消息通信

目录

    • 2.3 交换器和绑定
    • 2.4 多租户模式:虚拟主机和隔离
    • 2.5 消息持久化和策略
    • 2.6 发送消息的过程

2.3 交换器和绑定

前面以及说明了什么是队列,消息如何投递到了队列中的呢?
     当消息投递到队列中时,通过消息发送给交换器完成,队列通过路由键绑定到交换器。当消息发送到代理服务器时,消息将拥有一个路由键(即便是空的)rabbitmq也会将其和绑定使用的路由键进行匹配。匹配成功,则消息投递到该队列;不匹配,消息进入“黑洞”。
当消息需要投递到多个队列时,AMQP协议定义了四种不同类型的交换机,分别为:

  • **direct:**路由器匹配,则消息被投递到对应队列
    Rabbitmq 之理解消息通信_第1张图片
    服务器必须为direct类型的交换器,包含一个空字符串名称的默认交换器。声明一个队列时,会自动绑定到默认交换器,队列名为路由键。前提是你已经获得了信道的实例:
    $channel->basic_public(msg,'','queue-name')
    msg为消息内容;第二个为空字符串,指定了默认交换器;第三个为路由键,声明队列名称。
  • fanout: fanout交换器会将收到的消息广播绑定到队列上。其消息通信模式为:
    当发生一条消息到fanout时,他会把消息投递给所有附加在此交换器的队列。其交换器消息流如下图
    Rabbitmq 之理解消息通信_第2张图片
  • topic: 此交换器能够使来自不同源头的消息到达同一个队列。
    Rabbitmq 之理解消息通信_第3张图片
  • headers: 此交换器允许你匹配AMQP消息的header而非路由键,除此之外headers路由器和direct 路由器完全一致,但是性能较差。故不太实用,且几乎再也用不到

2.4 多租户模式:虚拟主机和隔离

     每一个rabbitmq服务器都能创建虚拟消息服务器,我们称之为虚拟主机(vhost)。 每个vhost本质上是一个mini的rabbitmq服务器,拥有自己的队列、交换器和绑定,重要的是它拥有自己的权限机制。保证了一个rabbitmq服务器可服务众多应用程序。vhost之于rabbit就像虚拟机和物理机一样:通过各个实例间提供逻辑分离,,允许为众多客户区分开来。有可避免队列和交换器命名冲突。
     vhost是AMQP概念的基础,连接时指定。rabbitmq包含了开箱即用的rabbitmq的默认vhost:“/”,因此使用起来非常简单。权限控制是以vhost为单位的
     当rabbitmq创建用户时,用户通常会被指派至少一个vhost,且只能访问被指派的vhost内的队列、交换器和绑定。设计消息通信框架时vhost之间是绝对隔离的。
在rabbitmq集群上创建vhost时,整个集群上都会创建该vhost。
vhost基本操作:
通过rabbitmq安装目录下 ./sbin/ 目录下 rabbitmqctl 工具
创建: rabbitmqctl add_vhost[vhost_name]
删除: rabbitmqctl delete_vhost[vhost_name]
查看运行: rabbitmqctl list_vhosts

2.5 消息持久化和策略

能从AMQP服务器崩溃中恢复的消息,称之为持久化消息
消息从rabbit崩溃中恢复。则必须满足以下三点:

  • 将投递模式设置成2(持久)

  • 发送到持久的交换器

  • 到达持久化的队列
         rabiitmq确保持久性消息能从服务器重启中恢复的方式是,就他们写入磁盘上的一个持久化日志文件。发布一条持久性消息到持久交换器上时,rabbit会在消息提交到日志文件后才发送相应。当持久化消息到达非持久化队列,会自动从持久性日志中删除。
    在持久化队列中消费一条持久性消息是,会在持久化日志中吧这条消息标记为等待垃圾收集。消费持久化消息前,rabbitmq重启,服务器自动重建服务器和队列、绑定,重播持久性日志文件中的消息到合适的队列或者交换器中。
         消息持久化的性能:消息存入磁盘比写入内存中慢很多。极大减少了rabbitmq每秒处理消息的数量。很多情况下 消息吞吐量可能降低10倍,且在集群中支持不是很好。
    权衡取舍,要保证持久化消息通信,可运行两种类型的rabbit集群:非持久化消息通信、持久化消息通信的活动/热备非集群rabbitmq服务器
         正常情况下,如果消息经过交换器进入队列就可以完成消息的持久化,但如果消息在没有到达broker之前出现意外,那就造成消息丢失,有没有办法可以解决这个问题?
    RabbitMQ有两种方式来解决这个问题:
    1. 通过AMQP提供的事务机制实现;
    使用事务不但会降低2-10倍的消息吞吐量,且会使生产者和消费者同步。
    事务的实现主要是对信道(Channel)的设置,主要的方法有三个:

    • channel.txSelect()声明启动事务模式;
    • channel.txComment()提交事务;
    • channel.txRollback()回滚事务;

    2. 使用发送者确认模式实现;
    Confirm发送方确认模式使用和事务类似,也是通过设置Channel进行发送方确认的。其实现方式主要有三个:

    • channel.waitForConfirms()普通发送方确认模式;
    • channel.waitForConfirmsOrDie()批量确认模式;
    • channel.addConfirmListener()异步监听发送方确认模式;

2.6 发送消息的过程

1.消息生产者发布消息的过程:

  • 连接RabbitMq
  • 获取信道
  • 声明交换器
  • 创建消息
  • 发布消息
  • 关闭信道
  • 关闭连接

2.消费者接受消息的过程:

  • 连接RabbitMq
  • 获取信道
  • 声明交换器
  • 声明队列
  • 把队列和交换器绑定起来
  • 消息
  • 关闭信道
  • 关闭连接

你可能感兴趣的:(Rabbitmq)