阿里官方RocketMq使用

本文详细介绍如何使用阿里云消息队列RocketMQ版,包括开通服务、创建资源、使用SDK收发消息等步骤,适用于快速上手的初学者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

快速入门

如果使用的是阿里云主账号,则可以通过本文来体验从开通服务、创建资源、到使用 SDK 收发消息的完整流程,快速上手消息队列 RocketMQ 版。
本文以 HTTP 协议下的 Java SDK 为例进行说明。

步骤一:开通服务

  • 在消息队列 RocketMQ 版产品页,单击立即开通。
  • 在确认订单页面,选择我已阅读并同意《消息队列MQ服务协议》,再单击立即开通即可完成开通。

步骤二:创建资源

在使用消息队列 RocketMQ 版时,请注意以下网络访问限制:

  • TopicGroup ID 需创建在同一个地域(Region)下的同一个实例中才能互通。例如,当某 Topic 创建在华东1(杭州)下的实例 A 中,那么该 Topic 只能被在华东1(杭州)下的实例 A 中创建的 Group ID 对应的生产端和消费端访问。
  • 如果只是测试,或者需要在本地(非阿里云 ECS 服务器)使用消息队列 RocketMQ 版的服务,请将 TopicGroup ID 都创建在公网地域下的实例中。生产端和消费端可以部署在本地或者部署在任意地域的 ECS 上,前提是本地服务器或者相应的 ECS 需要能够访问公网。

创建实例
实例是用于消息队列 RocketMQ 版服务的虚拟机资源,会存储消息主题(Topic)和客户端 ID(Group ID)信息。

  • 登录消息队列 RocketMQ 版控制台。在页面顶部导航栏,选择地域,如公网地域。
  • 在左侧导航栏,单击实例管理。
  • 在实例管理页面右上角,单击创建实例按钮。
  • 在创建实例对话框,选择实例类型,并输入实例名和描述,然后单击确认。

创建 Topic
Topic 是消息队列 RocketMQ 版里对消息的一级归类,例如可以创建 Topic_Trade 这一 Topic 来识别交易类消息,消息生产者将消息发送到 Topic_Trade,而消息消费者则通过订阅该 Topic 来获取和消费消息。

  • Topic 不能跨实例使用,例如在实例 A 中创建的 Topic A 不能在实例 B 中使用。
  • Topic 名称必须在同一实例中是唯一的。
  • 可创建不同的 Topic 来发送不同类型的消息,例如用 Topic A 发送普通消息,Topic B 发送事务消息,Topic C 发送定时/延时消息。
  • 在控制台左侧导航栏,单击 Topic 管理。
  • 在 Topic 管理页面上方选择刚创建的实例,单击创建 Topic 按钮。
  • 在创建 Topic 对话框中的 Topic 一栏,输入 Topic 名称,选择该 Topic 对应的消息类型,输入该 Topic 的备注内容,然后单击确定。
    创建的 Topic 将出现在 Topic 列表中。

创建 Group ID
创建完实例和 Topic 后,您需要为消息的消费者(或生产者)创建客户端 ID ,即 Group ID 作为标识。

  • Group ID 必须在同一实例中是唯一的。
  • Group ID 和 Topic 的关系是 N:N,即一个消费者可以订阅多个 Topic,同一个 Topic 也可以被多个消费者订阅;一个生产者可以向多个 Topic 发送消息,同一个 Topic 也可以接收来自多个生产者的消息。

说明 消费者必须有对应的 Group ID,生产者不做强制要求。

  • 在控制台左侧导航栏,单击 Group 管理。
  • 在 Group 管理页面上方选择刚创建的实例,然后选择 TCP 协议 > 创建 Group ID。本文以 TCP 协议为例。
    说明 TCP 和 HTTP 协议下的 Group ID 不可以共用,因此需分别创建。
  • 在创建 Group ID 对话框中,输入 Group ID 和描述,然后单击确认。

