1、引言

消息是互联网信息的一种表现形式,是人利用计算机进行信息传递的有效载体,比如即时通讯网坛友最熟悉的即时通讯消息就是其具体的表现形式之一。

消息从发送者到接收者的典型传递方式有两种:

  • 1)一种我们可以称为即时消息:即消息从一端发出后(消息发送者)立即就可以达到另一端(消息接收者),这种方式的具体实现就是平时最常见的IM聊天消息;
  • 2)另一种称为延迟消息:即消息从某端发出后,首先进入一个容器进行临时存储,当达到某种条件后,再由这个容器发送给另一端。

在上述“消息传递方式2)”中所指的这个容器的一种具体实现就是MQ消息队列服务。

MQ消息队列中间件是中大型分布式系统中重要的组件,它主要用来解决:应用解耦、异步消息、流量削锋等问题,用以实现高性能、高可用、可伸缩和最终一致性架构。目前使用较多的消息队列有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ等。MQ消息队列中间件已被广泛用于电商、即时通讯、社交等各种中大型分布式应用系统。

在一个典型的IM即时通讯应用中,MQ消息队列可以用于:

  • 1)用户的聊天消息离线存储环节:因为IM消息的发送属于高吞吐场景,直接操纵DB很容易就把DB搞挂了,所以离线消息在落地入库前,可以先扔到MQ消息队列中,再由单独部署的消费者来有节奏地存储到DB中;
  • 2)用户的行为数据收集环节:因为用户的聊天消息和指令等,可以用于大数据分析,而且基于国家监管要求也是必须要存储一段时间的,所以此类数据的收集同样可以用于MQ消息队列,再由单独部署的消费者存储到DB中;
  • 3)用户的操作日志收集环节:log这种数据价值不高,但关键时刻又非常有用,而且数据量又很大,要想存储起来难度很高,这时就轮到Linkedin公司开源的Kafka出场了;
  • ....

因此,对于即时通讯开发者来说,正确地理解MQ消息队列,对于IM或消息推送系统的架构设计、方案选型等都大有裨益。

2、系列文章

  • 《IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议》
  • 《IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token》

3、MQ消息队列的典型应用场景

MQ消息队列目前在中大型分布式系统实际应用中常用的使用场景主要有:异步处理、应用解耦、流量削锋和消息通讯四个场景。

3.1应用场景1:异步处理

场景说明:一个典型的IM即时通讯系统中,用户注册成功后可能需要发送注册邮件和注册通知短信。

传统的做法有两种:

  • 1)串行的方式:即将注册信息写入数据库成功后、发送注册邮件、再发送注册短信。以上三个任务全部完成后,返回给客户端;
  • 2)并行方式:即将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间。

假设三个业务节点每个使用50毫秒,不考虑网络等其他开销,则串行方式的时间是150毫秒,并行的时间可能是100毫秒。

因为CPU在单位时间内处理的请求数是一定的,假设CPU1秒内吞吐量是100次。则串行方式1秒内CPU可处理的请求量是7次(1000/150)。并行方式处理的请求量是10次(1000/100)。

小结:如以上案例描述,传统的方式系统的性能(并发量,吞吐量,响应时间)会有瓶颈。

如何解决这个问题呢?答案是:引入消息队列,将不是必须的业务逻辑,异步处理。

改造后的架构如下:

按照以上约定,用户的响应时间相当于是注册信息写入数据库的时间,也就是50毫秒。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50毫秒。因此架构改变后,系统的吞吐量提高到每秒20 QPS。比串行提高了3倍,比并行提高了两倍。

3.2应用场景2:应用解耦

场景说明:一个典型的电商购物系统中,用户下订单后,订单系统需要通知库存系统。

传统的做法是:订单系统调用库存系统的接口。如下图所示:

传统模式的缺点:假如库存系统无法访问,则订单减库存将失败,从而导致订单失败,订单系统与库存系统耦合。

如何解决以上问题呢?答案是:引入应用消息队列后的方案。如下图:

如上图所示,大致的原理是:

  • 订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功;
  • 库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作。

好处就是:假如在下单时库存系统不能正常使用,也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦。

3.3应用场景3:流量削锋

流量削锋也是消息队列中的常用场景,一般在电商秒杀等大型活动(比如双11)、团购抢单活动中使用广泛。

应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。

