Java分布式系统---消息中间件

@(Java消息中间件)java

简介

消息中间件也能够称消息队列,是指用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通讯来进行分布式系统的集成。经过提供消息传递和消息队列模型,能够在分布式环境下扩展进程的通讯。当下主流的消息中间件有RabbitMQ、Kafka、ActiveMQ、RocketMQ等。其能在不一样平台之间进行通讯,经常使用来屏蔽各类平台协议之间的特性,实现应用程序之间的协同。其优势在于可以在客户端和服务器之间进行同步和异步的链接,而且在任什么时候刻均可以将消息进行传送和转发。是分布式系统中很是重要的组件,主要用来解决应用耦合、异步通讯、流量削峰等问题redis

消息中间件的做用

消息中间件几大主要做用以下:算法

  • 解耦
    下降工程间的强依赖程度,针对异构系统进行适配。在项目启动之初来预测未来项目会碰到什么需求,是极其困难的。经过消息系统在处理过程当中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口,当应用发生变化时,能够独立的扩展或修改两边的处理过程,只要确保它们遵照一样的接口约束。
  • 冗余(存储)
    有些状况下,处理数据的过程会失败。除非数据被持久化,不然将形成丢失。消息队列把数据进行持久化直到它们已经被彻底处理,经过这一方式规避了数据丢失风险。许多消息队列所采用的”插入-获取-删除”范式中,在把一个消息从队列中删除以前,须要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。
  • 扩展性
    由于消息队列解耦了你的处理过程,因此增大消息入队和处理的频率是很容易的,只要另外增长处理过程便可。不须要改变代码、不须要调节参数。便于分布式扩容。
  • 削峰
    在访问量剧增的状况下,应用仍然须要继续发挥做用,可是这样的突发流量没法提早预知;若是觉得了能处理这类瞬间峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列可以使关键组件顶住突发的访问压力,而不会由于突发的超负荷的请求而彻底崩溃。
  • 可恢复性
    系统的一部分组件失效时,不会影响到整个系统。消息队列下降了进程间的耦合度,因此即便一个处理消息的进程挂掉,加入队列中的消息仍然能够在系统恢复后被处理。
  • 顺序保证
    在大多使用场景下,数据处理的顺序都很重要。大部分消息队列原本就是排序的,而且能保证数据会按照特定的顺序来处理。
  • 缓冲
    在任何重要的系统中,都会有须要不一样的处理时间的元素。消息队列经过一个缓冲层来帮助任务最高效率的执行,该缓冲有助于控制和优化数据流通过系统的速度。以调节系统响应时间。
  • 异步通讯
    有些业务不想也不须要当即处理消息。消息队列提供了异步处理机制,容许用户把一个消息放入队列,但并不当即处理它。想向队列中放入多少消息就放多少,而后在须要的时候再去处理它们。

消息中间件的两种模式

PTP模式 (点对点)使用Queue做为通讯载体

P2P模式包含三个角色:消息队列(Queue),发送者(Sender),接收者(Receiver)。每一个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。数据库

P2P的特色:apache

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

Pub/Sub模式 (发布/订阅 广播)使用Topic做为通讯载体

消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不一样,发布到topic的消息会被全部订阅者消费。
queue实现了负载均衡,将producer生产的消息发送到消息队列中,由多个消费者消费。但一个消息只能被一个消费者接受,当没有消费者可用时,这个消息会被保存直到有一个可用的消费者。
topic实现了发布和订阅,当你发布一个消息,全部订阅这个topic的服务都能获得这个消息,因此从1到N个订阅者都能获得一个消息的拷贝浏览器

Pub/Sub的特色安全

  • 每一个消息能够有多个消费者
  • 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须建立一个订阅者以后,才能消费发布者的消息。
  • 为了消费消息,订阅者必须保持运行的状态。
  • 若是但愿发送的消息能够不被作任何处理、或者只被一个消息者处理、或者能够被多个消费者处理的话,那么能够采用Pub/Sub模型。

消息中间件解决的问题

异步通讯

场景说明:用户在注册后,须要发注册邮件和注册短信,传统的作法有两种:1.串行; 2.并行
1.串行方式:将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个任务所有完成后才返回给客户端。 这有一个问题是,邮件,短信并非必须的,它只是一个通知,而这种作法让客户端等待没有必要等待的东西.
2.并行方式:将注册信息写入数据库后,发送邮件的同时,发送短信,以上三个任务完成后,返回给客户端,并行的方式能提升处理的时间。
假设三个业务节点分别使用50ms,串行方式使用时间150ms,并行使用时间100ms。虽然并性已经提升的处理时间,可是,前面说过,邮件和短信对我正常的使用网站没有任何影响,客户端没有必要等着其发送完成才显示注册成功,应该是写入数据库后就返回.服务器

