基于阿里云RocketMQ封装库的集成技术示例

基于阿里云RocketMQ封装库的集成技术示例

整体架构

新建一个私有库,该库封装阿里云 RocketMQ 的三种协议接入方式,通过 Spring Boot 自动配置,根据 YAML 中的 protocol 字段选择不同的消费者客户端实现。

复制代码
application.yml
      │
      ▼
RocketMqProperties (@ConfigurationProperties)
      │
      ├── producer: MqProperties → ONSFactory.createProducer()
      │
      └── consumer: Map<String, MqProperties>
              │
              ▼ (根据 protocol 字段路由)
         ┌────────────┬────────────┬────────────┐
         │    TCP     │    HTTP    │    SELF    │
         ▼            ▼            ▼
  ConsumerBean   MQClient      DefaultMqPush
  (阿里云ONS)   (阿里云HTTP)   ConsumerWrapper
                                (开源RocketMQ)

注:

博客:

https://blog.csdn.net/badao_liumang_qizhi

配置结构

YAML 配置模板

yaml 复制代码
rocketmq:
  producer:
    accessKey: xxx
    secretKey: xxx
    endpoint: http://{instanceId}.{region}.mq.aliyuncs.com:80
    sendMsgTimeoutMillis: 3000   # 可选,默认 3000

  consumer:
    my-consumer-1:              # 自定义消费者名称(key)
      accessKey: xxx
      secretKey: xxx
      endpoint: http://{instanceId}.{region}.mq-internal.aliyuncs.com:8080
      topic: TOPIC_NAME         # 支持 | 分隔多个 topic
      tag: my-tag
      groupId: GID-xxx
      protocol: tcp             # tcp / http / self
      instanceId: MQ_INST_xxx   # 仅 HTTP 协议使用
      msgType: NORMAL           # 仅 SELF 协议使用(NORMAL / ORDERLY)

属性类 MqProperties

java 复制代码
public class MqProperties {
    private String endpoint;
    private String accessKey;
    private String secretKey;
    private String topic;
    private String tag;
    private String groupId;
    private String instanceId;
    private String protocol;
    private String msgType;
    private String sendMsgTimeoutMillis;
}

属性绑定关系

java 复制代码
@Configuration
@EnableConfigurationProperties(RocketMqProperties.class)
public class RocketMqConfig { ... }

@ConfigurationProperties(prefix = "rocketmq")
public class RocketMqProperties {
    private MqProperties producer;
    private Map<String, MqProperties> consumer;
}

三种协议模式对比

