大纲
1.什么是消息中间件
2.消息中间件的技术选型
3.RocketMQ的架构原理和使用方式
4.消息中间件路由中心的架构原理
5.Broker的主从架构原理
6.高可用的消息中间件生产部署架构
7.部署一个小规模的RocketMQ集群进行压测
8.如何对RocketMQ集群进行可视化的监控和管理
9.进行OS内核参数和JVM参数的调整
10.如何对小规模RocketMQ集群进行压测
11.消息中间件集群生产部署规划的思维导图
1.什么是消息中间件
(1)什么是同步
(2)如何基于消息中间件实现异步
(3)消息中间件的作用
(1)什么是同步
通常一个公司里可能会存在多个业务系统,这些业务系统之间的通信都是通过接口调用来进行的。现在假设用户在浏览器或者APP向系统A发起一个请求,系统A收到这个请求后会马上去调用系统B的接口。当系统B的接口返回响应结果给系统A后,系统A才能返回结果给用户。

在这种情况下,用户发起一个请求,系统A收到请求,接着系统A必须马上去调用系统B的接口,直到系统B的接口返回了,系统A才能返回结果给用户,这种模式就是所谓的"同步调用"。
这个同步的意思,就是各个系统的联动都是同步依次进行的。一个系统先动,然后马上带动另外一个系统一起动,最后大家依次处理完后再返回结果。这就是同步调用通俗的解释。
(2)如何基于消息中间件实现异步
现在假设在系统A和系统B之间加入了一个"消息中间件",也就是MQ,即消息队列。加入了"消息中间件"以后,系统A和系统B之间是怎么通信的?很简单,之所以叫"消息中间件",是因为它里面最核心的就是"消息"。
系统A一般会发送一条消息给MQ,接着系统A就认为自己的工作干完了,直接返回结果给用户。这时系统A跟系统B就没什么关系了,因为系统A要做的事情只是接收请求,发送消息到MQ,然后就返回结果给用户。然后系统B根据自己的情况,可能会在系统A投递消息到MQ之后的1秒内、1分钟之后,甚至1小时后,从MQ里获取到一条属于自己的消息,然后根据消息完成自己的工作。

在这种情况下,系统A和系统B有没有实现通信?有,因为系统A发了一个消息给MQ,系统B从MQ里获取了一个消息,干了自己该干的工作。
那么系统A跟系统B之间是不是同步调用?不是,因为系统A仅仅是发消息到MQ,至于系统B什么时候获取消息,有没有获取消息,它是不管的。所以这种情况下,我们说系统A和系统B是"异步调用"。
所谓异步调用,意思就是系统A先处理自己的工作,然后想办法通知系统B。但是系统B什么时候收到通知、什么时候去处理自己的工作,这些系统A不管,和系统A没关系。但是最终在正常下,系统B总会获取到这个通知,然后处理自己的工作。
这种情况下,并不是系统A动了,系统B就马上同步动,他们不是同步的。而是系统A动了,但是系统B可能过一会儿才动,他们的步调是不一样的,所以是异步的。这就是所谓的"异步调用"通俗的解释。
(3)消息中间件的作用
消息中间件,其实就是一种系统,它自己独立部署。然后让两个系统之间通过发消息和收消息,来进行异步的调用,而不是仅仅局限于同步调用。消息中间件的主要作用有三个:异步化提升性能、降低系统耦合、流量削峰。
比如现在假设系统A要调用系统B。然后系统A先执行一些操作,需要耗费20ms,接着系统B执行一些操作要耗费200ms,总共就要耗费220ms。这时等系统A和系统B都处理完,才能返回结果给用户,要等待220ms。

一.异步化提升性能
如果在系统A和系统B之间加一个MQ:系统A干完自己的事情,就20ms,然后发送一条消息到MQ,就5ms,然后就返回结果给用户了。也就是说,用户仅仅等待25ms就收到了结果。然后系统B从MQ里获取消息,接着花费200ms去执行。但是这个200ms就跟用户没关系了,用户早就收到结果了,也不关心你花200ms还是2s去干自己的事。

这样对用户来说,就从原来等待220ms返回结果,变成现在只要25ms就可以返回结果了。可见,消息中间件可以用来提升系统性能。
二.降低系统耦合
如果系统A同步调用系统B,这其实属于系统间的耦合,系统A和系统B互相之间会有影响。如果系统B突然出现故障,会导致系统A在调用系统B的时候感知到这个故障。由于系统B故障了,所以系统A对系统B的调用失败。系统A就得返回异常给用户,以及在后续处理这个异常。

