面试官常问的 微服务 问题71-79
71.如何避免消息重复投递或重复消费?
在消息生产时,MQ 内部针对每条生产者发送的消息生成一个 inner-msg-id,作为去重的依据(消息投递失败并重传),避免重复 的消息进入队列;
在消息消费时,要求消息体中必须要有一个 bizId(对于同一业务全局唯一,如支付 ID、订单 ID、帖子 ID 等)作为去重的依据, 避免同一条消息被重复消费。
72.消息基于什么传输?
由于 TCP 连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。RabbitMQ 使用信道的方式来传输数据。信道 是建立在真实的 TCP 连接内的虚拟连接,且每条 TCP 连接上的信道数量没有限制。
73.消息如何分发?
若该队列至少有一个消费者订阅,消息将以循环(round-robin)的方式发送给消费者。每条消息只会分发给一个订阅的消费者(前 提是消费者能够正常处理消息并进行确认) 。
通过路由可实现多消费的功能
74.消息怎么路由?
消息提供方 -> 路由 -> 一至多个队列
消息发布到交换器时,消息将拥有一个路由键(routingkey) ,在消息创建时设定。
通过队列路由键,可以把队列绑定到交换器上。
消息到达交换器后,RabbitMQ 会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则) ;
常用的交换器主要分为一下三种:
1)fanout:如果交换器收到消息,将会广播到所有绑定的队列上
2)direct:如果路由键完全匹配,消息就被投递到相应的队列
3)topic:可以使来自不同源头的消息能够到达同一个队列。 使用 topic 交换器时,可以使用通配符
75.如何确保消息不丢失?
消息持久化,前提是队列必须持久化
RabbitMQ 确保持久性消息能从服务器重启中恢复的方式是,将它们写入磁盘上的一个持久化日志文件,当发布一条持久性消息到 持久交换器上时,Rabbit 会在消息提交到日志文件后才发送响应。
一旦消费者从持久队列中消费了一条持久化消息,RabbitMQ 会在持久化日志中把这条消息标记为等待垃圾收集。
如果持久化消息 在被消费之前RabbitMQ 重启,那么 Rabbit 会自动重建交换器和队列(以及绑定),并重新发布持久化日志文件中的消息到合适的队列。
76.vhost 是什么?起什么作用?
vhost 可以理解为虚拟 broker ,即 mini-RabbitMQserver。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的 是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手 段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。
(个人理解是类似于:当tomcat里多个项目的主机名有重复的情况时,用vhost不会起冲突)
77.如何设置消息的过期时间?
1)设置队列属性,队列中所有消息都有相同的过期时间
2)对消息本身进行单独设置,每条消息的 TTL 可以不同
3)如果两种方法一起使用,则消息的 TTL 以两者之间较小的那个数值为准
78.如何实现延时队列?
使用死信交换机。消息投递到一个没有消费者的队列中,为这个队列指定死信队列,当消息达到设置过期时间还没有被消费时将
会被发布到死信队列中,而消费者订阅死信队列直接消费到了一份延时消息。
声明交换器类型为 x-delayed-message 来标示此交换机为延时交换机。
发送消息时在 header 中添加”x-delay”参数来控制消息的延时时间
79.如何指定消息的优先级?
设置队列的 maxpriority 参数,RabbitMQ 中消息的优先级默认是 0,最大值是 10
(个人理解:优先级只在多条消息同时存在的时候才能体现效果!)