特性 TCP HTTP SELF
协议类型 阿里云 ONS TCP 阿里云 HTTP 开源 Apache RocketMQ
客户端类 ConsumerBean MQClient DefaultMqPushConsumerWrapper
使用 accessKey/secretKey
使用 endpoint ✅ (作为 NAMESRV_ADDR) ✅ (作为 HTTP endpoint) ✅ (作为 namesrvAddr)
使用 groupId ✅ (GROUP_ID)
使用 instanceId ✅ (区分实例)
使用 msgType ✅ (NORMAL/ORDERLY)
多 topic 支持 ✅ (用 ` ` 分隔) ✅ (用 `
消息监听接口 TcpMqListener RocketMqHttpPuller SelfBuildMqListener / SelfBuildMqOrderlyListener

生产者初始化流程

java 复制代码
// RocketMqConfig.producer() 等效逻辑
@Bean
public Producer producer() {
    MqProperties props = rocketMqProperties.getProducer();
    if (props == null) return null;

    Properties properties = new Properties();
    properties.put("AccessKey", props.getAccessKey());
    properties.put("SecretKey", props.getSecretKey());
    properties.put("NAMESRV_ADDR", props.getEndpoint());
    properties.put("SendMsgTimeoutMillis",
        StringUtils.defaultIfBlank(props.getSendMsgTimeoutMillis(), "3000"));

    Producer producer = ONSFactory.createProducer(properties);
    producer.start();
    return producer;
}

消费者初始化流程

路由逻辑

ApplicationReadyEvent 事件触发时,遍历所有消费者配置,按 protocol 路由:

java 复制代码
@EventListener
public void handleApplicationReady(ApplicationReadyEvent event) {
    Map<String, xxxRocketMqListener> beans = context.getBeansOfType(JshRocketMqListener.class);
    // 将 listeners 按 topic 分组为 listenerMap

    for (MqProperties mqProperties : rocketMqProperties.getConsumer().values()) {
        MqProtocol protocol = MqProtocol.valueOf(mqProperties.getProtocol().toUpperCase());
        switch (protocol) {
            case HTTP -> clients.add(createHttpClient(mqProperties, listenerMap));
            case TCP  -> clients.add(createTcpClient(mqProperties, listenerMap));
            case SELF -> clients.add(createSelfClient(mqProperties, listenerMap));
        }
    }

    // 启动所有客户端
    clients.forEach(xxxRocketMqConsumerClient::start);
}

TCP 模式 --- createTcpClient

java 复制代码
private xxxRocketMqConsumerClient createTcpClient(MqProperties mqProperties, Map<String, xxxRocketMqListener> listenerMap) {
    Properties properties = new Properties();
    properties.setProperty("GROUP_ID", mqProperties.getGroupId());
    properties.setProperty("AccessKey", mqProperties.getAccessKey());
    properties.setProperty("SecretKey", mqProperties.getSecretKey());
    properties.setProperty("NAMESRV_ADDR", mqProperties.getEndpoint());

    ConsumerBean consumerBean = new ConsumerBean();
    consumerBean.setProperties(properties);

    xxxRocketMqConsumerClient client = new xxxRocketMqConsumerClient(consumerBean);

    // 解析多 topic,为每个 topic 创建订阅
    List<String> topics = Lists.newArrayList(StringUtils.split(mqProperties.getTopic(), "|"));
    for (String topic : topics) {
        String key = String.format("%s_%s",
            topic, StringUtils.defaultIfBlank(mqProperties.getTag(), ""));
        xxxRocketMqListener listener = listenerMap.get(key);

        Subscription subscription = new Subscription();
        subscription.setTopic(topic);
        subscription.setExpression(mqProperties.getTag());

        Map<Subscription, MessageListener> subscriptionTable = new HashMap<>();
        subscriptionTable.put(subscription, new TcpMqListener(listener));
        consumerBean.setSubscriptionTable(subscriptionTable);
    }

    return client;
}

HTTP 模式 --- createHttpClient

java 复制代码
private xxxRocketMqConsumerClient createHttpClient(MqProperties mqProperties, Map<String, xxxRocketMqListener> listenerMap) {
    List<String> topics = Lists.newArrayList(StringUtils.split(mqProperties.getTopic(), "|"));

    MQClient mqClient = new MQClient(
        mqProperties.getEndpoint(),
        mqProperties.getAccessKey(),
        mqProperties.getSecretKey()
    );

    Map<MQConsumer, xxxRocketMqListener> map = new HashMap<>();

    for (String topic : topics) {
        String key = String.format("%s_%s",
            topic, StringUtils.defaultIfBlank(mqProperties.getTag(), ""));
        xxxRocketMqListener listener = listenerMap.get(key);

        MQConsumer consumer;
        if (StringUtils.isNoneBlank(mqProperties.getInstanceId())) {
            // 带 instanceId 的 4 参数版本
            consumer = mqClient.getConsumer(
                mqProperties.getInstanceId(), topic,
                mqProperties.getGroupId(), mqProperties.getTag());
        } else {
            // 不带 instanceId 的 3 参数版本
            consumer = mqClient.getConsumer(topic,
                mqProperties.getGroupId(), mqProperties.getTag());
        }
        map.put(consumer, listener);
    }

    return new xxxRocketMqConsumerClient(map);
}

SELF 模式 --- createSelfClient

java 复制代码
private xxxRocketMqConsumerClient createSelfClient(MqProperties mqProperties, Map<String, xxxRocketMqListener> listenerMap) {
    DefaultMqPushConsumerWrapper consumer = new DefaultMqPushConsumerWrapper(mqProperties.getGroupId());
    consumer.setNamesrvAddr(mqProperties.getEndpoint());
    consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);

    xxxRocketMqConsumerClient client = new xxxRocketMqConsumerClient(consumer);

    List<String> topics = Lists.newArrayList(StringUtils.split(mqProperties.getTopic(), "|"));
    for (String topic : topics) {
        String key = String.format("%s_%s",
            topic, StringUtils.defaultIfBlank(mqProperties.getTag(), ""));
        xxxRocketMqListener listener = listenerMap.get(key);
        consumer.subscribe(topic, mqProperties.getTag());
    }

    // 根据 msgType 注册不同类型的监听器
    MqType mqType = MqType.valueOf(mqProperties.getMsgType().toUpperCase());
    switch (mqType) {
        case NORMAL  -> consumer.registerMessageListener(new SelfBuildMqListener(listener));
        case ORDERLY -> consumer.registerMessageListener(new SelfBuildMqOrderlyListener(listener));
    }

    return client;
}

业务消费者实现模板

接口定义

java 复制代码
public interface xxxRocketMqListener {
    void consume(byte[] bytes);
    String topic();
    String tag();
}

实现示例

java 复制代码
@Component
@Slf4j
public class OrderMqConsumer implements xxxRocketMqListener {

    @Value("${rocketmq.consumer.order.tag}")
    private String tag;

    @Value("${rocketmq.consumer.order.topic}")  // 或直接引用业务 topic 变量
    private String topic;

    @Override
    public void consume(byte[] bytes) {
        OrderDto order = JsonUtil.deserializeObject(bytes, new TypeReference<OrderDto>() {});
        log.info("收到订单消息: {}", order.getId());
        // 业务逻辑
    }

    @Override
    public String topic() {
        return topic;
    }

    @Override
    public String tag() {
        return tag;
    }
}

Listener 匹配机制

库通过 String.format("%s_%s", topic, tag) 生成 key,将 xxxRocketMqListener 的实现与 YAML 中的消费者配置关联起来。消费者实现类的 topic() + tag() 返回值必须与配置一致。


消息发送模板

java 复制代码
@Component
public class OrderMqSender {

    @Autowired
    private Producer producer;

    @Value("${rocketmq.producer.tag}")
    private String tag;

    @Value("${rocketmq.consumer.order.topic}")
    private String topic;

    public void send(OrderDto order) {
        byte[] body = JsonUtil.serializeObject(order).getBytes();
        Message message = new Message(topic, tag, body);
        message.setKey(String.valueOf(order.getId()));
        producer.send(message);
    }
}

生命周期管理

java 复制代码
// 启动:ApplicationReadyEvent 时启动所有 consumer client
clients.forEach(JshRocketMqConsumerClient::start);

// 销毁:ContextClosedEvent 时关闭所有 consumer client
@EventListener
public void handleContextClosed(ContextClosedEvent event) {
    clients.forEach(client -> {
        try { client.destroy(); } catch (Exception e) { ... }
    });
}

// xxxRocketMqConsumerClient 实现了 DisposableBean
public class xxxRocketMqConsumerClient implements DisposableBean {
    public void start() { ... }
    public void destroy() { ... }
}

各属性使用总结

属性 Producer TCP Consumer HTTP Consumer SELF Consumer
accessKey
secretKey
endpoint
groupId
topic
tag
instanceId
protocol --- --- ---
msgType
sendMsgTimeoutMillis

关键设计要点

  1. 多消费者支持consumer 是一个 Map,支持配置多个独立消费者,每个消费者可以有不同的协议、topic、groupId
  2. 多 topic 订阅 :单个消费者配置支持 | 分隔的多个 topic
  3. Listener 自动发现 :通过 Spring 的 getBeansOfType(xxxRocketMqListener.class) 自动收集所有实现类
  4. 延迟启动 :消费者在 ApplicationReadyEvent 之后才启动,确保所有 Bean 初始化完成
  5. 优雅停机 :监听 ContextClosedEvent 关闭所有消费者连接
相关推荐
AKAMAI3 小时前
Linode接口及默认防火墙现已全面开放使用
人工智能·云计算
阿里云云原生11 小时前
一周上线!信永中和基于阿里云 AgentTeams + AI 网关打造多智能体 AI 平台
阿里云·云原生·ai网关·agentteams
发量惊人的中年网工14 小时前
工业视觉云边 AI 推理总是卡顿?SD-WAN 打通边缘算力互联
网络·人工智能·网络安全·云计算
Loveucafe15 小时前
日咖夜酒咖啡厅在哪里
阿里云
故乡dee云17 小时前
AWS 月度账单怎么看?费用明细、扣款时间和结算规则说明
云计算·aws
Loveucafe18 小时前
口碑好的民谣清吧
阿里云
数智化管理手记20 小时前
手工统计指标误差大、效率低?指标管理系统如何告别人工算数痛点?
大数据·运维·数据库·人工智能·云计算
梦想的颜色1 天前
2026 国产大模型硬核横评|阿里云百炼(通义 Qwen3.7 Max)VS DeepSeek V4-Pro:平台、定价、吞吐、能力、工程落地全方位对比
阿里云·通义千问·阿里云百炼·deepseek v4-pro·qwen3.7·llm 吞吐量实测·#企业 maas 平台横评
栈溢出的浪漫1 天前
2026 WAIC 直击丨阿里云全栈AI落地:从芯片算力到智能体原生云
阿里云·全栈ai·2026waic·智能体原生云·大模型产业化