1 概述
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题。实现高性能,高可用,可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。
目前在生产环境,使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ等。
2 JMS简介
2.1 JMS概述
JMS(Java Messaging Service)是Java平台上有关面向消息中间件(MOM)的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发,翻译为Java消息服务。
JMS只是接口,并没有给予实现,实现JMS接口的消息中间件称为"JMS Provider",目前知名的开源MOM(Message Oriented Middleware,也就是消息中间件) 系统包含Apache的ActiveMQ、RocketMQ、Kafka以及RabbitMQ,可以说他们都是"基本遵循"和”参考“ JMS规范,有各自的特点和优势。
2.2 专业术语
- JMS(Java Message Service):实现JMS 接口的消息中间件;
- Provider(MessageProvider):消息的生产者;
- Consumer(MessageConsumer):消息的消费者;
- PTP(Point to Point):即点对点的消息模型,这也是非常经典的模型;
- Pub / Sub(Publish/Subscribe):,即发布/订阅的消息模型;
- Queue:队列目标,也就是我们常说的消息队列,一般都是会真正的进行物理存储;
- Topic:主题目标;
- ConnectionFactory:连接工厂,JMS 用它创建连接;
- Connection:JMS 客户端到JMS Provider 的连接;
- Destination:消息的目的地;
- Session:会话,一个发送或接收消息的线程(这里Session可以类比Mybatis的Session);
2.3 JMS消息格式定义
- StreamMessage 原始值的数据流
- MapMessage 一套名称/值对
- TextMessage 一个字符串对象
- BytesMessage 一个未解释字节的数据流
- ObjectMessage 一个序列化的Java对象
3 应用场景
分布式消息队列的使用场景大概有4个:
- 异步处理
- 应用解耦
- 流量削锋
- 消息通讯
3.1 异步处理
场景说明:用户信用卡消费后,需要执行两个业务功能:
- 发送消费账单信息到用户邮箱
- 发动消费信息短信到用户手机
简单的业务实现,一般两种,单线程方式和多线程方式:
- 单线程方式
如图所示,一共耗时60ms。
-
多线程方式
如图所示,一共耗时60ms。
-
消息队列方式
如图所示,一共耗时25ms。
架构的改变,明显比前面两种方式响应时间减少,提高了系统的吞吐量。
3.2 应用解耦
场景说明:以上面的用户消费为例子。如下图:
- 支付系统:用户消费成功后,完成持久化处理,将消息写入消息队列,返回用户消费成功。
- 短信系统:订阅短信的消息,采用拉/推的方式,获取消费信息,然后发送短信。
- 邮件系统:订阅邮件的消息,采用拉/推的方式,获取消费信息,然后发送邮件。
- 假如:当短信系统或者邮件系统出现故障的时候,不影响用户的消费。因为用户消费后,就将消费的记录写入到了消息队列中。实现了支付系统和短信系统以及邮件系统的应用解耦。
3.3 流量削锋
流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛。
应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。
- 可以控制活动的人数;
- 可以缓解短时间内高流量压垮应用;
- 将用户的请求,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面,例如 “当前页面太火爆了,请刷新后重试”;
- 秒杀业务根据消息队列中的请求信息,再做后续处理。
3.4 日志处理
日志处理是指将消息队列用在日志处理中,比如Kafka的应用,解决大量日志传输的问题。架构简化如下:
- 日志采集模块,负责监控系统应用产生的是日志信息,解析处理写入到kafka消费队列;
- Kafka消息队列,负责日志数据的接收,存储和转发;
- 日志分析模块:订阅并消费kafka队列中的日志数据;
4 应用实例
4.1 实时日志分析ELK平台
开源实时日志分析ELK平台能够完美的解决我们上述的问题,ELK由ElasticSearch、Logstash和Kiabana三个开源工具组成。官方网站:https://www.elastic.co/products
- Elasticsearch是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。
- Logstash是一个完全开源的工具,他可以对你的日志进行收集、过滤,并将其存储供以后使用(如,搜索)。
- Kibana 也是一个开源和免费的工具,它Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助您汇总、分析和搜索重要数据日志。
4.2 电商系统
消息队列采用高可用,可持久化的消息中间件。比如Active MQ,Rabbit MQ,Rocket Mq。
(1)应用将主干逻辑处理完成后,写入消息队列。消息发送是否成功可以开启消息的确认模式。(消息队列返回消息接收成功状态后,应用再返回,这样保障消息的完整性)
(2)扩展流程(发短信,配送处理)订阅队列消息。采用推或拉的方式获取消息并处理。
(3)消息将应用解耦的同时,带来了数据一致性问题,可以采用最终一致性方式解决。比如主数据写入数据库,扩展应用根据消息队列,并结合数据库方式实现基于消息队列的后续处理。
5 消息模型
5.1 P2P模式
P2P (Point to Point) 模式,即点对点模式,包含三个角色,消息队列(Queue),发送者(Sender),接收者(Receiver)。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。
- 每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中)
- 发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列
- 接收者在成功接收消息之后需向队列应答成功
如果你希望发送的每个消息都应该被成功处理的话,那么你需要P2P模型。
5.2 Pub/Sub模式
Pub/Sub (Publish/Subscribe) 模式,即发布订阅模式,主题(Topic),发布者(Publisher),订阅者(Subscriber)。多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。
- 每个消息可以有多个消费者
- 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息。
- 为了消费消息,订阅者必须保持运行的状态。
当然,为了缓和这种严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅。这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息。
如果你希望发送的消息可以不被做任何处理、或者被一个消费者处理、或者可以被多个消费者处理的话,那么可以采用Pub/Sub模型。
6 相关信息
- 博文不易,辛苦各位猿友点个关注和赞,感谢