3.消息队列
引入消息队列后,把发送邮件,短信不是必须的业务逻辑异步处理
在这里插入图片描述
由此能够看出,引入消息队列后,用户的响应时间就等于写入数据库的时间+写入消息队列的时间(能够忽略不计),引入消息队列后处理后,响应时间是串行的3倍,是并行的2倍。网络

应用解耦

这是一个高耦合度系统的例子
在这里插入图片描述
先是来一我的找他要求发送数据给一个新的系统H,系统A的同窗要修改代码而后在那个代码里加入调用新系统H的流程。

一会那个系统B是个陈旧老系统要下线了,告诉系统A的同窗:别给我发送数据了,接着系统A再次修改代码再也不给这个系统B。

而后若是要是某个下游系统忽然宕机了呢?

系统A的调用代码里是否是会抛异常?那系统A的同窗会收到报警说异常了,结果他还要去care是下游哪一个系统宕机了。

因此在实际的系统架构设计中,若是所有采起这种系统耦合的方式,在某些场景下绝对是不合适的,系统耦合度太严重。

而且互相耦合起来并非核心链路的调用,而是一些非核心的场景(好比上述的数据消费)致使了系统耦合,这样会严重的影响上下游系统的开发和维护效率。

所以在上述系统架构中,就能够采用MQ中间件来实现系统解耦。

系统A就把本身的一份核心数据发到MQ里,下游哪一个系统感兴趣本身去消费便可,不须要了就取消数据的消费,以下图所示:
在这里插入图片描述

流量削峰

  • 场景1
    假设你有一个系统,平时正常的时候每秒可能就几百个请求,每秒几百请求是能够轻松抗住的,
    可是偶尔在高峰期一会儿来了每秒钟几千请求,弹指一挥间出现了流量高峰,为了抗住这个高峰,可能会选择扩充机器,增长到10台,可是高峰事后,每秒就几百个请求,这不是有点浪费机器资源吗?
    可是若是你就部署一台机器,那会致使瞬时高峰时,一会儿压垮你的系统,由于绝对没法抗住每秒几千的请求高峰。
    此时咱们就能够用MQ中间件来进行流量削峰。全部机器前面部署一层MQ,平时每秒几百请求你们均可以轻松接收消息。
    一旦到了瞬时高峰期,一下涌入每秒几千的请求,就能够积压在MQ里面,而后那一台机器慢慢的处理和消费。
    等高峰期过了,再消费一段时间,MQ里积压的数据就消费完毕了。
    这个就是很典型的一个MQ的用法,用有限的机器资源承载高并发请求,若是业务场景容许异步削峰,高峰期积压一些请求在MQ里,而后高峰期过了,后台系统在必定时间内消费完毕再也不积压的话,那就很适合用这种技术方案。
    在这里插入图片描述
  • 场景2
    秒杀活动,通常会由于流量过大,致使应用挂掉,为了解决这个问题,通常在应用前端加入消息队列。
    做用:
    1.能够控制活动人数,超过此必定阀值的订单直接丢弃
    2.能够缓解短期的高流量压垮应用(应用程序按本身的最大处理能力获取订单)

待补充

消息中间件经常使用协议

  • AMQP协议
    AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不一样产品,不一样开发语言等条件的限制。
    优势:可靠、通用

  • MQTT协议
    MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通信协议,有可能成为物联网的重要组成部分。该协议支持全部平台,几乎能够把全部联网物品和外部链接起来,被用来当作传感器和致动器(好比经过Twitter让房屋联网)的通讯协议。
    优势:格式简洁、占用带宽小、移动端通讯、PUSH、嵌入式系统

  • STOMP协议
    STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操做的链接格式,容许客户端与任意STOMP消息代理(Broker)进行交互。
    优势:命令模式(非topic\queue模式)

  • XMPP协议
    XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操做。核心是基于XML流传输,这个协议可能最终容许因特网用户向因特网上的其余任何人发送即时消息,即便其操做系统和浏览器不一样。
    优势:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大

  • 其余基于TCP/IP自定义的协议
    有些特殊框架(如:redis、kafka、zeroMq等)根据自身须要未严格遵循MQ规范,而是基于TCP\IP自行封装了一套协议,经过网络socket接口进行传输,实现了MQ的功能。

