1.揭开消息中间件RabbitMQ的神秘面纱

当你看到这篇博文的时候,相信你至少已经知道RabbitMQ 是一个非常优秀的消息中间件,它使用专门处理高并发的Erlang 语言编写而成的消息中间件产品。

当然如果你不知道也没关系,读完本篇你将Get 以下技能:

  • 为什么需要消息中间件?
  • 什么是生产者?
  • 什么是消费者?
  • 什么是队列?
  • 什么是消息队列?
  • 什么是消息中间件?
  • 消息中间件有哪些?
  • 了解何时使用RabbitMQ或Apache Kafka?
  • 什么是RabbitMQ?

0x01 为什么需要消息中间件?

Web 应用都是基于 HTTP 协议的请求/响应模式,无法像 TCP 协议那样保持长连接,因此 Web 应用就很难像手机那样实现实时的消息推送。

就目前来看,Web 应用的消息推送方式主要有以下几种:

1.Ajax 短轮询

Ajax 轮询主要通过页面端的 JS 定时异步刷新任务来实现数据的加载,但这种方式实时效果较差,而且对服务端的压力也较大。

2. 长轮询

长轮询主要也是通过 Ajax 机制,但区别于传统的 Ajax 应用,长轮询的服务器端会在没有数据时阻塞请求直到有新的数据产生或者请求超时才返回,之后客户端再重新建立连接获取数据,具体实现方式见图 1 所示。但长轮询服务端会长时间地占用资源,如果消息频繁发送的话会给服务端带来较大的压力。

图 1. 长轮询实现方式

3.WebSocket 双向通信

WebSocket 是 HTML5 中一种新的通信协议,能够实现浏览器与服务器之间全双工通信。如果浏览器和服务端都支持 WebSocket 协议的话,该方式实现的消息推送无疑是最高效、简洁的。并且最新版本的 IE、Firefox、Chrome 等浏览器都已经支持 WebSocket 协议,Apache Tomcat 7.0.27 以后的版本也开始支持 WebSocket。

参考 基于 RabbitMQ 的实时消息推送

0x02  消息传递术语

2.1  什么是生产者?

制作意味着发送。 一个发送消息的程序是一个生产者:

Tips: P 代表生产者

2.2 什么是消费者?

消费与接受有类似的意义。 消费者是一个主要等待接收消息的程序:

请注意,生产者,消费者和中间件不必驻留在同一主机上;

2.3 什么是队列?

  • 队列是生活在RabbitMQ中的邮箱的名称。 尽管消息流经RabbitMQ和您的应用程序,但它们只能存储在队列中。
  • 一个队列只受主机内存和磁盘限制的约束,它本质上是一个很大的消息缓冲区。
  • 许多生产者可以发送进入一个队列的消息,并且许多消费者可以尝试从一个队列接收数据。 这就是我们代表队列的方式:

 

2.4 什么是消息队列?

消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。

消息发布者只管把消息发布到 MQ 中而不用管谁来取,消息使用者只管从 MQ中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在。

2.5 什么是消息中间件?

消息队列中间件(简称消息中间件)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。

通过提供消息传递和消息排队模型,它可以在分布式环境下提供应用解耦、弹性伸缩、冗余存储、流量削峰、异步通信、数据同步等等功能,

其作为分布式系统架构中的一个重要组件,有着举足轻重的地位.

传统的信息系统作法可能是收到一条消息就马上同步存入数据库,这种作法在小并发量的情况下可以很好的工作,但互联网大并发环境下就是灾难.

更多解释请参考:消息队列之 RabbitMQ

2.6 其他概念

概念:

  • Brocker:消息队列服务器实体。
  • Exchange:消息交换机,指定消息按什么规则,路由到哪个队列。
  • Queue:消息队列,每个消息都会被投入到一个或者多个队列里。
  • Binding:绑定,它的作用是把exchange和queue按照路由规则binding起来。
  • Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
  • Vhost:虚拟主机,一个broker里可以开设多个vhost,用作不用用户的权限分离。
  • Producer:消息生产者,就是投递消息的程序。
  • Consumer:消息消费者,就是接受消息的程序。
  • Channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。

