当前位置: 首页 > 科技观察

专访-为什么一定要用消息中间件?

时间:2023-03-13 06:50:09 科技观察

这篇文章开始,我们会告诉你消息中间件的高频面试问题,同时也会涵盖MQ中间件的一些常见技术问题。如果面试官看到你简历中写的使用MQ中间件的经历,很可能会有以下问题:1、贵公司在生产环境中使用的是什么消息中间件?2、为什么要在系统中引入消息中间件?3、引入消息中间件有什么优缺点?好吧,让我们一一分析吧!1、你们用的什么消息中间件?首先可以说一下你们公司选择的是什么消息中间件,比如RabbitMQ,然后给大家初步分析一下不同MQ中间件技术的选择。举个例子:比如ActiveMQ就是一个老牌的消息中间件。国内很多公司过去用的很广泛,功能也很强大。但问题是无法确认ActiveMQ能否支持互联网公司高并发、高负载、高吞吐的复杂场景,在国内互联网公司实现的也很少。而且一些传统企业更多的使用ActiveMQ来做异步调用和系统解耦。然后就可以说说RabbitMQ了,它的优点是可以支持高并发、高吞吐、高性能,并且有非常完善和方便的后台管理接口使用。另外还支持集群,高可用部署架构,高可靠消息支持,功能比较齐全。而且经过调研,国内各大互联网公司部署大规模RabbitMQ集群支撑自身业务的案例很多,国内也有很多中小型互联网公司在使用RabbitMQ。另外,RabbitMQ的开源社区非常活跃,使用频率更高的迭代版本修复发现的bug,进行各种优化。因此,经过综合考虑,公司采用了RabbitMQ。但是RabbitMQ也有一个缺陷,就是它是基于erlang语言开发的,所以很难对里面的源码进行分析,也很难进行深入的源码定制和改造。毕竟需要扎实的erlang语言基础。然后我们可以说说阿里巴巴开源的RocketMQ。通过了阿里巴巴生产环境高并发、高吞吐的测试。性能优异,支持分布式事务等特殊场景。而且RocketMQ是基于Java语言开发的,适合深入阅读源码。如有需要,可在源码层面解决线上生产问题,包括对源码的二次开发和改造。另一个是Kafka:Kafka提供的消息中间件,功能明显少了很多,比上面提到的MQ中间件要少很多。但是Kafka的优势在于它是为超高吞吐实时日志采集、实时数据同步、实时数据计算等场景而设计的。因此,在大数据领域,Kafka常与实时计算技术(如SparkStreaming、Storm、Flink等)结合使用。但是在传统的MQ中间件使用场景中很少使用。PS:如果你没有在自己的电脑上部署过上面的一些MQ技术,也没有写过几个helloworld的经验,建议自己去各个技术的官网找helloworld的demo,自己运行一下。2、为什么要用消息中间件?回答这个问题,先说说消息中间件的常见使用场景,再结合自己系统的相应使用场景,说说在自己的系统中引入消息中间件解决的问题。1)系统解耦假设你有一个系统A,这个系统A会产生一个核心数据,现在下游有系统B、C需要这个数据。很简单,A系统只是调用B系统和C系统的接口,向它们发送数据。整个过程如下图所示:但是现在如果有系统D、系统E、系统F、系统G等,其他十几个系统会逐渐需要这个核心数据吗?如下图所示:不要以为这是在开玩笑。一个大型系统往往分为几十个甚至上百个子系统,每个子系统对应N个以上的服务。这些系统彼此错综复杂地联系在一起。关系网络。如果一个系统产生了一个核心数据,那么无数其他下游系统可能需要这个数据来实现各种业务逻辑。这时候如果你采用上面的模型来设计系统架构,那你负责系统A的同学肯定会烦死的。首先,有一个人来找他,要求向一个新的系统H发送数据,系统A的同学需要修改代码,然后在那个代码中加入调用新系统H的过程。过了一会儿,系统B是一个即将下线的旧系统。告诉A系统的同学:不要给我发数据,然后A系统又修改了代码,不再发给B系统了,万一下游系统突然宕机了怎么办?系统A的调用代码会不会抛出异常?那么系统A的同学就会收到告警,说有异常,最后他得去关心是哪个下游系统宕机了。因此,在实际的系统架构设计中,如果全部采用系统耦合的方式,在某些场景下是绝对不合适的,系统耦合度太严重了。并且相互之间的耦合并不是核心环节的调用,而是一些非核心场景(比如上面提到的数据消费)导致系统耦合,会严重影响上下游系统的开发和维护效率。因此,在上述系统架构中,可以使用MQ中间件来实现系统解耦。系统A将自己的核心数据发送给MQ,任何有兴趣的下游系统都可以自己消费,不需要就取消数据消费,如下图:2)异步调用假设你有一个系统call环节是系统A调用系统B,一般需要20ms;系统B调用系统C,一般需要200ms;系统C调用系统D,一般需要2s,如下图:现在最大的问题是:用户请求一个请求的速度极慢,因为需要20ms+200ms+2000ms(2s)=2220ms,即超过2秒,完成一个链接。但实际上,链路中系统A调用系统B,系统B调用系统C,两步只用了220ms。因为引入了系统C调用系统D的步骤,导致最终链接执行时间超过2秒,直接降低了10倍的链接调用性能。这就是导致链接执行过慢的罪魁祸首。那么这个时候我们可以想一想,是不是可以把系统D从链接中提取出来,进行异步调用呢?其实很多业务场景是可以允许异步调用的。比如:你平时点外卖,点击下单然后付款。这时候扣款,创建订单,通知商家给你准备菜品。接下来需要找骑手给你送外卖吗?寻找骑手的过程需要一套复杂的算法来实现调度,比较耗时。但实际上,比几十秒晚一点完成骑手调度是可以的,因为其实你付钱的那一刻就没有必要马上给你找到好的骑手,也没有这个必要。那我们能不能把找骑手给你送外卖的环节做成异步的,哪怕有几十秒的延迟,只要我们在一定的时间内给你找到骑手就可以了?送餐就可以了。这是否让您下单外卖变得超快?支付成功后,您可以直接创建订单,扣款,并通知商家立即为您准备食物。这个过程可能需要数百毫秒。那么后台异步通过调度算法可能需要几十秒才能找到骑手送餐,但这一步不影响我们快速下单。当然,我们并不是说大家熟悉的那些外卖平台的技术架构一定要这样实现,只是用一个生活中常见的例子来给大家说明一下。所以上面的链接也是一样的。如果业务流程支持异步,是不是可以考虑把系统C对系统D的调用提取出来做成异步的,而不是放到链接里同步顺序调用。这样,实现思路是SystemA->SystemB->SystemC,耗时220ms,直接成功。然后系统C向MQ中间件发送消息,系统D在消费消息后缓慢异步执行2秒的业务流程。这样一来,核心环节的执行性能直接提升了10倍。整个过程如下图所示:3)流量调峰假设你有一个系统,通常每秒有数百个请求。系统部署在8核16G的机器上,正常处理就ok了。每秒上百个请求可以轻松抵挡,但是如下图,在高峰期突然来了每秒上千个请求,出现了瞬时流量高峰。这个时候你的选择是建10台机器来抵御Live每秒上千请求的瞬时峰值?那么如果瞬时峰值只有一天半小时,那么直接降到每秒几百个请求。如果在线部署很多机器,那么每台机器每秒可以处理几十个请求。是不是有点浪费机器资源?大部分时候一台机器每秒几百个请求就够了,但是为了抵御每天的瞬时高峰,部署了10台机器,每天只能用半个小时,其他时间都是浪费资源。但是如果你只部署一台机器,会导致你的系统在瞬间的峰值时不堪重负,因为你是绝对无法抗拒每秒上千请求的峰值的。此时,我们可以使用MQ中间件进行流量削峰。所有机器前面都部署了一层MQ,每个人都可以很轻松的接收到每秒几百个请求的消息。一旦到了瞬时高峰期,MQ里面就可以积压每秒几千个请求,然后那台机器就可以慢慢处理消费了。高峰期结束后,经过一段时间的消费,就会消费掉MQ中积压的数据。这是MQ的一个很典型的用法,用有限的机器资源去承载高并发的请求。如果业务场景允许异步调峰,那么在高峰期,部分请求会积压在MQ中,高峰期后,后台系统会在一定时间内消费。如果完成后没有积压,那么这个技术方案就非常适合。