创建阿里云 AccessKey
阿里云 AccessKey 用于收发消息时进行账户鉴权。
在调用 SDK 发送和订阅消息的时候,除了需要指定创建的 Topic 和 Group ID 以外,还需输入您在 RAM 控制台创建的身份验证信息,即 AccessKey。AccessKey 的信息包含 AccessKeyId 和 AcessKeySecret。

步骤三:获取接入点

在控制台创建好资源后,需通过控制台获取实例的接入点。在收发消息时,您需要为生产端和消费端配置该接入点,以此接入某个具体实例或地域的服务。

  • 在控制台左侧导航栏,单击实例管理。

  • 在实例管理页面上方选择刚创建的实例。

  • 在默认显示的实例信息页签的获取接入点信息区域,您可以分别看到新创建实例的 TCP 和 HTTP 协议接入点。接入点性质因协议而异,具体说明如下:

  • HTTP 协议:在控制台看到的 HTTP 协议接入点是某个地域的接入点,跟具体实例无关。在收发消息时还需另外设置实例 ID。

  • 在这里插入图片描述
    完成以上准备工作后,您就可以运行示例代码,用消息队列 RocketMQ 版进行消息发送和订阅了。

步骤四:发送消息

可以通过以下方式发送消息:

  1. 控制台发送消息:用于快速验证 Topic 资源的可用性,主要用作测试。
    * 项目 在控制台左侧导航栏,单击 Topic 管理。
    * 在 Topic 管理页面,找到您刚刚创建的 Topic,单击右侧操作列的发送。
    * 在发送消息对话框中的 Message Body 一栏,输入消息的具体内容,单击确定。
    控制台会返回消息发送成功通知以及相应的 Message ID。

  2. 调用 SDK 发送消息:用于生产环境下使用消息队列 RocketMQ 版。

  3. 下文以调用 HTTP Java SDK 为例进行说明。
    * 通过以下任一方式引入依赖:
    + Maven 方式引入依赖:

          <groupId>com.aliyun.mq</groupId>
          <artifactId>mq-http-sdk</artifactId>
          <version>1.0.1</version>
          <classifier>jar-with-dependencies</classifier>
      </dependency>      
    

根据以下说明设置相关参数,运行示例代码:

/**
 4. @author hcy
 */
public class MqUtil {

    private static String accountEndpoint = "";
    private static String accessId = "";
    private static String accessKey = "";
    private static MqUtil mqUtil;
    // 所属的 Topic
    private static String topic = "";
    private static String groupId = "";
    private static String instanceId = "";

    static {
        // 链接直接从链接池工厂进行获得
        try {
            ResourceBundle bundle = ResourceBundle.getBundle("rocketmq");
            accountEndpoint = bundle.getString("accountEndpoint");
            accessId = bundle.getString("accessId");
            accessKey = bundle.getString("accessKey");
            topic = bundle.getString("topic");
            instanceId = bundle.getString("instanceId");
        } catch (Exception e) {
            e.printStackTrace();
            // TODO: handle exception
        }
    }

    // 发送消息
    private void send(String json, String messageTag) {
        MQClient mqClient = new MQClient(
                // 设置HTTP接入域名(此处以公共云生产环境为例)
                accountEndpoint,
                // AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建
                accessId,
                // SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建
                accessKey
        );
        // 获取Topic的生产者
        MQProducer producer;
        if (instanceId != null && instanceId != "") {
            producer = mqClient.getProducer(instanceId, topic);
        } else {
            producer = mqClient.getProducer(topic);
        }
        try {
            TopicMessage pubMsg = new TopicMessage(
                    // 消息内容
                    json.getBytes(),
                    // 消息标签
                    messageTag
            );

            // 同步发送消息,只要不抛异常就是成功
            TopicMessage pubResultMsg = producer.publishMessage(pubMsg);

            // 同步发送消息,只要不抛异常就是成功
            System.out.println(new Date() + " Send mq message success. Topic is:" + topic + ", msgId is: " + pubResultMsg.getMessageId()
                    + ", bodyMD5 is: " + pubResultMsg.getMessageBodyMD5());
        } catch (Throwable e) {
            // 消息发送失败,需要进行重试处理,可重新发送这条消息或持久化这条数据进行补偿处理
            System.out.println(new Date() + " Send mq message failed. Topic is:" + topic);
            e.printStackTrace();
        }
    }

