背景
考虑到现有业务很多依赖于MQ的方式进行,这种方式需要依赖于MQ,发送消息到mq和消费mq消息时需要了解mq消息结构进行相应处理;
对于后续对同样的事件做其他处理的人如不能提前了解到已有相应消息发到了mq就得再发一次消息到mq等。
图1.1 消息中间件
现需要考虑在不依赖于Mq的形式下如何更优雅地实现异步任务处理!!!
一.消息任务
1.1 现有轮询方式
轮询:针对每一个业务记录一张轮询中间表,通过轮询扫描消费。
优点:
1. 时间性把控粒度高。
2. 每个业务彼此分离,互不干涉。
缺点:
1. 每次创建业务都要建立一张属于自己的轮询表,也要建立一个新的轮询配置。
2. 资源消耗大。
3. 研发效率低。
1.2优化方式
模拟RabbitMq的ACK方式建立一张共性表解决通用性业务的消息体存储,共性化业务通用一个轮询。
模拟RabbitMq的ACK模式,使用轮询的方式替代mq的消息发送机制。制定专属表字段Table_Name模拟RabbitMq的RoutingKey。
每个业务处理通过Table_Name方式实现接口进行派发处理。每个实现了轮询逻辑派发接口的类即可以认为是一个队列。
以这种方式可以有效的实现消息的异步处理。
优点:
1. 代码规范化,每个服务中心只需要建立集中的一个轮询业务;
2. 符合开闭原则,每增加一个轮询处理只要多实现一个接口类即可;
3.可以减少数据库资源的消耗;
4.减少无用代码的增加,提高开发效率。
缺点:
1.由于数据量的增加,轮询压力增大,对特殊业务的轮询时间性无法针对性的把控,需要建立特殊业务轮询处理(增加轮询)。
二.演变模型
2.1演化方向:模型由图1.2 ——》 图1.3
图1.2 RabbitMQ
图1.3 定时任务模拟图
三.ACK模式
3.1什么是ack模式?
RabbitMQ 的 ACK 模式是指消息确认机制,即消费者消费消息后需要向 RabbitMQ 服务器发送一个 ACK(acknowledgement)信号来告诉服务器该消息已经被处理。
ACK 模式主要有以下两种:
1.自动确认模式(autoAck)
在自动确认模式下,消费者在收到消息后会立即向RabbitMQ 服务器发送一个 ACK 信号,表示该消息已经被消费。
这种模式适用于对于消息的可靠性要求不高的场景,比如日志处理等。
2.手动确认模式(manualAck)
手动确认模式下,消费者需要在处理完消息后,主动向RabbitMQ 服务器发送 ACK 信号。
如果消费者没有发送 ACK 信号,RabbitMQ 认为该消息没有被正确处理,并将该消息重新分发给其他消费者。
此外,在手动确认模式下,如果消费者在处理消息时出现异常,可以通过拒绝消息(NACK)来告诉 RabbitMQ 服务器该消息不能被处理,
此时 RabbitMQ 将会将该消息重新分发给其他消费者或保存到死信队列中。
四.表结构
4.1建立合适的表结构
1. Uid,table_name,msg,remark,ack
2. Hisid,Uid,table_name,msg,remark,ack (历史表,用于记录处理过的消息)
(表名称和字段名称可根据业务自行命名,以上数据结构供参考,可自行根据业务外拓字段)
五.消息体
1.规范化msg的输入形式。可以走切面或者监听的方式异步记录。写一个公用方法写入(特殊业务可调用该方法写入)。
2.规范化Table_Name字段:采用驼峰名称,代表哪个表写进来的数据。
3.规范化ack,默认设置为0;消费完成,写入2表(历史表)。
如有特殊要处理的,可以增加业务逻辑通过ack模式处理,这里ack默认值为0;
默认轮询处理失败一次ack自增1 。通用轮询方法只扫ack默认为0或者1的。
Ack不等于0,1的,通过二次轮询,第二个特殊轮询业务处理。(减少通用轮询的压力,避免造成轮询卡单。消息消费延缓等问题)。
如有特殊业务申请对应轮询:需要申请ack默认值处理。比如特殊业务1,ack值设置100。(0-9不建议,给默认通用轮询留下可用空间;
每次申请的特殊轮询ack默认在原先基础最大值上增加100,每次建立轮询通过这个方案执行的ack都要走申请,避免ack重复)。
六.实现类图
方案一:
图1.4 类图
方案二: