RabbitMQ中消息发布与权衡

发布时间 2023-12-23 19:59:55作者: 帅哥川

1. 原生Java客户端进行消息通信

客户端需要amqp-client-5.0.0.jar和slf4j-api-1.6.1.jar

建议使用Maven:

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.0.0</version>
</dependency>

image-20231217181103549

1. Direct 交换器

DirectProducer:direct类型交换器的生产者

NormalConsumer:普通的消费者

MulitBindConsumer:队列绑定到交换器上,是允许绑定多个路由键的,也就是多重绑定

MulitChannelConsumer:一个连接下允许有多个信道

MulitConsumerOneQueue:一个队列,多个消费者,则会表现出消息在消费者之间的轮询发送

image-20231217190328539

1. 生产者和消费者的一般用法

DirectProducer:direct 类型交换器的生产者

NormalConsumer:普通的消费者

使用 DirectProducer 作为生产者,NormalConsumer 作为消费者,消费者绑定一个队列

image-20231218223457906

2. 队列和交换器的多重绑定(一个列绑定了多个路由键【routing key】)

DirectProducer:direct 类型交换器的生产者

NormalConsumer:普通的消费者

MultiBindConsumer:队列绑定到交换器上时,是允许绑定多个路由键的,也就是多重绑定

对比:单个绑定的消费者只能收到指定的消息,多重绑定的消费者可以收到多个消息

image-20231218223654056

3. 一个连接多个信道

DirectProducer:direct 类型交换器的生产者

MultiChannelConsumer:一个连接下允许有多个信道

一个连接,我们可以使用多线程的方式模拟多个信道进行通讯。这样可以做到多路复用

4. 一个队列多个消费者

MultiConsumerOneQueue:一个队列多个消费者,则会表现出消息在消费者之间的轮询发送。

image-20231218223833847

2. Fanout

消息广播到绑定的队列

广播类型的交换机只与队列有关系,路由键失效了。只要队列绑定了交换机,那么不管路由键是否匹配,都会发送给所有的队列。

3.Topic交换器

通过使用*#,使来自不同源头的消息达到同一队列,.号将路由键分隔为几个标识。*号匹配一个,#号匹配多个

假设有交换器 topic_course,

讲课老师有 king,mark,james,

技术专题有 kafka,jvm,redis,

课程章节有 A、B、C,

路由键的规则为 讲课老师+“.”+技术专题+“.”+课程章节,如:king.kafka.A。

*与#的区别:

如果我们发送的路由键变成 king.kafka.A

那么队列中如果绑定了 king.* 不能匹配

队列中如果绑定了 king.# 能够匹配

1.要关注所有的课程,怎么做?

声明一个队列并绑定到交换器上:channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME, "#");

2.关注king 老师的所有课程,怎么办?

声明一个队列并绑定到交换器上:channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME, "king.#");

注意:如果这里改为 king.* 的话,则不会出现任何信息,因为 “*”匹配 1 个(使用.分割的标识的个数)

3.关注king老师所有的A章节,怎么办?

声明一个队列并绑定到交换器上:channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME, "king.#.A");或者声明一个队列并绑定到交换器上:channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME, "king.*.A");

4.关注kafka所有的课程,怎么办?

声明一个队列并绑定到交换器上:channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME, "#.kafka.#");

5.关注所有的 B章节,怎么办

声明一个队列并绑定到交换器上:channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME, "#.B");

6.关注king 老师 kafka 的 A 章节,怎么办?

声明一个队列并绑定到交换器上:channel.queueBind(queueName,TopicProducer.EXCHANGE_NAME, "king.kafka.A");

2. 消息发布时的权衡

​ RabbitMQ在设计的时候,特意让生产者和消费者脱钩,也就是消息的发布和消息的消费之间是解耦的。

​ 在RabbitMQ中,有不同的投递机制(生产者),但是每种机制都对性能有一定的影响。

​ 在RabbitMQ实际项目中,生产者和消费者都是客户端,它们都可以完成声明交换器,队列和绑定关系,但是在我们实战过程中,我们在生产者代码中声明交换器,在消费者代码里声明队列和绑定关系。另外,还要说明的是,生产者发布消息时不一定非得需要消费者,对应RabbitMQ来说,如果