欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#队列学习笔记:RabbitMQ基础知识

程序员文章站 2022-07-02 11:02:40
一、引言 RabbitMQ是Rabbit Message Queue的简写,但不能仅仅理解其为消息队列,消息代理更合适。RabbitMQ是一个由 Erlang 语言开发的AMQP(高级消息队列协议)的开源实现,其内部结构如下: RabbitMQ作为一个消息代理,主要和消息打交道,负责接收并转发消息。 ......

    一、引言

    rabbitmq是rabbit message queue的简写,但不能仅仅理解其为消息队列,消息代理更合适。rabbitmq是一个由 erlang 语言开发的amqp(高级消息队列协议)的开源实现,其内部结构如下:

C#队列学习笔记:RabbitMQ基础知识

    rabbitmq作为一个消息代理,主要和消息打交道,负责接收并转发消息。rabbitmq提供了可靠的消息机制、跟踪机制和灵活的消息路由,支持消息集群和分布式部署。适用于排队算法、秒杀活动、消息分发、异步处理、数据同步、处理耗时任务、cqrs等应用场景。

    二、基础概念

     讲解基础概念之前,先来构造一个整体结构图,以方便我们更好地去理解rabbitmq的基本原理。

C#队列学习笔记:RabbitMQ基础知识

    通过上面这张结构图,能够清晰地了解到send message到receive message的一个大致流程。

    2.1、queue

    queue(队列)在rabbitmq中的作用是存储消息,队列的特性是先进先出。上图可以清晰地看到client a和client b是生产者,生产者生产消息最终被送到rabbitmq的内部对象queue中去,而消费者则是从queue中取出数据,可以简化表示为:

C#队列学习笔记:RabbitMQ基础知识

    生产者send message,“a”被传送到queue中,消费者发现消息队列queue中有订阅的消息,就会将这条消息a读取出来进行一系列的业务操作。这里是一个消费者对应一个队列queue,也可以多个消费者订阅同一个队列queue,此时就会将queue里面的消息平分给其他的消费者,但是会存在一个问题就是如果每个消息的处理时间不同,就会导致某些消费者一直在忙碌中,而有的消费者处理完消息后一直处于空闲状态。这时我们可以使用prefetchcount来限制每次发送给消费者消息的个数,详情见下图所示:

C#队列学习笔记:RabbitMQ基础知识

    这里的prefetchcount=1是指每次从queue中发送一条消息,等消费者处理完这条消息后,queue会再发送一条消息给消费者。

    2.2、exchange

    在本节开头的结构图中我们留下了一个坑:消费者client a和消费者client b,是如何知道要发送的消息是给queue1还是给queue2的呢?下面让我们来解开这个面纱。首先要明确的一点是:生产者生产的消息并不是直接发送给消息队列queue的,而是要经过exchange(交换器)将消息路由到一个或多个queue,当然这里还会对不符合路由规则的消息进行丢弃,这个涉及到后面要讲的exchange type。那么exchange是怎样将消息准确地推送到对应的queue的呢?功劳最大的当属binding。rabbitmq通过binding将exchange和queue链接在一起,这样exchange就知道如何将消息准确地推送到queue中去了,简单示意图如下所示:

C#队列学习笔记:RabbitMQ基础知识

    生产者将消息发送给exchange的时候,一般会产生一个routing key,而通过binding链接exchange和queue的时候,一般会指定一个binding key。当routing key与binding key对应得上的时候,消息就会发送到对应的queue中去。

     2.3、exchange type

    exchange type有4种,不同的类型有着不同的策略,也就意味着类型的不同将决定着绑定的queue的不同。换言之,生产者发送了一个消息,routing key的规则是a,那么生产者会将routing key=a的消息推送到exchange中,这时候exchange根据自己的规则去筛选生产者发来的消息。

  • fanout

    fanout类型的exchange,路由规则非常简单:它会把所有发送到该exchange的消息,路由到所有与它绑定的queue中。

C#队列学习笔记:RabbitMQ基础知识

    上图所示,生产者(p)将消息1推送到exchange,由于exchange type=fanout,这时候会遵循fanout的规则将消息推送到所有与它绑定的queue中(上图的两个queue),最后给两个消费者消费。

  • direct

    direct类型的exchange,路由规则也很简单:它会把消息路由到那些routing key与binding key完全匹配的queue中。

C#队列学习笔记:RabbitMQ基础知识

    当生产者(p)发送消息时rotuing key=booking,exchange获取到生产者发送过来的消息后,会根据自身的规则进行匹配相应的queue,这时发现queue1和queue2都符合,就会将消息传送给这两个队列。如果我们以rotuing key=create和rotuing key=confirm发送消息时,这时消息只会被推送到queue2队列中,其它routing key的消息将会被丢弃。

  • topic

    如果说前面的direct规则是严格意义上的匹配(即routing key必须与binding key相匹配的时候才将消息传送给queue),那么topic这个规则就是模糊匹配,可以通过通配符满足一部分规则就可以传送,它的约定是:

    1)routing key为一个句点号“. ”分隔的字符串(我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词),如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”。

    2)binding key与routing key一样也是句点号“. ”分隔的字符串。

    3)binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)。

C#队列学习笔记:RabbitMQ基础知识

    当生产者发送消息routing key=f.c.e的时候,这时候只满足queue1,所以会被路由到queue1中;如果routing key=a.c.e这时候会被同时路由到queue1和queue2中;如果routing key=a.f.b时,这时只会路由到queue2中。

  • headers

    headers类型的exchange,不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。

    在绑定exchange与queue时指定一组键值对,当消息发送到exchange时,rabbitmq会取到该消息的headers(也是一个键值对的形式),并对比其中的键值对是否完全匹配exchange与queue绑定时指定的键值对,如果完全匹配则消息会路由到该queue,否则不会路由到该queue。该类型的exchange没有用到过(不过也应该很有用武之地),所以不作介绍。

    下面对4种exchange类型进行简要的表格整理:

exchange规则
类型名称 类型描述
fanout 把所有发送到该exchange的消息路由到所有与它绑定的queue中
direct routing key==binding key
topic 简称模糊匹配
headers exchange不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。

    2.4、补充说明

    connectionfactory、connection、channel:都是rabbitmq对外api中最基本的对象。

    connectionfactory:connection的制造工厂。

    connection:rabbitmq的socket链接,它封装了socket协议相关的逻辑。connection建立一个tcp连接,生产者和消费者通过tcp连接到rabbitmq server。

    channel:

    1)channel是与rabbitmq打交道的最重要的一个接口,我们大部分的业务操作都是通过channel这个接口来完成的,包括定义exchange与queue、绑定exchange与queue、发布消息等。

    2)channel虚拟连接,是建立在上面tcp连接的基础上。数据流动都是通过channel来进行的,为什么不是直接在tcp连接上进行数据流动呢?是因为建立和关闭tcp连接是有代价的。频繁地建立与关闭tcp连接对于系统的性能有很大的影响,而且tcp的连接数也有限制,这也限制了系统处理高并发的能力,而在tcp连接中建立channel是没有上述代价的。

 

    参考自:

    https://www.cnblogs.com/dwlsxj/p/rabbitmq.html