五分钟学后端技术:如何学习后端工程师必学的消息队列

      最后更新:2020-04-01 12:52:40 手机定位技术交流文章

      原始语句

      作者:黄

      重印时,请在文章开头注明出处和作者。

      什么是消息队列

      “拉比吗?”“卡夫卡?”“火箭男?”本文将带您了解消息队列的一些基本理论。如果你是一个老手,你可以从这篇文章中学到一些你以前没有注意到的关于消息队列的重要概念。如果你是新手,我相信这篇文章将是打开消息队列大门的一块砖。

      根据百度百科,一个“消息队列”是一个在消息传输过程中保存消息的容器。消息队列管理器在将消息从其源中继到其目的地时充当中介。队列的主要目的是提供路由并确保消息传递。如果发送消息时接收方不可用,消息队列将保存消息,直到消息能够成功传递。

      为什么使用消息队列

      我认为使用消息队列有两个主要优势:

      1.通过异步处理提高系统性能(削峰填谷,减少响应时间);

      2.减少系统耦合。如果面试官在面试中问你这个问题,一般情况是你在简历中加入了信息队列的内容。此时,建议您结合自己的项目进行回答。

      “大型网站的技术架构”的第4章和第7章都提到了通过消息队列来提高应用程序的性能和可伸缩性。

      在我通常的日常工作中,有许多使用消息队列的场景。例如,我有一个计划任务,需要为应用程序A安排在每天7点。计划任务系统如何告诉应用程序A?一种方法是直接调用应用程序a的RPC服务。但是,调度任务系统不能记录这么多应用程序的RPC服务,所以如果交换消息,复杂性将大大降低。

      还有一个使用消息队列的常见场景,也就是说,一些不需要及时处理的RPC调用被转换为消息,例如最典型的电子商务订单,它们必须具有高实时性要求。但是,有些信息会在用户下订单后异步发送,如用户对商品的评价和用户的退款请求。这些请求不需要实时处理,可以异步处理。这是使用消息队列的最佳时间。消息队列将帮助您存储这些挂起的消息,并在应用程序负载较低时将它们分发给应用程序,或者等待应用程序主动从消息队列获取消息。

      公共消息队列

      我们可以将消息队列与存储消息的容器进行比较。当我们需要使用信息时,我们可以把信息拿出来自己使用。消息队列是分布式系统中的重要组成部分。消息队列主要用于通过异步处理来提高系统性能、削峰和减少系统耦合。目前,有许多消息队列在使用,包括主动队列、拉比特队列、卡夫卡队列、火箭队列。

      当然,我们公司使用的大多数消息都是自行开发的消息队列产品。一方面,必须适应金融分散的情况。另一方面,自主开发的中间件有专门的团队维护,所以任何问题都可以及时处理和修复。

      让我们来看看这些开源消息队列是如何设计的,以及它们各自的优缺点。

      RabbitMQ

      兔子MQ于2007年发布,是一个基于AMQP(高级消息队列协议)的可重用企业消息系统,是目前最主流的消息中间件之一。

      主要特点:

      可靠性:提供多种技术,让您在性能和可靠性之间进行权衡。这些技术包括持久性机制、交付确认、发布者确认和高可用性机制。

      灵活路由:消息在到达队列之前通过交换机进行路由。RabbitMQ为典型的路由逻辑提供了多种内置交换机类型。如果您有更复杂的路由要求,可以一起使用这些交换机。您甚至可以实现自己的交换机类型,并将其用作RabbitMQ插件。

      消息集群:同一局域网中的多个拉比服务器可以聚合在一起,用作独立的逻辑代理。

      队列高度可用:队列可以在集群中的机器上镜像,以确保硬件问题下的消息安全;

      支持多种协议:支持多种消息队列协议;

      服务器是用Erlang语言编写的,支持你能想到的所有编程语言。

      管理界面:RabbitMQ有一个易于使用的用户界面,它使用户能够监控和管理消息代理的许多方面。

      跟踪机制:如果消息异常,RabbitMQ提供了一个消息跟踪机制,这样用户可以发现发生了什么。

      插件机制:许多插件被提供来从多个方面进行扩展,并且还可以编写自己的插件;

      优势:

      由于erlang语言的特点,mq具有良好的性能和高并发性。

      健壮、稳定、易于使用、跨平台、多语言支持、完整的文档;

      有消息确认机制和持久机制,可靠性高。

      高度可定制的路由;

      管理界面丰富,在互联网公司也广泛使用。

      社区活动频繁;

      缺点:

      尽管erlang语言结合了自身的并发优势,具有良好的性能,但它不利于二次开发和维护。

      实现了代理体系结构,这意味着消息可以在发送到客户端之前在中央节点上排队。这一特性使RabbitMQ易于使用和部署,但使其运行速度变慢,因为中央节点增加了延迟,并且封装后消息更大。

      需要学习更复杂的接口和协议,学习和维护成本更高;

      ActiveMQ

      ActiveMQ是由Apache生产的。ActiveMQ是一个JMS提供程序,它完全支持JMS1.1和J2EE 1.4规范。它速度非常快,支持多语言客户端和协议,并且可以很容易地嵌入到具有许多高级功能的企业应用环境中。

      主要特点:

      遵守JMS规范:JMS规范提供了良好的标准和保证,包括同步或异步消息分发、一次性和一次性消息分发、消息接收和订阅等。遵守JMS规范的优势在于,无论使用哪个JMS实现提供者,这些基本特性都是可用的。

      连接性:ActiveMQ提供了广泛的连接选项。支持的协议有:HTTP/S、IP组播、SSL、STOMP、TCP、UDP、XMPP等。对许多协议的支持给了ActiveMQ很大的灵活性。

      有许多支持的协议:OpenWire、STOMP、REST、XMPP、amqp

      持久性插件和安全插件:ActiveMQ提供了多种持久性选项。此外,ActiveMQ的安全性还可以根据用户需求进行身份验证和授权定制。

      支持的客户端语言有很多种:除了Java,还有:C/C++、。NET、Perl、PHP、Python、Ruby;

      代理集群:多个主动队列代理可以组成一个集群来提供服务;

      异常简单的管理:ActiveMQ是按照开发人员的想法设计的。因此,它不需要特殊的管理员,因为它提供了简单和用户友好的管理功能。有许多方法可以监控不同级别的ActiveMQ数据,包括在JConsole或ActiveMQ的Web控制台中使用JMX、处理JMX警报消息、使用命令行脚本,甚至监控各种类型的日志。

      优势:

      跨平台(JAVA编写是平台无关的,ActiveMQ可以在几乎任何JVM上运行)

      可以使用JDBC:数据可以保存到数据库中。虽然使用JDBC会降低ActiveMQ的性能,但数据库一直是开发人员最熟悉的存储介质。将消息存储在数据库中并查看。此外,该公司有一个特殊的数据库管理员,以优化数据库,并把主从分开。

      JMS支持:支持JMS的统一接口;

      支持自动重新连接;

      有一种安全机制:它支持基于shiro、jaas等的各种安全配置机制。它可以验证和授权队列/主题。

      完美的监控:它有完美的监控,包括网络控制台,JMX,壳牌命令行,乔洛基亚的休息应用编程接口;;

      友好的界面:提供的网络控制台可以满足大多数情况,并且可以使用许多第三方组件,如hawtio;

      缺点:

      区域活动没有拉比的高。

      根据其他用户的反馈,将会出现令人困惑的问题,新闻将会丢失。

      目前,焦点集中在activemq6.0产品-apollo上,对5.x的维护较少;

      不适用于有数千个队列的应用程序场景;

      火箭MQ

      火箭MQ是阿里公司的一个开源产品,用Java语言实现,在设计中引用了卡夫卡并做了一些自己的改进。信息的可靠性比卡夫卡好。RocketMQ广泛应用于ali组的订单、交易、充值、流量计算、消息推送、日志流、binglog分发等场景。

      主要特点:

      它是一种高性能、高可靠性、高实时性和分布式的队列模型消息中间件。

      生产者、消费者和队列都可以分布;

      生产者依次向一些队列发送消息。队列集称为主题。如果使用者进行广播消费,则一个使用者实例消费与此主题对应的所有队列。如果使用者使用集群,则多个使用者实例平均使用与此主题对应的队列集。

      可以保证严格的消息顺序;

      提供丰富的信息拉取模式;

      高效的用户水平可扩展性;

      实时消息订阅机制;

      十亿级消息累积能力;

      较少依赖;

      优势:

      单台机器支持10,000多个持久队列。

      RocketMQ的所有消息都是持久的。首先,它们被写入系统PAGECACHE,然后刷磁盘,这可以确保内存和磁盘都有数据的副本。

      访问时,直接从内存中读取。

      该模型简单,界面易于使用(JMS界面在许多场合并不太实用);

      性能非常好,它可以在代理中积累大量的消息;

      支持多种消费,包括集群消费、广播消费等。

      每个链路的分布式扩展设计,主从高可用性;

      开发级别相对活跃,版本更新很快。

      缺点:

      支持的客户端语言不多,目前有java和c++,其中c++还不成熟。

      RocketMQ社区的关注度和成熟度也不如前两个社区。

      没有web管理界面,并且提供了CLI(命令行界面)管理工具来查询、管理和诊断各种问题。

      没有在mq核心中实现JMS和其他接口。

      卡夫卡

      阿帕奇卡夫卡是一个分布式消息发布和订阅系统。它最初由LinkedIn基于其独特的设计实现为分布式提交日志系统,后来成为Apache项目的一部分。卡夫卡系统快速、可扩展且可持续。它的分区特性、可复制性和容错性都是很好的特性。

      主要特点:

      快速持久化使得消息能够在O(1)的开销下持久化;

      高吞吐量,在普通服务器上可以达到10W/s的吞吐量。

      。完全分布式系统。代理、生产者和消费者都支持自动分发,并自动实现负载平衡。

      支持同步和异步复制高可用性;

      支持数据批量发送和拉取;

      零拷贝:减少输入输出操作步骤;

      数据迁移和扩展对用户是透明的;

      机器可以在不停机的情况下扩展。

      其他特性:严格的消息序列、丰富的消息拉取模型、用户的高效水平扩展、实时消息订阅、十亿级消息累积能力和规则删除机制;

      优势:

      客户端语言丰富,支持java。net、php、ruby、python、go和其他语言。

      性能优异,单机写TPS约为每秒一百万条,消息大小为10字节;

      它提供了一个完全分布式的体系结构,具有复制机制、高可用性和可靠性,并且理论上支持无限的消息积累。

      支持批量操作;

      消费者使用“拉”来获取消息,消息是有序的,并且可以通过控制来确保所有消息只被消费和消费一次。

      有一个优秀的第三方卡夫卡网络管理界面——卡夫卡管理器;;

      它在日志记录领域非常成熟,被许多公司和开源项目使用。

      缺点:

      卡夫卡在一台机器上有超过64个队列/分区,负载将明显激增。队列越多,发送消息的负载越大,响应时间越长。

      使用短轮询方法,实时性取决于轮询间隔时间;

      消费失败不支持重试;

      支持消息序列,但是当代理关闭时,将出现消息混乱。

      社区更新缓慢;

      消息队列的拉和推

      有这么多消息队列,有一个区别非常重要,那就是模式,是拉好还是推好,让我们来看看

      推送意味着服务器主动向客户端发送数据。服务器收到消息后,会立即将其推送到客户端。

      推送模式的最大优势是实时性。因为服务器可以在消息可用时立即推送消息,所以消息消费没有“额外”延迟。

      但是,在消息中间件的场景中,推送模式将面临以下问题:

      需要在代理端维护消费者的状态,这不利于代理支持大量消费者场景。

      消费者的消费速度不一致,在经纪人的推动下,很难应对不同的消费者情况。

      代理很难处理消费者不能消费消息的情况(代理不能确定消费者的失败是暂时的还是永久的)

      大量的推送消息会增加消费者的负担或使消费者不堪重负。

      拉模式可以很好地应对上述情况。

      拉动模式由消费者从经纪人处主动获得。

      这带来了一些好处:

      经纪人不再需要维护消费者的状态(每次拉动都包含必要的信息,如实际的抵消)

      该状态由消费者维护,因此消费者可以根据自己的负载和其他状态轻松决定从代理获取消息的频率。

      拉模式还有聚合消息的优势。

      因为代理不能预测消息何时被写入,所以它只能在收到消息后立即推送给消费者,所以它不能在聚合消息后推送给消费者。但是,消费者主动使用拉模式来获取消息,每次它拉时,都会获取尽可能多的接近代理的消息。

      然而,与推模式相反,拉模式面临实时性的问题。

      因为消费者主动拉消息,所以实时性能与拉周期相关,并且存在“额外”延迟。如果为了减少延迟而增加拉取的执行频率,则在没有消息时可能会产生大量拉取请求(消息中间件完全解耦,代理和消费者无法预测下一个消息将在何时产生);如果频率低,延迟自然会很大。

      此外,拉模式的状态在消费者处保持,因此多个消费者需要相互协调。因此,需要在这里引入ZK或其他服务,如名称服务器,以完成消费者之间的协调。

      有没有办法在改变它们各自的缺陷的同时,将推拉的优势结合起来?答案是肯定的。

      长期投票

      使用长轮询模式,消费者主动向代理发起请求,在正常情况下,代理用消息响应消费者;在没有消息或其他特殊情况下,可以在服务器上阻止请求以延迟返回。

      长轮询不是推送模式,而是拉取模式的变体。

      所以:

      当代理始终具有可读消息时,长轮询相当于执行间隔为0的拉取模式(每次收到拉取结果时都会启动下一个拉取请求)。

      如果代理没有可读的消息,则代理会阻止该请求,并在“生成下一条消息或请求超时之前”向消费者响应该请求。"

      以上两点避免了冗余的拉请求,也解决了拉请求的执行频率导致的“额外”延迟。

      请注意,上面有一个概念:“超时前”。每个请求都有一个超时,拉请求也是如此。“超时前”是指消费者的“拉”请求超时之前。

      基于长轮询模型,无论结果是读取消息还是不读取消息,代理都需要确保在请求超时之前向消费者返回结果。

      因为消费者和代理之间的时间是有偏差的,并且从消费者向代理发送请求需要时间,所以如果请求的超时时间是5秒,并且请求在返回之前在代理端被阻塞了5秒,那么消费者将在接收到代理响应之前确定请求的超时时间。因此,代理需要确保在消费者确定请求超时之前返回结果。

      在正常实践中,请求在代理端被阻止的时间总是小于长轮询请求的超时时间。例如,如果长轮询请求的超时时间是30秒,那么Broker在收到请求后的25秒内肯定会返回结果。中间5s的区别用于处理经纪人和消费者之间总是存在偏差以及网络中存在延迟的情况。(可以看出,长轮询模式的前提是代理和消费者之间的时间偏差不是“很大”)

      长轮询有什么问题吗?可以改进吗?、

      动态推/拉

      “长轮询相当于执行间隔为0的拉取模式(每次收到拉取结果时都会启动下一个拉取请求),此时代理始终具有可读消息。”

      这是轮询在服务器上处理可消耗消息的时间。在这种情况下,如果长轮询请求返回时消息到达服务器,则消费者消耗的延迟为:

      假设代理和消费者之间的网络开销时间是r毫秒,那么这个消息需要3R才能到达消费者的第一个r:消息已经到达代理,但是长轮询请求已经完成了数据读取并准备返回给消费者。从经纪人到消费者需要休息。第二个r:消费者收到代理的响应,并启动下一个长轮询。这个请求到达代理需要休息。第三个r: broker接收请求并读取这些数据。然后需要r才能返回给消费者,所以总共需要3R(不考虑阅读成本,只考虑网络成本)

      此外,在这种情况下,请求和响应总是在代理和消费者之间进行(长轮询变为拉取,间隔为0)。

      考虑到这种方式,它具有长轮询的优点,并且可以在消息可读时减少从代理到消费者的主动推送消息的数量,从而减少不必要的请求。

      参考文章

      http://www.luyixian.cn/news_show_261068.aspx

      https://blog.51cto.com/caczjz/2141194?资料来源=dra

      https://www.jianshu.com/p/251b76643d47

      https://www.jianshu.com/p/36a7775b04ec

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/3370.html

          热门文章

          文章分类