消息队列的使用过程大概如下:

  • 消息接收
    • 客户端连接到消息队列服务器,打开一个channel。
    • 客户端声明一个exchange,并设置相关属性。
    • 客户端声明一个queue,并设置相关属性。
    • 客户端使用routing key,在exchange和queue之间建立好绑定关系。
  • 消息发布
    • 客户端投递消息到exchange。
    • exchange接收到消息后,就根据消息的key和已经设置的binding,进行消息路由,将消息投递到一个或多个队列里。
  • AMQP 里主要要说两个组件:
    • Exchange 和 Queue
    • 绿色的 X 就是 Exchange ,红色的是 Queue ,这两者都在 Server 端,又称作 Broker
    • 这部分是 RabbitMQ 实现的,而蓝色的则是客户端,通常有 Producer 和 Consumer 两种类型。
    Exchange通常分为四种:
    • fanout:该类型路由规则非常简单,会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中,相当于广播功能
    • direct:该类型路由规则会将消息路由到binding key与routing key完全匹配的Queue中
    • topic:与direct类型相似,只是规则没有那么严格,可以模糊匹配和多条件匹配
    • headers:该类型不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配

0x03 消息中间件有哪些?

ActiveMQ 是 Apache 出品的、采用 Java 语言编写的完全基于 JMS1.1 规范的面向消息的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通信。不过由于历史原因包袱太重,目前市场份额没有后面三种消息中间件多,其最新架构被命名为 Apollo,号称下一代 ActiveMQ,有兴趣的同学可行了解。

RabbitMQ 是采用 Erlang 语言实现的 AMQP 协议的消息中间件,最初起源于金融系统,用于在分布式系统中存储转发消息。RabbitMQ 发展到今天,被越来越多的人认可,这和它在可靠性、可用性、扩展性、功能丰富等方面的卓越表现是分不开的。

Kafka 起初是由 LinkedIn 公司采用 Scala 语言开发的一个分布式、多分区、多副本且基于 zookeeper 协调的分布式消息系统,现已捐献给 Apache 基金会。它是一种高吞吐量的分布式发布订阅消息系统,以可水平扩展和高吞吐率而被广泛使用。目前越来越多的开源分布式处理系统如 Cloudera、Apache Storm、Spark、Flink 等都支持与 Kafka 集成。

RocketMQ 是阿里开源的消息中间件,目前已经捐献个 Apache 基金会,它是由 Java 语言开发的,具备高吞吐量、高可用性、适合大规模分布式系统应用等特点,经历过双 11 的洗礼,实力不容小觑。

ZeroMQ 号称史上最快的消息队列,基于 C 语言开发。ZeroMQ 是一个消息处理队列库,可在多线程、多内核和主机之间弹性伸缩,虽然大多数时候我们习惯将其归入消息队列家族之中,但是其和前面的几款有着本质的区别,ZeroMQ 本身就不是一个消息队列服务器,更像是一组底层网络通讯库,对原有的 Socket API 上加上一层封装而已。

目前市面上的消息中间件还有很多,比如腾讯系的 PhxQueue、CMQ、Kafka 等,甚至NoSQL Redis据说 也有消息 队列的功能。

参考博文:IM系统的MQ消息中间件选型:Kafka还是RabbitMQ?

0x04 了解何时使用RabbitMQ或Apache Kafka?

英文原文:Understanding When to use RabbitMQ or Apache Kafka

人们做出选择,情绪和个人喜好往往是非常重要的因素,但是作为一个有经验的技术专家来说,肯定是不能因为个人喜好去草率做出决定的。

如今市场上有数十种消息传递技术,什么样的场景用什么技术,这是一个技术专家应该考虑的问题。

