优质博文:IT-BLOG-CN
一、代码规范
【1】消费者必须以Consumer
结尾,生产者必须以Producer
结尾。
【2】选择合适的消费模式:根据业务判断消费模式是集群模式还是广播模式,具体为:MessageConsumerProvider.addListener(String subject, String consumerGroup, MessageListener listener,boolean consumeMostOnce)
//consumerGroup
为空时是广播模式,否则为集群模式。
【3】选择适合的队列类型:根据业务判断消费模式是普通队列还是延迟队列,具体为:Message message = producer.generateMessage("qmq.fx.test");
// 延迟10smessage.setDelayTime(10, TimeUnit.SECONDS);
。
【4】选择适合的消费者数量:若想加快消费速度,可以新增单台机器的消费者数量,具体为:MessageListenerConfig messageListenerConfig = new MessageListenerConfig();messageListenerConfig.setNotifierThreadCount(Runtime.getRuntime().availableProcessors());
。
二、命令规范
【1】若为监听数据库,命名为top.cache.db.topcoredb.表名
若为其他业务需要,命名为top.模块.业务
。
配置规范
【1】需要新增配置文件xxx.qmq.properties
:若应用使用qmq
,需要新增配置文件xxx.qmq.properties
,否则会导致qmq
初始化失败。
【2】明确使用的场景:解耦减少依赖,使核心业务外的其他业务插件化,例如订单出票后需要发邮件,库存卖空需要触发报警等削峰异步化,前置流量过大,将整体流程拆为两部分,核心逻辑保持干净和足够的性能,较重的逻辑后置处理定时器支持在未来指定时刻消费消息,减少业务侧轮询任务的开发。
【3】慎用Pull
模式:确保所有分支都覆盖ACK
,最好是有finally
,建议Push
模式:采用自动ack
,无须业务线程池。
【4】有限次数的重试。
【5】消息量适度:消息量过大且消费者来不及处理会导致消息堆积。
【6】消息大小适度:业务消息<4KB
。
【7】合并处理:相同处理对象更新频次较高场景,建议滑动窗口聚合.
【8】尽量避免使用有序消息:有时序要求场景,和服务提供方确认是不是同步写入。
【9】消息重复投递,业务要做容错:幂等处理。
【10】消息堆积、延迟、处理能力下降等指标监控。
【11】防止jackson
版本不一致:jackson
版本不一致可能会导致反序列化的结果不一致。
【12】对消息量大的消息队列可以单独拆分:监听binlog
时,对于消息量大又不太重要的表,可以拆分消息队列,将这部分放到单独的消息队列中,可以避免这部分消息积压影响重要数据。
【13】重要数据持久化消息或做补偿动作:正常qmq
客户端不能保证消息不丢失,如果对对消息有可靠性要求,需要持久化消息或做补偿动作。比如数据库监听binlog
,将订单状态通过qmq
进行同步,实际情况可能存在丢失;可以通过定时任务查询数据库进行补偿。
三、使用规范
【1】QMQ
新主题通过注册模式部署到独立的集群, 避免直接代码中定义与使用。
【2】QMQ
适用范围, 避免滥用。
☑️ 不能将QMQ
用作数据传输, 数据存储等功能。
☑️ 适用于状态通知,事件驱动。
☑️ 适用于异步解耦。
☑️ 契约json
遵循最精简方式, 只传递基本信息, 如订单号, 状态等, 其他业务处理数据依赖接口反查. 同时精简有利于后续的补偿与异常处理。
【3】QMQ
生产者和消费者代码目前存在的问题:
☑️ 规范不统一, 编码风格不统一, 订阅和推送QMQ
消息代码写法各异。
☑️ 消费者与生产者的代码散落在各个地方, 同一个topic
存在多个producer
。
☑️ QMQ
缺乏契约治理, 消费者/生产者都需感知具体的message
, 定义一个或多个类做json
转换或读取具体的message
属性。
☑️ 开发直接依赖的是QMQ
框架Message
, 读取各个property
或字符串再转为对象, 非直接面向对象的编码风格。
【4】对于QMQ
生产者与消费者编码在框架基础上再次进行了统一的封装,实现代码风格与编码规范的统一。
☑️ 消费者模板
a) QMQ
消费者(流量入口)只能在service
层的consumer package
b) 命名后缀为XXXConsumer
。
☑️ 生产者模板
a) QMQ
生产者只能在service
层的producer package
。
b) 命名后缀为XXXProducer
。
c) 同一个Topic
只能有一个Producer
,严格禁止在不同的应用或单个应用不同的package
中出现相同topic
的生产者。
☑️ 生产者与消费者共同依赖契约对象
a) QMQ
契约类为contract
层。
b) QMQ
即使是只有1
,2
个property
, 也需定义一个类,走统一的对象模式。
b) 发布Contract Jar
, 提供maven
依赖给消费者, 包括后续升级同步。
☑️ 放到独立Consumer
集群。消费时,调用业务API
接口进行处理。
☑️ 返回状态要正确。如果消费成功,那么返回成功,否则返回失败。
【5】QMQ
订阅之后的处理逻辑即使非常简单, 调用链也必须是如下的统一模式, 流程或控制代码在service
层,细节代码在process
层.SendMessageService
(service
层) → SendMessageProcess
(process
层)
【6】QMQ
生产,需要注意几点:
☑️ 生产失败如何处理?
a) 失败记录信息。
b) Job
补偿处理。
☑️ 生产Q
是否需要持久化。
a) 核心Q
必须持久化。
【7】QMQ
异常消费重试注意:重试分本地重试和远程重试。如果使用本地重试,一定要设置最大重试次数,防止死循环。
【8】topic
和ConsumerGroup
的长度不允许超过170
。