假设在系统A和系统B之间加入一个消息中间件。在这种情况下,系统A对系统B的调用仅仅是发送一个消息到MQ,然后就直接返回给用户了,后面对系统B就不管了。此时系统B如果出现了故障,对系统A根本没影响,系统A也感觉不到。系统B出现故障就成了它自己的事,它要等故障恢复后继续去完成它的工作,此时对系统A没任何影响了。

为什么会有这样的效果呢?因为通过引入MQ,两个系统实现了异步化调用,也就实现了解耦。系统A并没有跟系统B耦合,所以互相之间并没有任何影响。所以消息中间件还能让两个系统解耦,让它们互相之间没有任何影响。
三.流量削峰
消息中间件还有一个特别好的功能叫流量削峰。假设系统A是不操作数据库的,因此只要多部署几台机器,就可以抗下每秒1万的请求。比如部署个20台机器,就可以轻松抗下每秒上万请求。然后系统B是要操作一台数据库服务器的,这台数据库服务器的上限是每秒接收6000请求。那么系统B无论部署多少台机器都没有用,因为它依赖的数据库最多只能每秒接收6000请求。

比如系统A在1秒内收到了1万请求,然后把这1万请求转发给系统B。由于系统B要操作数据库,每秒最多能处理6000请求,所以此时系统B是抗不下这1万请求的,一定会压垮数据库。因此可以通过引入MQ来解决这个问题,MQ抗高并发的能力远远高于数据库。同样配置下,如果数据库可以抗每秒6000请求,那么MQ可以抗每秒几万请求。
为什么呢?因为数据库复杂,它要能够支持执行复杂的SQL语句,支持事务等复杂的机制,支持对数据进行增删改查等。所以一般数据库单服务器也就支撑每秒几千的请求。但MQ就不一样了,它的核心功能就是让系统A发消息给它,再让系统B从它这里获取消息。这个就简单得多了,所以同等机器配置下,MQ一般都能抗几万并发请求。
所以只要引入MQ,就可以让系统A把每秒1万请求都作为消息直接发送到MQ里,MQ可以轻松抗下这每秒1万请求。接着系统B只要慢慢的从MQ里获取消息然后执行数据库读写操作即可,这个获取消息的速度是系统B自己可以控制的。所以系统B完全可以用一个比较低的速率获取消息然后写入数据库,保证对数据库的QPS不超过它的极限值6000。