如今最流行的选择有两种:RabbitMQ和Apache Kafka

所以接下来我们将从起源,设计意图,成功的案例,集成的功能和开发人员的体验来对比回答何时使用RabbitMQ或Apache Kafka问题。

4.1 起源

RabbitMQ 是一个“传统”消息代理,可以实现各种消息传递协议。它是首批实现合理级别功能,客户端库,开发工具和质量文档的开源消息代理之一。RabbitMQ最初是为实现AMQP而开发的,AMQP是一种开放式线路协议,具有强大的路由功能。虽然Java具有像JMS这样的消息传递标准,但它对于需要分布式消息传递的非Java应用程序没有帮助,因为它严重限制了任何集成场景,微服务或单片机。随着AMQP的出现,跨语言的灵活性成为开源消息代理的真实存在。

Apache Kafka 是在Scala中开发的,最初是在LinkedIn(领英)上作为连接不同内部系统的一种方式。当时,LinkedIn正在转向更加分散的架构,需要重新构想数据集成和实时流处理等功能,从而摆脱以前单一的方法来解决这些问题。今天,Kafka在Apache Software Foundation产品生态系统中得到了很好的采用,在事件驱动的架构中特别有用。 

4.2 架构设计

RabbitMQ

  • RabbitMQ被设计为通用消息代理,采用点对点,request(请求)//reply(回复)和pub-sub通信样式模式的多种变体。
  • 它使用智能 broker(代理)/dumb(哑) 消费者模型,专注于向消费者提供一致的消息传递,消费者的消费速度与经纪人跟踪消费者状态的速度大致相似。
  • 它是成熟的,在正确配置时表现良好,得到很好的支持(客户端库Java,.NET,node.js,Ruby,PHP和更多语言),并且有许多可用的插件可以将它扩展到更多的用例和集成场景。

简化整体RabbitMQ架构   资料来源:http://kth.diva-portal.org/smash/get/diva2:813137/FULLTEXT01.pdf

RabbitMQ中的通信可以根据需要同步或异步。发布者向交换发送消息,消费者从队列中检索消息。通过交换将生产者与队列分离可确保生产者不会受到硬编码路由决策的影响。RabbitMQ还提供了许多分布式部署方案(并且确实要求所有节点都能够解析主机名)。可以将多节点群集设置为群集联合,并且不依赖于外部服务(但某些群集形成插件可以使用AWS API,DNS,Consul等)。  

Apache KafKa

Apache Kafka专为高容量发布 - 订阅消息和流而设计,旨在持久,快速和可扩展。

从本质上讲,Kafka提供了一个持久的消息存储,类似于日志,在服务器集群中运行,它存储称为主题的类别中的记录流。

Figure 2 - Global Apache Kafka architecture (with 1 topic, 1 partition, replication factor 4). 资料来源:http://kth.diva-portal.org/smash/get/diva2:813137/FULLTEXT01.pdf 

 

 

每条消息都包含一个键,一个值和一个时间戳。几乎与RabbitMQ相反,Kafka雇用了一个笨重的经纪人,并使用聪明的消费者来读取它的缓冲区。Kafka不会尝试跟踪每个消费者读取的消息,只保留未读消息; 相反,Kafka会在一段时间内保留所有消息,消费者有责任在每个日志(消费者状态)中跟踪他们的位置。因此,通过合适的开发人员创建消费者代码,Kafka可以支持大量消费者并以极少的开销保留大量数据。如上图所示,Kafka确实需要运行外部服务 - 在这种情况下是Apache Zookeeper,这通常被认为是非常容易理解,设置和操作的。

Requirements and Use Cases 要求和用例

Apache Kafka

许多开发人员在意识到必须将大量内容连接在一起时开始探索消息传递,而其他集成模式(如共享数据库)则不可行或太危险。

