消息队列、消息代理和消息中间件的区别和联系

若是你常常看技术文章应该听过「消息队列」、「消息代理」和「消息中间件」这三个词,它们有什么区别和联系呢?但愿这篇文章能告诉你答案。html

中间件(Middleware)

首先就要说什么是中间件?个人理解是:git

中间件是帮助应用程序与其余应用程序、网络、硬件、操做系统交互或通讯的软件。github

换句更简洁的话:「将具体业务和底层逻辑解耦的软件」。其实符合中间件的软件范畴很是宽,平常用的Redis、Nginx、Zookeeper、Memcached等等都是「中间件」。所谓的「中间」是相对于架构体系内的,它不涉及具体的业务逻辑也不涉及底层的硬件逻辑,用于用户数据交换和管理,可以起到「中介」的做用,这就是中间件。数据库

那么问题来了:为何须要中间件的帮助(代理),直接去和对应的应用程序、硬件、操做系统等交互/通讯很差嘛?django

回答问题前,咱们要明确一点:编程

任何中间件必然是为了解决特定领域的某个(些)问题而出现的。服务器

我举2个例子来帮助你们理解。网络

数据库中间件

当项目很小的时候,直接使用编程语言下的数据库驱动操做数据库就能够了,有些开发会用ORM的方式操做数据库:这是够用的。数据结构

但随着业务发展,数据量和读写QPS愈来愈高,主从模式的MySQL实例压力愈来愈大,单纯的对服务器硬件升级已经没法知足生产环境的须要。在我司不成文的习惯是单表不要超过5千万条记录,数据库量大的时候就设计分库分表,也就是「分而治之」,把QPS和数据量分片限定在一个范围内。架构

固然还有不少其余相关的功能,如读写分离、路由策略、统计、管理、鉴权等等。这些是在业务逻辑之上的,不该该在业务代码中把这部分堆进去,应该抽象它们出来做为一个独立的组件,这就是数据库中间件。

如今主流的开源数据库中间件有Mycat、MySQL-proxy、Atlas等等,不过如今都不怎么维护了,另外还有Cetus,做者是tcpcopy的做者,这个项目还在不断维护,有同窗有兴趣的能够试试。固然其实各大公司内部都有本身的数据库中间件产品,更多的贴近公司的业务产品和基础设施。

Web框架中间件

通常Web框架都支持中间件,Web框架中间件的本质是插件系统,是一系列的框架钩子,在收到请求和返回响应这个过程里面去作一些额外的事情。中间件种类不少,举例一些:

  1. 响应压缩
  2. 记录日志
  3. 支持会话Session
  4. CSRF保护
  5. 验证/身份鉴别
  6. 访问控制
  7. 资源使用检查(如内存占用)
  8. 请求指标
  9. 健康检查
  10. 静态资源管理 ...

这些中间件将业务和非业务代码功能进行解耦:

  1. 框架里面可能内置了一些经常使用的中间件,也可能只是内置中间件支持。你能够配置使用某个(些),也能方便的自定义中间件
  2. Web视图中不须要手写中间件逻辑,按约定好的用法框架会在对应的生命周期中按照约定的顺序去执行这些中间件逻辑

PS: Golang语言中最知名的Web框架Gin支持中间件,并且还官网搞了个叫gin-gonic/contrib的项目搜集社区里面的中间件。

消息队列(Message Queue)

消息队列就是Message+Queue。其实消息能够说是一个数据传输单位,它包含了建立时间、通道/主题信息、输入参数等所有数据;队列(Queue)是一种FIFO(先进先出)的数据结构,编程语言通常都内置(内存中的)队列实现,能够做为进程间通信(IPC)的方法。使用队列最多见的场景就是生产者/消费者模式:生产者生产消息放到队列中,消费者从队列里面获取消息消费。

准确的说,消息队列(如下简称MQ**是一种能实现生产者到消费者单向通讯的通讯模型,而通常你们说MQ是指实现了这个模型的中间件,好比RabbitMQ、RocketMQ、Kafka等。

设想一个订单场景,当你付款成功以后要作什么:

  1. 通知/提醒系统。通知商家有人买了Ta的商品,通知买家你购买成功(至关于确认订单)。通知/提醒的方式不少,如邮件、短信、App内消息等等
  2. 会员系统。更新用户的积分、等级等
  3. 日志系统。订单这么重要的服务须要有日志能够用于将来回溯问题
  4. 推荐系统。更新用户画像,从新给用户推荐他可能感兴趣的商品 ..

这就出现了一些问题:

  1. 响应耗时。事实上作的比这要多得多,每一项都须要有开销,增长响应时间。若是这些逻辑是同步执行的,用户要等多久?这种体验是彻底不能够接受的!因此呢,须要一种异步消费的机制
  2. 过分耦合。原本仅仅是一个订单系统,结果上述的那些东西都要堆进来,这就成了一个巨无霸应用,将来开发、维护都是问题
  3. 错误丢失。假如这些后续的行为中某个(些)服务正好出现了故障执行失败或者验证超时,可是付款成功的确认是必须完成的,那么须要有个地方存这些尚未被正确消费的部分
  4. 须要组(广)播。就像上面的订单场景,付款成功这个消息被发送给多个子系统,至关于组播。将来若是要新增删减订阅源,怎么便捷的实现呢?

固然还有其余的问题:

  1. 秒杀场景下并发可能会很高的,很是有可能出现出现远超现有服务器处理能力的状况,这就容易把系统搞崩了,若是出现这种问题时把未处理的放进消息队列,这就达到了「削峰」和「限流」的做用。
  2. 某些场景下须要有消息的优先级 ...

而消息中间件就是解决上述问题的,虽然不一样的中间件的实现方案不一样,但都具有如下特色:

  1. 分布式。其实消息中间件解决的就是分布式系统之间消息传递的问题,消费者能够分布在多台服务器上,一方面下降了因为单点故障引发的消息队列阻塞的风险,另一方面也很是容易横向扩展。
  2. 持久可靠。消息队列通常会把接收到的消息存储到本地硬盘上,保证消息不会在未消息前莫名丢失。
  3. 高性能和高吞吐量。例如RocketMQ有亿级消息堆积能力,普遍应用在阿里系的各类高并发场景下;而Kafka在实时计算、日志采集等场景下算是业界的标准。

能够说,消息中间件是如今企业架构中不可或缺的组合部分,用了都说好。

消息代理(Message Broker)

消息代理是一种架构模式,用于消息验证、变换、路由。虽然不一样的消息中间件架构和实现各不相同,可是大部分都实现了Broker:其实就是消息中间件服务器,它是中间件的核心。

注意:RabbitMQ、Kafka、RocketMQ等都有消息代理,可是注意,不是全部中间件都这么选,例如ZeroMQ,它用了套接字风格的API。

在一些地方其实说消息代理就是指消息中间件,如Python语言知名的分布式任务队列框架Celery中就这么称呼的(所谓的「任务」其实就是一个包含了任务所有数据的消息)。固然,Celery中使用的消息代理比知名的消息中间件范围广得多,其余的如Redis、MongoDB、Zookeeper等均可以做为消息代理,由于对于Celery来讲,它要的只是一个消息存储的「代理」,相似数据库这种具有存储特性的软件均可以做为消息代理。

延伸阅读

原文地址: strconv.com/posts/messa…

  1. github.com/Meituan-Dia…
  2. docs.djangoproject.com/en/2.2/ref/…
  3. dbaplus.cn/news-159-99…
  4. en.wikipedia.org/wiki/Messag…
相关文章
相关标签/搜索