消息队列介绍
消息队列中间件是大型系统中的重要组件,已经逐渐成为企业系统内部通信的核心手段。它具有松耦合、异步消息、流量削峰、可靠投递、广播、流量控制、最终一致性等一系列功能,已经成为异步RPC的主要手段之一。
目前常见的消息中间件有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ等。
消息队列应用场景
消息队列在实际中常见的应用场景有应用解耦、异步处理、流量错峰与流控、日志处理等等。
应用解耦
消息中间件顾名思义是用于消息存放的中间件。拿支付订单流程举例,在没有中间件的情况下,流程大致如下:
- 用户支付订单,更新订单状态
- 调用库存服务,完成响应功能
- 调用积分服务,完成响应功能
- 调用短信服务,发送短信通知
这个过程是顺序执行的,如果库存和积分或者短信服务没有及时响应,或者短信服务处理堵塞,客户端用户收到响应的时间将会延长,体验变差。
其实我们知道对于订单流程,只有订单处理才是核心服务,其他依赖系统不是那么重要,可以通知到即可。所以可以使用消息中间件,我们在处理完毕订单之后放入中间件立刻返回,然后后续服务从中间件中拿到数据进行后续的处理。
异步处理
异步处理是使用消息中间件的一个重要功能,拿用户注册来说,如果没有消息中间件,流程大致如下:
- 提交注册信息,保存注册信息①
- 发送注册通知邮件②
- 发送短信验证码③
这个过程是顺序的,很明显在发送邮件或短信时候有可能因为网络等原因发送有一定延迟,这时候响应时间变长。时间为①+②+③。
在不使用中间件的情况下我们可以稍微改进,可以在注册信息记录完毕之后同时调用发送通知邮件和发送短信验证码的程序。时间为①+(max(②,③))。虽然改进,但是因为使用了并行处理,由于CPU的并行处理能力有限,瓶颈很快就会到来。
可以继续改进,注册信息记录完毕之后写入中间件,立即返回。短信服务和邮件服务从中间件中取出信息发送通知,时间为①+写入中间件时间。
流量错峰
在类似于秒杀这样的场景中会在某个时间流量突增,大量的请求同时到达服务端,无疑对后端的压力会大大增加,如果都等着处理完成可能会堵死后续的请求。这时候可以使用消息中间件把需要处理的信息先存储在中间件,也可以控制活动的参与人数。在后续服务程序有能力时再拿出信息进行处理,就可以削平流量峰值。保证处理程序的正常运行。
日志处理
在生产环境中,为了监控日志,会有大量的日志需要传输存储检索,现在比较有名的日志处理架构有ELK,在分布式应用中由于日志的数量级越来越大,存储起来对速度的要求也越快越快。这时候需要使用中间件解决大量日志传输的问题,比如Kafka。
下图是一个常见的日志处理架构:
-
Kafka:接收用户日志的消息队列。
-
Logstash:做日志解析,统一成JSON输出给Elasticsearch。
-
Elasticsearch:实时日志分析服务的核心技术,一个schemaless,实时的数据存储服务,通过index组织数据,兼具强大的搜索和统计功能。
-
Kibana:基于Elasticsearch的数据可视化组件,超强的数据可视化能力是众多公司选择ELK stack的重要原因。
JMS消息服务
JMS是Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。ActiveMQ就是JMS接口的实现。
JMS消息模式
大部分的消息队列都有两种通信模式。
- 点对点(Point-to-Point Messaging Domain)
- 发布-订阅(Publish/Subscribe Messaging Domain)
JMS也不例外的定义了这两种消息发送模型的规范,但是并没有给予实现,实现JMS接口的消息中间件(MOM)称为JMS Provider。
点对点
消息到达消息系统,被保留在消息队列中,然后由一个或者多个消费者消费队列中的消息,一个消息只能被一个消费者消费,然后就会被移除。例如订单处理系统。
发布-订阅
消息发送时指定主题(或者说通道),消息被保留在指定的主题中,消费者可以订阅多个主题,并使用主题中的所有的消息,例如现实中的电视与电视频道。所有客户端包括发布者和订阅者,主题中的消息可以被所有的订阅者消费,消费者只能消费订阅之后发送到主题中的消息。
JMS编码接口
- ConnectionFactory 用于创建连接到消费中间件的连接工厂
- Connection 代表了应用程序和消息服务器之间通信的线路
- Destination 指消息发布和接收的地点,包括队列和主题
- Session 表示一个单线程的上下文,用于发送和接收消息
- MessageConsumer 由会话创建,用于接收发送到目标的消息
- MessageProducer 由会话创建,用于发送消息到目标
- Message 是消费者在生产者之间传送的对象,消息头,一组消息属性,消息体