这时因为系统A发送消息到MQ很快,系统B从MQ消费消息很慢,所以MQ里自然会积压一些消息。不过不要紧,MQ一般都是基于磁盘来存储消息的,所以适当积压一些消息是可以的。当系统A的高峰过去,每秒可能就恢复到1000请求,此时系统B还是以每秒6000请求的速度获取消息写入数据库,那么自然MQ里积压的消息就会慢慢被消化掉了。
所以这就是使用MQ进行流量削峰的效果:系统A发送过来的每秒1万请求是一个流量洪峰,然后MQ直接给扛下来了,都存储到自己本地磁盘。这个过程就是流量削峰的过程,瞬间把一个洪峰给削下来,让系统B后续慢慢获取消息来处理。
2.消息中间件的技术选型
(1)订单系统的很多问题都可以用MQ来解决
(2)要在订单系统里用MQ技术应从哪一步开始
(3)Kafka、RabbitMQ以及RocketMQ的调研对比
(4)活跃的社区和广泛的运用
(1)订单系统的很多问题都可以用MQ来解决
举个例子,支付订单流程中步骤过多,导致性能很差。这个问题可以用MQ来解决,让订单系统仅仅完成最核心的一些步骤和调用,然后发送消息到MQ,比如仓储系统之类的就可以从MQ里获取消息,然后慢慢的执行一些比较耗时的步骤。
还有比如订单系统在退款时,可能会遇到第三方支付系统退款失败的问题,从而影响整个退款流程的失败。这个问题也可以用MQ解决,可以让订单系统在退款时完成公司内部各个系统的流程,然后发送消息到MQ,由一个专门的服务去负责调用第三方支付系统,处理可能出现的失败。
在双11大促活动时,也可以让瞬间涌入的大量下单请求到MQ里去排队,然后让订单系统在后台慢慢的获取订单,以数据库可以接受的速率完成操作,避免瞬间请求量过大击垮数据库。
(2)要在订单系统里用MQ技术应从哪一步开始
要做一些技术架构的升级,引入一些新的技术,当然要从技术调研开始。其实技术调研就是对一个技术去找到一些业内常用的开源实现,然后对各种不同的实现都进行一些调研,对比一下它们的优劣势,看看谁比较符合我们的需求,谁比较适合我们来使用;
具体来说,对于前面订单系统的情况,现在只有一个MQ的概念,但是要考虑一下:
一.业内常用的MQ有哪些
二.每一种MQ各自的表现如何
三.这些MQ在同等机器条件下,能抗多少QPS
四.性能有多高(发送一条消息给它要2ms还是20ms)
五.可用性能否得到保证(部署MQ的机器挂了怎么办)
然后还得考虑:
一.它们会不会丢失数据
二.如果需要的话能否让它们进行线性的集群扩容
三.消息中间件经常需要使用的一些功能都有吗(比如说延迟消息、事务消息、消息堆积、消息回溯、死信队列等)
另外还得考虑这些MQ的文档是否齐全、社区是否活跃、在行业内是否广泛运用、是用什么语言编写的。把这些事情都搞清楚了,那么就完成了技术调研,可以全面的对比各种MQ的优劣势,然后从中选择一个最适合的来使用。
(3)Kafka、RabbitMQ以及RocketMQ的调研对比
一般国内常用的MQ技术有四种实现:ActiveMQ、Kafka、RabbitMQ、RocketMQ。但是其中ActiveMQ主要是几年以前较多公司使用,现在国内用的公司都很少了。因此下面主要针对Kafka、RabbitMQ、RocketMQ三种技术进行介绍。
一.Kafka的优势和劣势
首先Kafka的吞吐量几乎是行业里最优秀的,在常规的机器配置下,一台机器的QPS就可以达到每秒十几万,相当的强悍。Kafka性能也很高,基本上发送消息给Kafka是毫秒级的性能。Kafka可用性也很高,Kafka是支持集群部署的,其中部分机器宕机是可以继续运行的。
Kafka的劣势一是:存在数据丢失的问题。因为Kafka收到消息之后会写入一个内存缓冲区里,并没有直接落地到物理磁盘上去。所以要是机器本身故障了,可能会导致内存缓冲区里的数据丢失。
Kafka的劣势二是:功能非常单一。主要是支持发送消息给它,然后从里面消费消息,其他就没有什么额外的高级功能了。所以基于Kafka有限的功能,可能适用的场景并不是很多。
因此综上所述得出Kafka在行业里的一个使用标准:就是把Kafka用在用户行为日志的采集和传输上。比如大数据团队要收集APP上用户的一些行为日志,这种日志就是用Kafka来收集和传输的。因为那种日志适当丢失数据是没有关系的,而且一般量特别大,要求吞吐量要高,一般就是收发消息,不需要太多的高级功能,所以Kafka是非常适合这种场景的。
二.RabbitMQ的优势和劣势
在RocketMQ出现之前,国内大部分公司都从ActiveMQ切换到RabbitMQ来使用,包括很多一线互联网大厂,而且直到现在都有很多中小型公司在使用RabbitMQ。
RabbitMQ的优势在于可以保证数据不丢失,也能保证高可用性,即集群部署的时候部分机器宕机可以继续运行,然后支持部分高级功能,比如死信队列、消息重试等,这些是它的优点。
RabbitMQ缺点一是:吞吐量是比较低的,QPS一般就是几万的级别。所以如果遇到特别高并发的情况下,支撑起来是有点困难的。而且它进行集群扩展的时候(也就是加机器部署),还比较麻烦。
RabbitMQ缺点二是:开发语言是erlang,国内很少有精通erlang语言的工程师。因此也没办法去阅读它的源代码,甚至修改它的源代码。
所以现在行业里的一个情况是,很多BAT等一线互联网大厂都切换到使用更加优秀的RocketMQ了。但是很多中小型公司觉得RabbitMQ基本可以满足自己的需求还在继续使用中,因为中小型公司并不需要特别高的吞吐量,RabbitMQ已经足以满足他们的需求了,而且也不需要部署特别大规模的集群,也没必要去阅读和修改RabbitMQ的源码。
三.RocketMQ的优势和劣势
RocketMQ是阿里开源的消息中间件,非常靠谱,它几乎同时解决了Kafka和RabbitMQ的缺陷。
RocketMQ的吞吐量也同样很高,单机QPS可以达到10万以上,而且可以保证高可用性、可以通过配置保证数据绝对不丢失、可以部署大规模的集群、还可以支持各种高级的功能,比如延迟消息、事务消息、消息回溯、死信队列、消息积压等。同时,RocketMQ是基于Java开发的,符合国内大多数公司的技术栈,工程师很容易就可以阅读它的源码,甚至是修改它的源码。
所以现在国内很多一线互联网大厂都切换为使用RocketMQ了。它们需要RocketMQ的高吞吐量,大规模集群部署能力,以及各种高阶的功能去支撑自己的各种业务场景,同时还可以根据自己的需求定制修改RocketMQ的源码。
RocketMQ是非常适合用在Java业务系统架构中,因为它很高的性能表现、高阶功能的支持,可以解决各种业务问题。当然RocketMQ也有一点美中不足的地方,就是RocketMQ的官方文档相对简单一些。
(4)活跃的社区和广泛的运用
最后一点,基本上Kafka、RabbitMQ和RocketMQ的社区都还算活跃,而且基本应用广泛。尤其是Kafka和RabbitMQ,目前Kafka几乎是国内大数据领域日志采集传输的标准。RabbitMQ在各种中小公司里运用极为广泛,RocketMQ也是开始在一些大公司和其他公司里快速推行中。
3.RocketMQ的架构原理和使用方式
(1)MQ如何集群化部署来支撑高并发访问
(2)MQ如果要存储海量消息应该怎么做
(3)Broker宕机时如何保障高可用
(4)如何进行数据路由访问正确的Broker
关于RocketMQ的两个问题:
一.如何集群化部署来承载高并发访问?
二.要存储海量消息,如何实现分布式存储架构?
(1)MQ如何集群化部署来支撑高并发访问
当RocketMQ部署在一台机器上,即使这台机器配置很高,但一般来说一台机器也就支撑10万+的并发访问。假设有大量的系统都要往RocketMQ里高并发的写入消息,可能有每秒几十万请求。此时由于RocketMQ是可以进行集群化部署的,通过部署RocketMQ在多台机器上,假设每台机器都能抗10万并发,然后只要让几十万请求分散到多台机器上、让每台机器承受的QPS不超过10万即可。如下图示:

(2)MQ如果要存储海量消息应该怎么做
MQ会收到大量的消息,这些消息并不是马上就会被所有的消费方获取过去消费的。所以一般MQ都得把消息在自己本地磁盘存储起来,然后等待消费方获取消息去处理。
既然如此,MQ就得存储大量的消息,可能是几百万条,可能几亿条,甚至万亿条。这么多的消息在一台机器上肯定是没法存储的,RocketMQ是如何分布式存储海量消息的呢?
其实发送消息到MQ的系统会把消息分散发送给多台不同的机器。假设一共有1万条消息,分散发送给10台机器,可能每台机器就是接收到1000条消息,如下图示:

其次,每台机器上部署的RocketMQ进程一般称之为Broker。每个Broker都会收到不同的消息,然后会把这些消息存储在自己的磁盘文件里。假设有1亿条消息,然后有10台机器部署了RocketMQ的Broker,理论上可让每台机器存储1000万条消息。
所以,RocketMQ会通过分布式存储来实现存储海量消息的。分布式存储就是把数据分散在多台机器上来存储,每台机器存储一部分消息,这样多台机器加起来就可以存储海量消息了。

(3)Broker宕机时如何保障高可用
如果一台Broker突然宕机了怎么办?那不就会导致RocketMQ里一部分的消息就没了吗?这就会导致MQ的不可靠和不可用,这个问题怎么解决?
RocketMQ的解决思路是使用Broker主从架构以及多副本策略。简单来说,Broker有Master和Slave两种角色。Master Broker收到消息之后会同步给Slave Broker,这样Slave Broker上就能有一模一样的一份副本数据,这样同一条消息在RocketMQ整个集群里就有两个副本了:一个在Master Broker里,一个在Slave Broker里。这时候如果任何一个Master Broker出现故障,还有一个Slave Broker上有一份数据副本,可以保证数据不丢失,还能继续对外提供服务,保证了MQ的可靠性和高可用性。

最低0.47元/天 解锁文章
1376

被折叠的 条评论
为什么被折叠?



