龙城区建设局网站,广告推广怎么做最有效,mvc做网站用的多不多,中职高一网站建设试题大家好#xff0c;我是陶然同学#xff0c;软件工程大三即将实习。认识我的朋友们知道#xff0c;我是科班出身#xff0c;学的还行#xff0c;但是对面试掌握不够#xff0c;所以我将用这100多天更新Java面试题#x1f643;#x1f643;。 不敢苟同#xff0c;相信大… 大家好我是陶然同学软件工程大三即将实习。认识我的朋友们知道我是科班出身学的还行但是对面试掌握不够所以我将用这100多天更新Java面试题。 不敢苟同相信大家和我一样都有一个大厂梦作为一名资深Java选手深知面试重要性接下来我准备用100天时间基于Java岗面试中的高频面试题以每日3题的形式带你过一遍热门面试题及恰如其分的解答。当然我不会太深入因为我怕记不住 因此不足的地方希望各位在评论区补充疑惑、见解以及面试中遇到的奇葩问法希望这100天能够让我们有质的飞越一起冲进大厂让我们一起学juan起来 RabbitMQ工作原理 Broker接收和分发消息的应用RabbitMQ Server 就是 Message Broker
Virtual host出于多租户和安全因素设计的把 AMQP 的基本组件划分到一个虚拟的分组中类
似于网络中的 namespace 概念。当多个不同的用户使用同一个 RabbitMQ server 提供的服务时
可以划分出多个 vhost每个用户在自己的 vhost 创建 exchangequeue 等
Connectionpublisherconsumer 和 broker 之间的 TCP 连接
Channel如果每一次访问 RabbitMQ 都建立一个 Connection在消息量大的时候建立 TCP
Connection 的开销将是巨大的效率也较低。Channel 是在 connection 内部建立的逻辑连接如
果应用程序支持多线程通常每个 thread 创建单独的 channel 进行通讯AMQP method 包含了
channel id 帮助客户端和 message broker 识别 channel所以 channel 之间是完全隔离的。
Channel 作为轻量级的Connection 极大减少了操作系统建立 TCP connection 的开销
面试题rabbitmq为什么是基于channel(通道)去处理而不是连接
一个应用有多个线程需要从rabbitmq中消费或是生产消息如果建立很多个Connection连接对
操作系 统而言建立和销毁tcp连接是很昂贵的开销如果遇到使用高峰性能瓶颈也随之显现。
rabbitmq采用类似nio的做法连接tcp连接复用不仅可以减少性能开销同时也便于管理。
Queue消息最终被送到这里等待 consumer 取走
Bindingexchange 和 queue 之间的虚拟连接binding 中可以包含 routing keyBinding
信息被保存到 exchange 中的查询表中用于 message 的分发依据
RabbitMQ消息丢了怎么办 其中的每一步都可能导致消息丢失常见的丢失原因包括
发送时丢失
生产者发送的消息未送达exchange 消息到达exchange后未到达queue
MQ宕机queue将消息丢失consumer接收到消息后未消费就宕机
针对这些问题RabbitMQ分别给出了解决方案
生产者确认机制mq持久化消费者确认机制失败重试机制
生产者确认机制
RabbitMQ提供了publisher confirm机制来避免消息发送到MQ过程中丢失。这种机制必须给每个消
息指定一个唯一ID。消息发送到MQ以后会返回一个结果给发送者表示消息是否处理成功。
返回结果有两种方式
publisher-confirm发送者确认
消息成功投递到交换机返回ack消息未投递到交换机返回nackpublisher-return发送者回执消息投递到交换机了但是没有路由到队列。返回ACK及路由失败原因。消息持久化
生产者确认可以确保消息投递到RabbitMQ的队列中但是消息发送到RabbitMQ以后如果突然宕
机也可能导致消息丢失。
要想确保消息在RabbitMQ中安全保存必须开启消息持久化机制。
交换机持久化队列持久化消息持久化
消费者消息确认
RabbitMQ是阅后即焚机制RabbitMQ确认消息被消费者消费后会立刻删除。
而RabbitMQ是通过消费者回执来确认消费者是否成功处理消息的消费者获取消息后应该向
RabbitMQ发送ACK回执表明自己已经处理消息。
消费失败重试机制
当消费者出现异常后消息会不断requeue重入队到队列再重新发送给消费者然后再次异常再次requeue无限循环导致mq的消息处理飙升带来不必要的压力。
本地重试
开启本地重试时消息处理过程中抛出异常不会requeue到队列而是在消费者本地重试重试达到最大次数后Spring会返回ack消息会被丢弃
失败策略
在之前的测试中达到最大重试次数后消息会被丢弃这是由Spring内部机制决定的。
在开启重试模式后重试次数耗尽如果消息依然失败则需要有MessageRecovery接口来处
理它包含三种不同的实现
RejectAndDontRequeueRecoverer重试耗尽后直接reject丢弃消息。默认就是这种方式ImmediateRequeueMessageRecoverer重试耗尽后返回nack消息重新入队RepublishMessageRecoverer重试耗尽后将失败消息投递到指定的交换机
比较优雅的一种处理方案是RepublishMessageRecoverer失败后将消息投递到一个指定的专门
存放异常消息的队列后续由人工集中处理。
RabbitMQ消息重复消费 造成重复消费的原因
MQ向消费者推送message消费者向MQ返回ack告知所推送的消息消费成功。但是由于网络波
动等原因可能造成消费者向MQ返回的ack丢失。MQ长时间一分钟收不到ack于是会向消
费者再次推送该条message这样就造成了重复消费。
解决重复消费的办法
用从存储redis或者mysql记录一下已经消费的message的id当message被消费前先去存储中
查一下消费记录没有该条message的id则正常消费返回ack有该条message的id的话不用消费
直接返回ack给MQ。
当然实际生产中的话选用redis是比较好的选择毕竟查mysql要进行磁盘IO效率要低得多而且
绝大多数重复消费都是由于MQ没有收到消费者的ack于是造成MQ再次向消费者进行同一条
message的投递。所以message的消费记录其实我们并不需要一直记录只需要保存一段时间当
下次投递过来的时候消费者能查到消费记录然后准确返回ack给MQ就行。
以下是一个使用redis解决重复消费的示例步骤
监听器接收MQ队列中的数据。
利用redis的setnx命令以消息唯一id为key以消息内容为value超时时间设置为10分钟存入
redis中。
如果能够成功存入说明没有重复消费则处理业务处理完业务后返回ack或者nack确认。
如果存不进去则说明重复消费直接返回ack确认的回调信息就可以了。