最近刷题,看到了有问中间件的题目,于是整理了一些中间件的知识,大多是在小破站上的笔记,仅供大家参考~
主要分为七个部分来分享:
一、常见的中间件
二、什么是队列?
三、常见消息队列MQ的比较
四、队列的优点和缺点
五、消息队列的原理
六、为什么使用消息队列?
七、队列的测试点
八、高频软件测试面试题
一、常见的中间件
Redis:缓存中间价
MQ:消息队列中间件
Nginx:Web服务器中间件
二、什么是队列?
队列(Queue)是一种常见的数据结构,用于按照先进先出(FIFO,First In First Out)的原则管理元素。这意味着最先被添加到队列的元素将首先被移除。队列的操作通常包括两个主要动作:入队(Enqueue)和出队(Dequeue) 。
三、常见消息队列MQ的比较
ActiveMQ:比较老,一般不用了
RabbitMQ:大部分公司够用了,除非像阿里并发那么大的公司
RocketMQ:阿里在用的
Kafka:主要用于记录日志,例如淘宝的足迹功能
四、队列的优点和缺点
1、优点
解耦
异步
流量削峰填谷
2、缺点
可用性低
复杂度
一致性问题(例如消息丢失,消息重复等等,导致两个系统数据不一致)
五、消息队列的原理
下面以用户下单这个场景为例,分享下整个过程:
一)生产者如何将消息可靠投递到消息队列(MQ):
- 客户端发送消息到消息队列MQ。
- 消息队列MQ将消息进行持久化,并向客户端发送 Ack 消息。由于网络问题可能导致 Ack 消息无法及时发送至客户端,因此客户端在等待一段超时时间后,会重新传送消息。
- 客户端在收到 Ack 消息后,确认消息已被成功投递。
二) 消息队列如何将消息可靠投递给消费者:
- 消息队列MQ将消息推送给客户端(或者客户端通过拉取方式获取消息)。
- 客户端接收并完成业务逻辑处理。
- 客户端向消息队列MQ发送 Ack 消息,通知消息队列删除该消息。由于网络问题可能导致 Ack 失败,客户端会收到重复的消息,从而引发了消费幂等性的问题。
- 消息队列删除已被成功消费的消息。
六、为什么使用消息队列?
主要用于解耦、异步、流量削峰填谷。
1、解耦
如果不加中间件MQ,订单系统直接调用库存系统,当库存系统出现故障时,用户就会下单失败。加了中间件之后,就不会出现下单失败了,用户下单之后,把订单id传给MQ,监控系统发现库存系统挂了之后,立马修复,最后还是可以下单成功。
2、异步
如果不加中间件MQ,下单的时候,订单系统会同步调用库存系统,有了MQ之后,下单后,订单系统只要把订单id传给MQ即可。
3、流量削峰填谷
例如B是订单系统,C是库存系统,C系统每分钟只能承受1W的并发,现在突然有30W的并发,那先把订单消息发送给MQ,C系统从MQ拉取信息,处理速度还是每分钟1W,最后花费30分钟来处理,用时间换空间。
七、队列的测试点
一)正向的业务逻辑测试
1、数据正确性
产者推送消息,消费者能正常消费信息,比如消息发送的字段以及接收的字段有无缺失,且保持一致
2、时序
不同时序推送消息,先后顺序是否与预期一致。
注意队列优先级,可使用事务解决
二)反向的异常测试
1、消息推送失败是否有重试
如因为网络原因导致的消息丢失,是否有补发和重试机制(用定时任务跑),通常情况下Produce会设置补发。
2、避免重复消息
例如生产者重复推送同一条数据 ,由于RocketMQ天生就有消息重复发送的机制,所以当产生消息重新发送时,如何对此问题进行处理?通常情况下要对消费端的服务做幂等处理,数据库里添加唯一索引,保证消息不被重复消费。
三)性能测试(消费积压)
主要就是通过性能测试,看看在高并发访问的情况下,系统正确处理消息的能力,是否会出现消息队列拥堵,宕机等情况。
解决消费积压的办法:
- 首先要快速解决消息积压问题,比如加大consumer消费数量,消费频次;
- 临时紧急扩容,比如临时征用10倍的机器来部署consumer程序,这个程序部署上去消费积压的数据,等快速消费完积压数据之后,得恢复原先部署架构,重新用原先的consumer机器来消费消息。
八、高频软件测试面试题
1、如何保证消息不丢失?
消息队列将收到的消息持久化到磁盘中,以保证消息队列异常或重启的情况下,消息不会丢失
2、消息队列的工作原理是什么?
生产者创建消息并将其发送到消息队列, 消费者从消息队列中接收消息,并异步地处理这些消息, 消费者在成功处理消息后向消息队列发送确认(Acknowledge)消息,通知队列可以删除已处理的消息。