在这种场景下加入消息队列服务的好处:

  • 1)可以控制活动的人数;
  • 2)可以缓解短时间内高流量压垮应用。

用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。秒杀业务根据消息队列中的请求信息,再做后续处理。

3.4应用场景4:日志处理

日志处理是指将消息队列用在日志处理中,比如Linkedin这种大型职业社交应用架构中Kafka的应用(Kafka就是Linkedin开发并开源的),解决大量日志传输的问题。

使用Kafka后的架构简化如下:

上图所示的架构原理就是:

  • 日志采集客户端:负责日志数据采集,定时写入Kafka队列;
  • Kafka消息队列:负责日志数据的接收,存储和转发;
  • 日志处理应用:订阅并消费kafka队列中的日志数据。

3.5应用场景5:即时消息通讯

即时消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的即时消息通讯场景。比如实现点对点消息队列或者IM聊天室等(但Jack Jiang认为,在中大型IM系统中,MQ并不适合这么用,具体的讨论请见:《请教可以使用MQ消息队列中间件做即时通讯系统吗?》)。

  • 点对点通讯:客户端A和客户端B使用同一队列,进行消息通讯;
  • 聊天室通讯:客户端A,客户端B,客户端N订阅同一主题,进行消息发布和接收。实现类似聊天室效果。

以上实际是消息队列的两种消息模式,点对点或发布订阅模式。模型为示意图,供参考。

4、MQ消息队列的常见消息模式

常见的MQ消息队列消息模式有:

  • 1)P2P模式;
  • 2)Pub/sub模式(也就是常说的“发布/订阅”模式);
  • 3)推(Push)模式和拉(Pull)模式。

下面将逐个介绍这几种常消息模式。

4.1P2P模式

P2P模式包含三个角色:

  • 1)消息队列(Queue);
  • 2)发送者(Sender);
  • 3)接收者(Receiver)。

每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。

P2P消息模式的特点:

每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中)发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列接收者在成功接收消息之后需向队列应答成功 如果希望发送的每个消息都会被成功处理的话,那么需要P2P模式。

4.2Pub/sub模式

如上图所示,此消息模式包含三个角色:

  • 1)主题(Topic);
  • 2)发布者(Publisher);
  • 3)订阅者(Subscriber)。

多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。

Pub/Sub的特点:

每个消息可以有多个消费者发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息。为了消费消息,订阅者必须保持运行的状态。为了缓和这样严格的时间相关性,有些MQ消息队列(比如RabbitMQ)允许订阅者创建一个可持久化的订阅。这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息。如果希望发送的消息可以不被做任何处理、或者只被一个消息者处理、或者可以被多个消费者处理的话,那么可以采用Pub/Sub模型。

4.3推模式和拉模式

推(push)模式是一种基于C/S机制、由服务器主动将信息送到客户器的技术。

在Push模式应用中,服务器把信息送给客户器之前,并没有明显的客户请求。push事务由服务器发起。push模式可以让信息主动、快速地寻找用户/客户器,信息的主动性和实时性比较好。但精确性较差,可能推送的信息并不一定满足客户的需求。

Push模式不能保证能把信息送到客户器,因为推模式采用了广播机制,如果客户器正好联网并且和服务器在同一个频道上,推送模式才是有效的。

Push模式无法跟踪状态,采用了开环控制模式,没有用户反馈信息。在实际应用中,由客户器向服务器发送一个申请,并把自己的地址(如IP、port)告知服务器,然后服务器就源源不断地把信息推送到指定地址。在多媒体信息广播中也采用了推模式。

拉(Pull)模式与推(Push)模式相反,是由客户器主动发起的事务。服务器把自己所拥有的信息放在指定地址(如IP、port),客户器向指定地址发送请求,把自己需要的资源“拉”回来。不仅可以准确获取自己需要的资源,还可以及时把客户端的状态反馈给服务器。

5、主流的MQ消息队列技术选型对比

一份主流MQ技术对比清单:

5.1Kafka

Kafka是Linkedin开源的MQ系统(现已是Apache下的一个子项目),它是一个高性能跨语言分布式发布/订阅消息队列系统,主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输,0.8开始支持复制,不支持事务,适合产生大量数据的互联网服务的数据收集业务。

