在实际项目开发中,有时候需要与其他系统进行集成完成相关业务功能,这种情况最原始的做法是程序内部相互调用。
除此之外,还可以使用消息服务中间件进行业务处理,使用消息服务中间件能够提升系统的异步通信和扩展解耦能力。
消息服务概述
使用消息服务可以实现一个高性能、高可用、高扩展的系统,解决了异步处理、应用解耦、流量削峰、分布式事务管理等问题。
1.异步处理
场景:用户注册后,系统需要将信息写入数据库,并发送注册邮件和注册短信通知。
- 针对该场景,有三种处理方式
- 串行处理方式:用户发送注册请求后,服务器会先将注册信息写入数据库,依次发送注册邮件和短信消息,服务器只有在消息处理完毕后才会将处理结果返回客户端。 弊端:该方式非常耗时,用户体验差。
- 并行处理方式:用户发送注册请求后,将注册信息写入数据库,同时发送注册邮件和短信消息,最后返回给客户端。 在一定程度上提高了后台业务处理的效率,但在遇到较为耗时的业务处理时,仍然显得不够完善。
- 消息服务处理方式:可以在业务中嵌入消息服务进行业务处理,该方式先将注册信息写入数据库,在极短的世间内将注册信息写入消息队列后即可返回响应消息。即前端业务不需要理会不相干的后台业务处理,而发送注册邮件和短信的业务会自动读取消息队列中的相关消息进行后续业务处理。
2.应用解耦
场景:用户下单后,订单服务需要通知库存管理
- 如果使用传统方式处理订单业务,用户下单后,订单服务会直接调用库存服务接口进行库存更新, 这种方式存在一个很大的问题:即一旦库存系统出现异常,订单服务会失败导致订单丢失。
- 如果使用消息服务模式,订单服务的下订单消息会快速写入消息队列,库存服务会监听并读取到订单,从而修改库存。更加高效和可靠。
3.流量削峰
场景:秒杀活动——由于服务器处理资源能力有限,出现峰值时很容易造成服务器宕机、用户无法访问的情况。
- 为了解决该问题,通常会采用消息队列缓冲瞬时高峰流量,对请求进行分层过滤,从而过滤掉一些请求。
- 如果专门增设服务器来应对瞬时高峰的请求,会在非峰期会浪费多余的服务器和配置。
- 加入消息服务是比较理想的方案——通过在应用前端加入消息服务,先将所有请求写入到消息队列,并限定阙值,多余的请求直接返回秒杀失败,秒杀服务会根据秒杀规则从消息队列中读取并处理有限的秒杀请求。
4.分布式事务管理
场景:怎样保证分布式系统的请求业务处理的数据一致性
- 目前较为可靠的处理:基于消息队列的二次提交,在失败的情况可以进行多次尝试或者基于队列数据进行回滚操作。
在分布式系统中加入消息服务能够保证性能不变,又能保证业务一致性的方案。
常用消息中间件
消息队列中间件(消息中间件)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,基于数据通信进行分布式系统的集成。
-
ActiveMQ
ActiveMQ丰富的API和多种集群构建模式使得它成为业界老牌的消息中间件,广泛的应用于中小型企业中。
相比较后续的RabbitMQ、RocketMQ、Kafka等中间件,其性能相对较弱,在如今的高并发、大数据处理的场景下显得力不从心,会出现消息延迟、堆积、堵塞等问题。 -
RabbitMQ
基于AMQP协议实现,AMQP是为了应对大规模并发活动而提供统一消息服务的应用层标准高级消息队列协议,专门为面向消息的中间件设计,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。 -
Kafka
是一种高吞吐两的分布式发布订阅消息系统,主要特点是:追求高吞吐量,适用于大量数据的互联网服务的数据收集业务。 -
RocketMQ
是阿里巴巴开源产品,具有高吞吐量、高可用、适合大规模分布式系统应用的优点。 - 在实际项目技术选型时,在没有特别要求的场景下,通常会选择使用RabbitMQ作为消息中间件,如果针对的是大数据业务,推荐使用Kafka或者是RocketMQ作为消息中间件。
RabbitMQ消息中间件
-
简介
- 前面已经提到,RabbitMQ是基于AMQP协议的轻量级、可靠、可伸缩和可移植的消息代理,Spring使用RabbitMQ通过AMQP协议进行通信;在SpringBoot中对RabbitMQ进行了集成管理。
- 在所有的消息服务中,消息中间件都会作为一个第三方消息代理,接受发布者发布的消息,并推送给消息消费者。
- 其主要流程为:
- 1)消息发布者(P)向RabbitMQ代理指定的虚拟主机服务器发送消息。
- 2)虚拟主机服务器内部的交换器(X)接受消息,并将消息传递并存储到与之绑定的消息队列中。
- 3)消息消费者(C)通过一定的网络连接与消息代理建立连接,同时为了简化开支,在连接内部使用了多路复用的信道进行消息的最终消费。
-
工作模式
- 针对不同的服务需求,提供了不同的工作模式
-
Work queues(工作队列模式)
- 无须设置交换器(RabbitMQ会使用内部默认交换器进行消息转换),需要指定唯一的消息队列进行消息传递,并且可以有多个消息消费者。
- 该工作模式适用于一些较为繁重、并且可以拆分处理的业务,可以分派给多个消费者轮流处理业务。
-
Publish/Subscribe(发布订阅模式)
- 必须先配置一个fanout类型交换器,无须指定对应路由键,同时会将消息路由到每一个消息队列上,每一个消息队列都可以对相同消息进行接收存储。
- 适合由各自消息队列关联的消费者进行消费。
-
Routing(路由模式)
- 必须先配置一个direct类型的交换器,并指定不同的路由键位将对应的消息从交换器路由到不同的消息队列进行存储。
- 适用于进行不同类型消息分布处理的场合。
-
Topics(通配符模式)、RPC、Headers
-
安装