rabbitmq

1.rabbitmq用的是tcp连接。在tcp中虚拟了信道,不同的线程走不同的信道,一个线程一个信道。

2.路由键:生产者发布消息时,会携带路由键。rabbitmq里有交换器,路由器根据路由键给消息分配队列。路由键就是个字符串,最大长度255字节。

3.消息确认机制(ACK):避免消息丢失和消息重复消费

4.rabbitmq消息存在于内存中,也可以存在于磁盘中(持久化).

5.默认情况下,一个消息,只发给一个消费者,当多个消费者订阅一个队列时,消息会轮询的发给消费者。第一条消息给第一个消费者,第二个消息给第二个消费者。

6.生产者发送的路由键如果在rabbitmq里识别不了,那么,该条消息就会丢失。

7.路由器,交换器,队列等概念,都是AMQP规范定义的概念。

8.路由器的类型:

director:完全匹配:路由键完全匹配

fanout:广播形式:不管路由键,给所以队列分发消息。

topic:路由键可以有多个部分组成,如a.b; b.b。一般用符号"."将路由键分成几个部分。

         路由键中的"#"和"*":路由键为key.key1。交换器的绑定键key.#将key部分归纳起来。然后再通过#.key1将路由键归纳到相应的队列中。

         其中,#是匹配多个,如king.kafka.1的路由键是可以匹配king.#的。但是不能匹配king.*。#类似模糊查询,只写一个#,就是全部消息都能绑定。#.key,那么不管前面几个“.”,只要最后匹配key,则可以绑定

       在rabbitmq的绑定键中,有key.#(key.*)和#.key(*.key),这些绑定键是单独存在的。先通过key.#找到前面的key,再通过#.key找后面的key

 在topic类型的交换器中,路由键才会设置成a.b形式,其他类型交换器没必要这么设置。

8.rabbitmq的后台管理端口是15672。在代码中的tcp连接端口是5672.

9.生产者和消费者是 两个分离的过程。可以没有消费者,生产者一直往mq中发消息。写代码的时候,也是两个分离的过程去写。

10.生产者和消费者都需要跟mq进行连接,且都是通过信道,跟mq服务进行连接。生产者和消费者都需要指定mq的交换器。

java连接rabbitmq的过程:

生产者:创建连接,创建信道,设置交换器类型和名称,发送消息和路由键

消费者:创建连接,创建信道,设置交换器类型和名称,接受消息

mq需要的操作(需要在java代码中设置,放在生产端和消费端设置都行):声明队列,生命绑定键,将绑定键与队列和交换器进行绑定。

这样,mq就可以将消息,从生产者,发送给消费者了。中间的一系列设置操作,都是通过channel信道对象完成的。

具体代码,看rabbitmq的native里exchange的代码。

11.如何确保ACK:

失败通知:生产者发送的路由键,在mq中找不到对应队列,消息会丢失,然后返回失败通知(在消息发布时,设置一个参数为true即可)

事务:信道channel可以设置事务,但是严重影响性能,使生产者发生消息是同步效果。一般不用

发送方确认:开启发送方确认后,mq通过交换器将信息成功放入队列,则给生产者返回ack,如果mq在交换器往队列放消息时发生内部错误,没有将信息放入队列,则                           mq向生产者发送Nack消息。

      确认方式有单条确认和批量确认。单条确认就是每发一次,就调用一下确认方法。批量确认是发送完所有消息后,调用批量确认方法。批量确认如果某一条有问题,是不能知道哪条有问题的,需要人为手动排查。

      还有一种是异步监听,接受确认消息。

12.备用交换器:

失败通知模式,是没有路由键的消息,返回失败通知。如果没有路由键的消息,我们不想让他返回失败通知,而是想单独收集起来,那么,就用备用交换器。在声明主交换器的同时,声明备用交换器,那么,主交换器对应的路由键会进入主交换器队列,备用的会进入备用交换器队列。其实就是一个信道,同时开启了多个交换器的意思。

 13.以上讲的是生产者的消息确认机制,下面开始讲消费者的消息确认机制。

消费端有两种获取消息的方式:拉取和推送。一般用推送方式。

消费端的ACK是消费者给mq发送消息,告诉mq已经消费了该消息,mq可以删除该消息了。分为自动确认和 手动确认模式。消费端的确认模式,保证消息不会重复消费。

14.消费消息的拒绝(也是一个消费者,只不过它接收到的消息都进行拒绝策略):

reject:只能一条一条的拒绝

Nack:可以批量拒绝

拒绝测试,有个requeue参数,设置为false,则消息直接就丢了。设置为true,则消息会重新进入mq的队列中,重新投递消息。

如果设置了false,而且设置了死信对列,则消息不会丢失,会进入死信队列

15.死信消息:

mq中的队列,是有大小的。当消息超过队列大小时,队列的第一条消息,就是死信消息了。队列中的消息,也有过期时间,当超过过期时间,也就成了死信消息。拥有拒绝策略的消费者,拒绝的消息,也是死信消息。

死信消息不处理,结果就是丢失。如果想处理,就要绑定死信交换器。死信交换器对死信消息进行重新投递。死信交换器会有队列绑定,死信交换器投递到这些队列上。

16.创建队列时的几个参数:

自动删除:当绑定队列的消费者关闭连接时,自动删除属性的队列会在mq中消失。

多个消费者绑定一个队列时,默认队列轮询发送消息。可以设置参数,将队列的消息只发送给一个消费者。

17.在spring集成mq后,声明queue的时候,会默认绑定一个direct交换器,且会默认把队列名称作为绑定键与交换器绑定。

18.rabbitMQ实战:

订单系统和库存系统,通过rabbitMQ进行通信。

注意点:1.发送方确认、失败通知   (确认消息发到MQ)

            2.持久化(交换器、队列、消息),防止rabbitMQ挂掉

             3.消费端手动应答(确保消费端正常消费)

19.rabbitmq管理:

日志文件:记录rabbitmq的启动日志和连接日志、宕机日志等信息。

20.消息幂等性问题:

幂等性就是消息重复消费时,返回结果的一致性。

当消费端消费了消息,给服务器反馈ack时,假如网络有问题,rabbitmq服务器没有收到ack消息,那么,这条消息就有可能重新发送。消费端就会重复接收消息。对于有些业务而言,重复的操作可能会带来问题,所以要判断是否已经操作了该数据。

常见的解决方案是:rabbitmq发送消息时,可以给消息设置messageID属性,以此为唯一标识,在消费时,取到该唯一标识,看之前是否处理了该唯一标识。来避免重复消费。

或者用数据库层面的唯一索引来做判断等方式。

原文地址:https://www.cnblogs.com/hongyuansu/p/14016453.html