Macula Boot Starter Sender

概览

该模块实现了通过本地表发送事务消息到RocketMQ的功能。

组件坐标

<dependency>
    <groupId>dev.macula.boot</groupId>
    <artifactId>macula-boot-starter-sender</artifactId>
    <version>${macula.version}</version>
</dependency>

使用配置

macula:
  sender:
    message-table: 你的表名 # 默认是MACULA_MSG

唯一的自有属性 macula.sender.message-table 默认为 MACULA_MSG。应用需配置业务 DataSource、事务管理器及 RocketMQ 生产者,并自行建表、安排补偿任务;Starter 不会自动建表或启动定时补偿。RocketMQ 配置参考 RocketMQ 模块。

核心功能

事件消息首先和业务事务一起存储到本地数据库表,然后再发送给 RocketMQ。

业务事务提交后发送消息;发送失败由补偿任务重试。消费端仍需幂等处理,不能将该机制视为消息只投递一次。

使用前,需要在你的业务库中创建如下表(建议定期归档):

create table MACULA_MSG
(
    id           bigint auto_increment primary key,
    orderly      tinyint      not null comment '是否为顺序消息',
    topic        varchar(64)  not null comment 'MQ topic',
    sharding_key varchar(128) not null comment 'ShardingKey,用于选择不同的 partition',
    tag          varchar(128) not null comment 'Message Tag 信息',
    msg_id       varchar(64)  not null comment 'Msg ID 只有发送成功后才有数据',
    msg_key      varchar(64)  not null comment 'MSG Key,用于查询数据',
    msg          longtext     not null comment '要发送的消息',
    retry_time   tinyint      not null comment '重试次数',
    status       tinyint      not null comment '发送状态:0-初始化,1-发送成功,2-发送失败',
    create_time  datetime     not null,
    update_time  datetime     not null,
    index        idx_update_time_status(update_time, status)
)

可以使用相关API进行消息处理:

  • ReliableMessageSender#send 在业务方法中使用,执行可靠消息发送
  • ReliableMessageCompensator#compensate 周期性调度,对未发送或发送失败的消息进行补充
import cn.hutool.core.date.DateUtil;
import dev.macula.boot.starter.sender.ReliableMessageSender;
import dev.macula.boot.starter.sender.ReliableMessageCompensator;
import dev.macula.boot.starter.sender.Message;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;

// 在事务方法中,执行完业务逻辑后,调用MessageSender
@Service
@RequiredArgsConstructor
public class OrderService {
    private final ReliableMessageSender sender;

    private final ReliableMessageCompensator compensator;

    @Transactional
    public void createOrder(OrderDTO order) {
        doBusiness();
        sender.send(buildMessage(order));
    }

    private Message buildMessage(OrderDTO order) {
        Message message = Message.builder()
                .msg(JSONUtil.toJsonStr(order))
                .orderly(true)
                .shardingKey("123")         // 用来数据分区的,暂时没有用
                .msgKey(order.getOrderNo()) // 用订单号,发送顺序消息时有用
                .topic("test_topic")
                .tag("tag")
                .build();
        return message;
    }

    // 下面方法应由任务系统定时调度,用于未成功发送消息的补偿
    public void compensator() {
        compensator.compensate(DateUtil.offsetSecond(new Date(), -120), 100);
    }
}

依赖引入


<dependencies>
  <dependency>
    <groupId>dev.macula.boot</groupId>
    <artifactId>macula-boot-commons</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
  </dependency>

  <dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot-starter</artifactId>
  </dependency>
</dependencies>

版权说明

  • 本模块代码主要来源于 lego。