经常使用中间件介绍

  • RocketMQ
    阿里系下开源的一款分布式、队列模型的消息中间件,原名Metaq,3.0版本名称改成RocketMQ,是阿里参照kafka设计思想使用java实现的一套mq。同时将阿里系内部多款mq产品(Notify、metaq)进行整合,只维护核心功能,去除了全部其余运行时依赖,保证核心功能最简化,在此基础上配合阿里上述其余开源产品实现不一样场景下mq的架构,目前主要多用于订单交易系统。
    具备如下特色:
    可以保证严格的消息顺序
    提供针对消息的过滤功能
    提供丰富的消息拉取模式
    高效的订阅者水平扩展能力
    实时的消息订阅机制
    亿级消息堆积能力
    官方提供了一些不一样于kafka的对比差别:
    https://rocketmq.apache.org/docs/motivation/

  • RabbitMQ
    使用Erlang编写的一个开源的消息队列,自己支持不少的协议:AMQP,XMPP, SMTP,STOMP,也正是如此,使的它变的很是重量级,更适合于企业级的开发。同时实现了Broker架构,核心思想是生产者不会将消息直接发送给队列,消息在发送给客户端时先在中心队列排队。对路由(Routing),负载均衡(Load balance)、数据持久化都有很好的支持。多用于进行企业级的ESB整合。
  • ActiveMQ
    Apache下的一个子项目。使用Java彻底支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,少许代码就能够高效地实现高级应用场景。可插拔的传输协议支持,好比:in-VM, TCP, SSL, NIO, UDP, multicast, JGroups and JXTA transports。RabbitMQ、ZeroMQ、ActiveMQ均支持经常使用的多种语言客户端 C++、Java、.Net,、Python、 Php、 Ruby等。

  • Redis
    使用C语言开发的一个Key-Value的NoSQL数据库,开发维护很活跃,虽然它是一个Key-Value数据库存储系统,但它自己支持MQ功能,因此彻底能够当作一个轻量级的队列服务来使用。对于RabbitMQ和Redis的入队和出队操做,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不一样大小的数据。实验代表:入队时,当数据比较小时Redis的性能要高于RabbitMQ,而若是数据大小超过了10K,Redis则慢的没法忍受;出队时,不管数据大小,Redis都表现出很是好的性能,而RabbitMQ的出队性能则远低于Redis。

  • Kafka
    Apache下的一个子项目,使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统,具备如下特性:
    快速持久化:经过磁盘顺序读写与零拷贝机制,能够在O(1)的系统开销下进行消息持久化;
    高吞吐:在一台普通的服务器上既能够达到10W/s的吞吐速率;
    高堆积:支持topic下消费者较长时间离线,消息堆积量大;
    彻底的分布式系统:Broker、Producer、Consumer都原生自动支持分布式,依赖zookeeper自动实现复杂均衡;
    支持Hadoop数据并行加载:对于像Hadoop的同样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。

  • ZeroMQ
    号称最快的消息队列系统,专门为高吞吐量/低延迟的场景开发,在金融界的应用中常用,偏重于实时数据通讯场景。ZMQ可以实现RabbitMQ不擅长的高级/复杂的队列,可是开发人员须要本身组合多种技术框架,开发成本高。所以ZeroMQ具备一个独特的非中间件的模式,更像一个socket library,你不须要安装和运行一个消息服务器或中间件,由于你的应用程序自己就是使用ZeroMQ API完成逻辑服务的角色。可是ZeroMQ仅提供非持久性的队列,若是down机,数据将会丢失。如:Twitter的Storm中使用ZeroMQ做为数据流的传输。
    ZeroMQ套接字是与传输层无关的:ZeroMQ套接字对全部传输层协议定义了统一的API接口。默认支持 进程内(inproc) ,进程间(IPC) ,多播,TCP协议,在不一样的协议之间切换只要简单的改变链接字符串的前缀。能够在任什么时候候以最小的代价从进程间的本地通讯切换到分布式下的TCP通讯。ZeroMQ在背后处理链接创建,断开和重连逻辑。
    特性:
    无锁的队列模型:对于跨线程间的交互(用户端和session)之间的数据交换通道pipe,采用无锁的队列算法CAS;在pipe的两端注册有异步事件,在读或者写消息到pipe的时,会自动触发读写事件。
    批量处理的算法:对于批量的消息,进行了适应性的优化,能够批量的接收和发送消息。
    多核下的线程绑定,无须CPU切换:区别于传统的多线程并发模式,信号量或者临界区,zeroMQ充分利用多核的优点,每一个核绑定运行一个工做者线程,避免多线程之间的CPU切换开销。

主要消息中间件的比较

在这里插入图片描述

相关文章
相关标签/搜索