Kafka还具有以下特性:

  • 1)快速持久化,可以在O(1)的系统开销下进行消息持久化;
  • 2)高吞吐,在一台普通的服务器上既可以达到10W/s的吞吐速率;
  • 3)完全的分布式系统,Broker、Producer、Consumer都原生自动支持分布式,自动实现负载均衡;
  • 4)支持Hadoop数据并行加载,对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka通过Hadoop的并行加载机制统一了在线和离线的消息处理。

Apache Kafka相对于ActiveMQ是一个非常轻量级的消息系统,除了性能非常好之外,还是一个工作良好的分布式系统。

5.2RabbitMQ

RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。

RabbitMQ本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正因如此,它非常重量级,更适合于企业级的开发。同时实现了Broker构架,这意味着消息在发送给客户端时先在中心队列排队。对路由,负载均衡或者数据持久化都有很好的支持。

5.3RocketMQ

RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。

5.4ZeroMQ

ZeroMQ只是一个网络编程的Pattern库,将常见的网络请求形式(分组管理,链接管理,发布订阅等)模式化、组件化,简而言之socket之上、MQ之下。对于MQ来说,网络传输只是它的一部分,更多需要处理的是消息存储、路由、Broker服务发现和查找、事务、消费模式(ack、重投等)、集群服务等。

ZeroMQ是号称最快的消息队列系统,尤其针对大吞吐量的需求场景。ZeroMQ能够实现RabbitMQ不擅长的高级/复杂的队列,但是开发人员需要自己组合多种技术框架,技术上的复杂度是对这MQ能够应用成功的挑战。ZeroMQ具有一个独特的非中间件的模式,你不需要安装和运行一个消息服务器或中间件,因为你的应用程序将扮演这个服务器角色。你只需要简单的引用ZeroMQ程序库,可以使用NuGet安装,然后你就可以愉快的在应用程序之间发送消息了。但是ZeroMQ仅提供非持久性的队列,也就是说如果宕机,数据将会丢失。其中,Twitter的Storm 0.9.0以前的版本中默认使用ZeroMQ作为数据流的传输(Storm从0.9版本开始同时支持ZeroMQ和Netty作为传输模块)。

5.5小结

RabbitMQ/Kafka/ZeroMQ 都能提供消息队列服务,但有很大的区别。

在面向服务架构中通过消息代理(比如 RabbitMQ / Kafka等),使用生产者-消费者模式在服务间进行异步通信是一种比较好的思想。

因为服务间依赖由强耦合变成了松耦合。消息代理都会提供持久化机制,在消费者负载高或者掉线的情况下会把消息保存起来,不会丢失。就是说生产者和消费者不需要同时在线,这是传统的请求-应答模式比较难做到的,需要一个中间件来专门做这件事。其次消息代理可以根据消息本身做简单的路由策略,消费者可以根据这个来做负载均衡,业务分离等。

缺点也有,就是需要额外搭建消息代理集群(但优点是大于缺点的 ) 。

ZeroMQ 和 RabbitMQ/Kafka 不同,它只是一个异步消息库,在套接字的基础上提供了类似于消息代理的机制。使用 ZeroMQ 的话,需要对自己的业务代码进行改造,不利于服务解耦。

RabbitMQ 支持 AMQP(二进制),STOMP(文本),MQTT(二进制),HTTP(里面包装其他协议)等协议。Kafka 使用自己的协议。

Kafka 自身服务和消费者都需要依赖 Zookeeper。

RabbitMQ 在有大量消息堆积的情况下性能会下降,Kafka不会。毕竟AMQP设计的初衷不是用来持久化海量消息的,而Kafka一开始是用来处理海量日志的。

总的来说,RabbitMQ 和 Kafka 都是十分优秀的分布式的消息代理服务,只要合理部署,基本上可以满足生产条件下的任何需求。

网易云信,你身边的即时通讯和音视频技术专家,了解我们,请戳网易云信官网

想要行业洞察和技术干货,请关注网易云信博客

本文转载自52im,作者:JackJiang

IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列相关推荐

  1. IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token

    1.前言 众所周之,IM是个典型的快速数据流交换系统,当今主流IM系统(尤其移动端IM)的数据流交换方式都是Http短连接+TCP或UDP长连接来实现.Http短连接主要用于从服务器读取各种持久化信息 ...

  2. IM开发基础知识补课(一):正确理解前置HTTP SSO单点登陆接口的原理

    1.前言 一个安全的信息系统,合法身份检查是必须环节.尤其IM这种以"人"为中心的社交体系,身份认证更是必不可少. 一些PC时代小型IM系统中,身份认证可能直接做到长连接中(也就是 ...

  3. IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议

    1.前言 IM应用从服务端数据的角度来看,它是一种很特殊的应用场景,抛开基础数据.增值业务和附属功能不谈,单从IM聊天工具的立身之本--聊天数据来说,理论上是不需要在服务端存储的(或者说只需要短暂存储 ...

  4. IM开发基础知识补课:正确理解前置HTTP SSO单点登陆接口的原理

    1.前言 一个安全的信息系统,合法身份检查是必须环节.尤其IM这种以"人"为中心的社交体系,身份认证更是必不可少. 一些PC时代小型IM系统中,身份认证可能直接做到长连接中(也就是 ...

  5. 音视频开发基础知识(2)——最通俗易懂的视频编解码理论知识

    更多音视频知识请关注公众号:进击的代码家 音视频学习项目:LearnVideo AndroidMediaCodecDemo 视频基础概念 像素 **像素是图像的基本单元,一个个像素就组成了图像.你可以 ...

  6. IM开发基础知识补课(二):如何设计大量图片文件的服务端存储架构?

    1.前言 一个完善的IM系统中通常充斥着大量的图片内容,包括:用户头像.图片消息.相册.图片表情等等,那么在做服务端架构设计时该如何存储这些图片呢? 本文分享的是典型Web应用中大量图片的服务端存储加 ...

  7. 广告化开发(基础知识)~CPM/CPC/CPA的理解

    文章目录 CPM (cost per mille):每千人展现的成本 CPC (cost per click):每产生一次点击所花费的成本 CPA (cost per Action):每次实际动作的成 ...

  8. SP 短信开发-基础知识篇

    SP 短信开发-基础知识篇 很土的话题,但是最近帮朋友做这个东西,所以写点东西出来给初学者参考. 一.准备资料 SP开发资料网站上有很多,但是主要是以下几个文档: 1.MISC1.6 SP订购通知接口 ...

  9. 鸿蒙APP开发基础知识

    鸿蒙开发基础知识目录 DevEco Studio编辑器de使用 创建新项目 打开一个项目 新建一个文件夹 新建一个布局文件 新建一个Page Ability(Feature Ability) 配置Ab ...

最新文章

  1. Python识别文字,实现看图说话 | CSDN博文精选
  2. Javaweb 实验二 JSP应用开发基础
  3. SVN 问题解决之 The XML response contains invalid XML
  4. 浅谈 ThreadLocal
  5. 为什么物联网没有杀手级应用
  6. cs6序列号 mac版photoshop_重磅!Parallels Desktop 16 M1版发布
  7. Mybatis框架简单使用
  8. Oracle视图传递参数
  9. MATLAB 读取表格 | readmatrix函数
  10. Hadoop开发环境准备及错误问题解决方法
  11. 电脑XP系统最大支持多大内存?
  12. 翠竹林 Opencv+C++之人脸识别
  13. 钛媒体2022 EDGE AWARDS全球创新评选之「年度最佳企业服务品牌」揭榜
  14. Substrate 基础 -- 教程(Tutorials)
  15. Javascript事件绑定的几种方式
  16. 响铃:只做“连接器”,企业微信如何实现“人即服务”
  17. 树莓派3B+安装Raspbian简易教程
  18. (ios 5.1).html,iOS 5.1.1完美越狱教程(使用Absinthe 2.0.1)
  19. 如何编辑PDF文件?简单好用的编辑方法分享
  20. 启动tomcat失败 8005 端口被占用

热门文章

  1. 亚马逊记AWS(Amazon Web Services)自由EC2应用
  2. JS常用的设计模式(7)—— 外观模式
  3. oracle分页查询数据(收藏)
  4. Java内存溢出[转]和mysql配置文件简介[原创]
  5. 考研本校与外校如何选择?
  6. Keil uvision 4 MDK 安装教程附免费安装包资源
  7. 博图如何读取mysql数据_博途使用小结:从SQL中读取数据并给变量赋值
  8. 机器人学习--粒子滤波及其在定位中的应用
  9. new ArrayList 报错
  10. 青春环游记 | 雪中悍刀行之卡尔曼的鱼【回顾 2021,展望 2022】