Apache Kafka包括代理本身,它实际上是最着名和最受欢迎的部分,并且已经设计并突出地推向流处理场景。除此之外,Apache Kafka最近还添加了Kafka Streams,它将自己定位为Apache Spark,Apache Flink,Apache Beam / Google Cloud Data Flow和Spring Cloud Data Flow等流媒体平台的替代品。该文档很好地讨论了网站活动跟踪,度量标准,日志聚合,流处理,事件采购和提交日志等常见用例它描述的其中一个用例是消息传递,它可能会产生一些混乱。因此,让我们解决一下,并清楚了解哪些消息传递方案最适合Kafka,例如:

  • 从A到B流,没有复杂的路由,最大吞吐量(100k / sec +),按分区顺序至少提交一次。
  • 当您的应用程序需要访问流历史记录时,至少按分区顺序提供一次。Kafka是一个持久的消息存储,客户可以根据需要“重播”事件流,而不是更传统的消息代理,一旦消息传递,它就会从队列中删除。
  • 流处理
  • 活动采购

RabbitMQ

RabbitMQ是一种通用消息传递解决方案,通常用于允许Web服务器快速响应请求,而不是在用户等待结果时强制执行资源繁重的过程。它还可以将消息分发给多个接收者以供消费,或者在高负载(20k + / sec)下平衡负载之间的负载。当您的需求超出吞吐量时,RabbitMQ可提供许多功能可靠的交付,路由,联合,HA,安全性,管理工具和其他功能让我们来看看RabbitMQ的最佳场景,例如:

  • 您的应用程序需要使用现有协议的任意组合,如AMQP 0-9-1,STOMP,MQTT,AMQP 1.0。
  • 您需要基于每个消息(死信队列等)进行更精细的一致性控制/保证。但是,Kafka最近添加了更好的事务支持。 
  • 您的应用程序需要点对点,请求/回复以及发布/订阅消息传递的多样性
  • 复杂的路由到消费者,使用非平凡的路由逻辑集成多个服务/应用程序

RabbitMQ还可以有效地解决上面几个Kafka强大的用例,但是在其他软件的帮助下。当应用程序需要访问流历史时,RabbitMQ通常与Apache Cassandra一起使用,对于需要“无限”队列的应用程序,RabbitMQ通常与LevelDB插件一起使用,但这两种功能都不附带RabbitMQ本身。

为了更深入地了解Kafka和RabbitMQ的微服务特定用例,请访问Pivotal博客并阅读Fred Melo的这篇简短帖子

开发经验

RabbitMQ

RabbitMQ正式支持Java,Spring,.NET,PHP,Python,Ruby,JavaScript,Go,Elixir,Objective-C,Swift - 通过社区插件与许多其他客户端和devtools一起支持。RabbitMQ客户端库已经成熟并且文档齐全

Apache Kafaka

Apache Kafka在这方面取得了长足进步,虽然它只提供了一个Java客户端,但是社区开源客户端,生态系统项目以及适配器SDK的目录不断增加,可以构建自己的系统集成大部分配置是通过.properties文件或以编程方式完成的。

这两个选项的普及对许多其他软件提供商产生了很大的影响,这些软件提供商确保RabbitMQ和Kafka在他们的技术上运行良好。

至于开发人员的体验...值得一提的是我们在Spring KafkaSpring Cloud Stream等中提供的支持。 

安全和运营

RabbitMQ

两者都是RabbitMQ的优势。RabbitMQ管理插件提供HTTP API,基于浏览器的管理和监控UI,以及运营商的CLI工具。长期监控数据存储需要使用CollectD,Datadog或New Relic等外部工具。RabbitMQ还提供用于监控,审计和应用程序故障排除的API和工具。除了支持TLS之外,RabbitMQ还附带了由内置数据存储,LDAP或基于HTTPS的外部提供程序支持的RBAC,并支持使用x509证书而不是用户名/密码对进行身份验证。使用插件可以相当简单地开发其他身份验证方法。