    public static MqUtil getInstance() {
        if (mqUtil == null) {
            mqUtil = new MqUtil();
        }
        return mqUtil;

    }

    public synchronized void sendMessage(String json, String messageTag)
            throws Exception {
        //处理日志
        this.send(json, messageTag);
    }
}

查看消息是否发送成功
消息发送后,可以在控制台查看消息发送状态,步骤如下:

  1. 在控制台左侧导航栏,选择消息查询 > 按 Message ID 查询。
  2. 在搜索框中输入发送消息后返回的 Message ID,单击搜索查询消息发送状态。
    储存时间表示消息队列 RocketMQ 版服务端存储这条消息的时间。如果查询到此消息,表示消息已经成功发送到服务端。

步骤五:调用 SDK 订阅消息

消息发送成功后,需要启动消费者来订阅消息。下文以调用 HTTP Java SDK 为例说明如何订阅消息。

public static void main(String[] args) {
        MQClient mqClient = new MQClient(
                // 设置HTTP接入域名(此处以公共云生产环境为例)
                "XXX",
                // AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建
                "XXX",
                // SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建
                "XXX"
        );

        // 所属的 Topic
        final String topic = "XXX";
        // 您在控制台创建的 Group ID
        final String groupId = "XXX";
        // Topic所属实例ID,默认实例为空
        final String instanceId = "XXX";

        final MQConsumer consumer;
        if (instanceId != null && instanceId != "") {
            consumer = mqClient.getConsumer(instanceId, topic, groupId, "tagA");
        } else {
            consumer = mqClient.getConsumer(topic, groupId, "tagA");
        }

        // 在当前线程循环消费消息,建议是多开个几个线程并发消费消息
        do {
            List<Message> messages = null;

            try {
                // 长轮询消费消息
                // 长轮询表示如果topic没有消息则请求会在服务端挂住3s,3s内如果有消息可以消费则立即返回
                messages = consumer.consumeMessage(
                        3,// 一次最多消费3条(最多可设置为16条)
                        3// 长轮询时间3秒(最多可设置为30秒)
                );
            } catch (Throwable e) {
                e.printStackTrace();
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
            // 没有消息
            if (messages == null || messages.isEmpty()) {
                //System.out.println(Thread.currentThread().getName() + ": no new message, continue!");
                continue;
            }

            // 处理业务逻辑
            for (Message message : messages) {
                byte[] messageBodyBytes = message.getMessageBodyBytes();
                String messageRec = new String(messageBodyBytes);

                System.out.println(messageRec);
            }

            // Message.nextConsumeTime前若不确认消息消费成功,则消息会重复消费
            // 消息句柄有时间戳,同一条消息每次消费拿到的都不一样
            {
                List<String> handles = new ArrayList<String>();
                for (Message message : messages) {
                    handles.add(message.getReceiptHandle());
                }

                try {
                    consumer.ackMessage(handles);
                } catch (Throwable e) {
                    // 某些消息的句柄可能超时了会导致确认不成功
                    if (e instanceof AckMessageException) {
                        AckMessageException errors = (AckMessageException) e;
                        System.out.println("Ack message fail, requestId is:" + errors.getRequestId() + ", fail handles:");
                        if (errors.getErrorMessages() != null) {
                            for (String errorHandle : errors.getErrorMessages().keySet()) {
                                System.out.println("Handle:" + errorHandle + ", ErrorCode:" + errors.getErrorMessages().get(errorHandle).getErrorCode()
                                        + ", ErrorMsg:" + errors.getErrorMessages().get(errorHandle).getErrorMessage());
                            }
                        }
                        continue;
                    }
                    e.printStackTrace();
                }
            }
        } while (true);
    }
  1. 查看消息订阅是否成功。

完成上述步骤后,您可以在控制台查看消费者是否启动成功,即消息订阅是否成功。

在控制台左侧导航栏,单击 Group 管理。
找到要查看的 Group ID,单击该 Group ID 所在行操作列的订阅关系。
如果是否在线显示为是,且订阅关系一致,则说明订阅成功。否则说明订阅失败。

也可以在打印台查看是否输出消息。
在这里插入图片描述

Topic与Tag最佳实践

在消息队列 RocketMQ 版中,Topic 与 Tag 都是业务上用来归类的标识,区分在于 Topic 是一级分类,而 Tag 可以理解为是二级分类。您可通过本文了解如何搭配使用 Topic 和 Tag 来实现消息过滤。

背景信息
TopicTag 的定义如下:

Topic 消息主题,通过 Topic 对不同的业务消息进行分类。
Tag 消息标签,用来进一步区分某个 Topic 下的消息分类,消息从生产者发出即带上的属性。
Topic 和 Tag 的关系如下图所示。
在这里插入图片描述
适用场景
到底什么时候该用 Topic,什么时候该用 Tag?

建议从以下几个方面进行判断:

  • 消息类型是否一致:如普通消息、事务消息、定时(延时)消息、顺序消息,不同的消息类型使用不同的 Topic,无法通过 Tag 进行区分。
  • 业务是否相关联:没有直接关联的消息,如淘宝交易消息,京东物流消息使用不同的 Topic
    进行区分;而同样是天猫交易消息,电器类订单、女装类订单、化妆品类订单的消息可以用 Tag 进行区分。
  • 消息优先级是否一致:如同样是物流消息,盒马必须小时内送达,天猫超市 24 小时内送达,淘宝物流则相对会慢一些,不同优先级的消息用不同的Topic 进行区分。
  • 消息量级是否相当:有些业务消息虽然量小但是实时性要求高,如果跟某些万亿量级的消息使用同一个
    Topic,则有可能会因为过长的等待时间而“饿死”,此时需要将不同量级的消息进行拆分,使用不同的 Topic。

总的来说,针对消息分类,您可以选择创建多个 Topic,或者在同一个 Topic 下创建多个 Tag。但通常情况下,不同的 Topic 之间的消息没有必然的联系,而 Tag 则用来区分同一个 Topic 下相互关联的消息,例如全集和子集的关系、流程先后的关系。

订阅关系一致

订阅关系一致指的是同一个消费者 Group ID 下所有 Consumer 实例的处理逻辑必须完全一致。一旦订阅关系不一致,消息消费的逻辑就会混乱,甚至导致消息丢失。本文提供订阅关系不一致的示例代码,帮助你顺畅地订阅消息。

背景信息
消息队列 RocketMQ 版里的一个消费者 Group ID 代表一个 Consumer 实例群组。对于大多数分布式应用来说,一个消费者 Group ID 下通常会挂载多个 Consumer 实例。
由于消息队列 RocketMQ 版的订阅关系主要由 Topic + Tag 共同组成,因此,保持订阅关系一致意味着同一个消费者 Group ID 下所有的实例需在以下两方面均保持一致:

  • 订阅的 Topic 必须一致
  • 订阅的 Topic 中的 Tag 必须一致

正确订阅关系图片示例

多个 Group ID 订阅了多个 Topic,并且每个 Group ID 里的多个消费者实例的订阅关系保持了一致。
在这里插入图片描述
错误订阅关系图片示例
单个 Group ID 订阅了多个 Topic,但是该 Group ID 里的多个消费者实例的订阅关系并没有保持一致。

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值