Kafaka

这些领域对Apache Kafka构成了挑战。在安全方面,最近的Kafka 0.9版本添加了TLS,基于JAAS角色的访问控制和kerberos / plain / scram auth,使用CLI管理安全策略。这对早期版本进行了实质性改进,您只能锁定网络级别的访问权限,这对于共享或多租户来说效果不佳。

Kafka使用由shell脚本,属性文件和特定格式的JSON文件组成的管理CLI。Kafka Brokers,生产商和消费者通过Yammer / JMX发布指标,但没有保留任何历史记录,这实际上意味着使用第三方监控系统。使用这些工具,操作可以管理分区和主题,检查消费者偏移位置,并使用Apache Zookeeper为Kafka提供的HA和FT功能。虽然许多人认为对Zookeeper的要求存在高度怀疑,但它确实为Kafka用户带来了集群优势。

例如,3节点Kafka集群即使在2次故障后系统也能正常运行。但是,如果要在Zookeeper中支持尽可能多的故障,则需要额外的5个Zookeeper节点,因为Zookeeper是基于仲裁的系统,并且只能容忍N / 2 + 1故障。这些显然不应该与Kafka节点共存 - 所以要建立一个3节点的Kafka系统,你需要~8台服务器。在推断任何Kafka系统的可用性时,运营商必须考虑ZK集群的属性,无论是在资源消耗还是设计方面。

性能

Kafka

Kafka在设计上大放异彩:100k / sec的性能通常是人们选择Apache Kafka的关键驱动因素。  

当然,每秒消息的速率很难说明和量化,因为它们依赖于很多,包括你的环境和硬件,你的工作负载的性质,使用的交付保证(例如持久性成本高,镜像甚至更多)等等。

RabbitMQ

每秒20K消息很容易通过单个Rabbit队列推送,实际上并不比这更难,对保证方式的要求不高。该队列由一个Erlang轻量级线程支持,该线程在本机操作系统线程池上进行协作调度 - 因此它成为一个自然的瓶颈或瓶颈,因为单个队列永远不会做更多的工作,而不是让CPU周期工作在。

每秒增加消息通常归结为通过巧妙的路由(例如,可以同时运行不同的队列)来执行诸如跨多个队列中断流量之类的事情来正确利用一个环境中可用的并行性。当RabbitMQ 每秒实现100万条消息时,这个用例基本上完全是为了明智地做到这一点 - 但是使用了大量资源,大约30个RabbitMQ节点实现了。大多数RabbitMQ用户都享有卓越的性能,集群由3到7个RabbitMQ节点组成。

0x05 什么是RabbitMQ?

RabbitMQ 官网:http://www.rabbitmq.com/

RabbitMQ是部署最广泛的开源消息代理。

RabbitMQ在全球范围内在小型初创公司和大型企业进行了超过35,000次的生产部署,是最受欢迎的开源消息代理。

RabbitMQ轻巧且易于部署在云端和云端。 它支持多种消息传递协议。 RabbitMQ可以部署在分布式和联合配置中,以满足高规模,高可用性需求。

RabbitMQ可运行在许多操作系统和云环境中,并为大多数流行语言提供广泛的开发工具。

————官网解释

RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。

RabbitMQ服务器是用Erlang语言编写的,而群集和故障转移是构建在开放电信平台框架上的。

———— 维基百科

Tips: 

在最近研读的Think in Java 第四版中有这样一段话:

如果你发现程序中某个部分必须大量使用并发,并且你在试图构建这个部分时碰到了过多的问题,那么你可以考虑使用Erlang 这类专门的并发语言来创建这个部分。

本篇完~

更多请看我的RabbitMQ 学习专栏:https://www.cnblogs.com/xingyunblog/p/9685359.html

posted @ 2018-06-18 15:33  技术宅星云  阅读(2114)  评论(0编辑  收藏  举报