[RocketMQ 消息队列异步通信]

目录

 🎂前言:

 🎂引入 Maven 依赖:

 🎂发送消息:

 🎂接收消息:

 🎂除了上面提到的优化,我们还可以进一步优化RocketMQ的使用,具体如下:

 🎂生产者类RocketMQProducer.java:

   🎂讲解:

 🎂消费者类RocketMQConsumer.java:

  🎂讲解:

 🎂测试类RocketMQTest.java:


 🎂前言:

  前面写了rabbitMq的消息队列,今天补充一下RocketMQ  

 🎂引入 Maven 依赖:

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.9.0</version>
</dependency>

 🎂发送消息:

import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;

import java.nio.charset.StandardCharsets;

public class AsyncProducer {

    public static void main(String[] args) {
        DefaultMQProducer producer = new DefaultMQProducer("producer-group");
        producer.setNamesrvAddr("localhost:9876");

        try {
            producer.start();

            for (int i = 0; i < 10; i++) {
                Message message = new Message("topic", "tag", ("消息" + i).getBytes(StandardCharsets.UTF_8));
                producer.send(message, new SendCallback() {
                    @Override
                    public void onSuccess(SendResult sendResult) {
                        System.out.println("消息发送成功:" + sendResult);
                    }

                    @Override
                    public void onException(Throwable throwable) {
                        System.out.println("消息发送失败:" + throwable.getMessage());
                    }
                });
            }

            Thread.sleep(10000); // 等待消息发送完成
        } catch (MQClientException | InterruptedException e) {
            e.printStackTrace();
        } finally {
            producer.shutdown();
        }
    }
}

 🎂接收消息:

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;

import java.util.List;

public class AsyncConsumer {

    public static void main(String[] args) {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer-group");
        consumer.setNamesrvAddr("localhost:9876");
        try {
            consumer.subscribe("topic", "tag");
            consumer.registerMessageListener(new MessageListenerConcurrently() {
                @Override
                public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                    System.out.println("消息接收成功:" + list);
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                }
            });
            consumer.start();

            Thread.sleep(10000); // 等待消息接收完成
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            consumer.shutdown();
        }
    }
}

 

在上面的代码中,异步通信是通过设置 SendCallback 回调函数来实现的。在发送消息时,我们使用 producer.send() 方法并设置回调函数 SendCallback,当消息发送成功或失败时,程序会回调相应的方法。

消息发送成功时,SendCallback.onSuccess() 方法会被调用,我们可以在这里处理发送成功的逻辑,比如打印日志。而当消息发送失败时,SendCallback.onException() 方法会被调用,我们可以在这里处理发送失败的逻辑,比如打印错误信息。

由于消息的发送和接收都是异步的,因此我们需要等待一段时间,让消息发送和接收完成。在示例代码中,我们使用 Thread.sleep() 方法进行了等待,但实际应用中,这种方式并不可取,因为无法保证等待时间是否准确。正确的方式是使用其他的方式来进行等待,比如使用计数器或者等待条件的方式。

需要注意的是,如果在发送消息时设置了回调函数 SendCallback,那么消息将会异步发送,即程序不会等待消息发送完成就继续执行后续逻辑。因此,在异步通信中,我们需要仔细考虑消息发送和接收的顺序,以保证消息的正确性。

 🎂除了上面提到的优化,我们还可以进一步优化RocketMQ的使用,具体如下:

  • 使用RocketMQ的事务消息功能,确保消息的可靠性和一致性。

  • 使用RocketMQ的延迟消息功能,实现定时任务和延迟消息的发送。

  • 使用RocketMQ的顺序消息功能,确保消息的顺序性。

  • 使用RocketMQ的批量消息功能,提高消息的发送效率。

 

 🎂生产者类RocketMQProducer.java

public class RocketMQProducer {
    private final String namesrvAddr;
    private final String group;
    private final String topic;

    public RocketMQProducer(String namesrvAddr, String group, String topic) {
        this.namesrvAddr = namesrvAddr;
        this.group = group;
        this.topic = topic;
    }

    public void send(String message) throws Exception {
        try (TransactionMQProducer producer = new TransactionMQProducer(group)) {
            producer.setNamesrvAddr(namesrvAddr);
            producer.setTransactionListener(new TransactionListenerImpl());
            producer.start();
            Message msg = new Message(topic, "", message.getBytes(StandardCharsets.UTF_8));
            TransactionSendResult result = producer.sendMessageInTransaction(msg, null);
            System.out.printf("消息发送结果:%s%n", result);
        }
    }

    public void sendDelay(String message, int delayTime) throws Exception {
        try (DefaultMQProducer producer = new DefaultMQProducer(group)) {
            producer.setNamesrvAddr(namesrvAddr);
            producer.start();
            Message msg = new Message(topic, "", message.getBytes(StandardCharsets.UTF_8));
            msg.setDelayTimeLevel(delayTime);
            SendResult result = producer.send(msg);
            System.out.printf("消息发送结果:%s%n", result);
        }
    }

    public void sendOrderly(List<String> messages) throws Exception {
        try (DefaultMQProducer producer = new DefaultMQProducer(group)) {
            producer.setNamesrvAddr(namesrvAddr);
            producer.start();
            for (String message : messages) {
                Message msg = new Message(topic, "", message.getBytes(StandardCharsets.UTF_8));
                SendResult result = producer.send(msg, new MessageQueueSelector() {
                    @Override
                    public MessageQueue select(List<MessageQueue> list, Message message, Object o) {
                        int index = (int) o % list.size();
                        return list.get(index);
                    }
                }, messages.indexOf(message));
                System.out.printf("消息发送结果:%s%n", result);
            }
        }
    }

    public void sendBatch(List<String> messages) throws Exception {
        try (DefaultMQProducer producer = new DefaultMQProducer(group)) {
            producer.setNamesrvAddr(namesrvAddr);
            producer.start();
            List<Message> msgList = new ArrayList<>();
            for (String message : messages) {
                Message msg = new Message(topic, "", message.getBytes(StandardCharsets.UTF_8));
                msgList.add(msg);
            }
            SendResult result = producer.send(msgList);
            System.out.printf("消息发送结果:%s%n", result);
        }
    }

    static class TransactionListenerImpl implements TransactionListener {
        private final Random random = new Random();

        @Override
        public LocalTransactionState executeLocalTransaction(Message message, Object o) {
            int status = random.nextInt(3);
            switch (status) {
                case 0:
                    return LocalTransactionState.UNKNOW;
                case 1:
                    return LocalTransactionState.COMMIT_MESSAGE;
                case 2:
                    return LocalTransactionState.ROLLBACK_MESSAGE;
                default:
                    return LocalTransactionState.UNKNOW;
            }
        }

        @Override
        public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
            return LocalTransactionState.COMMIT_MESSAGE;
        }
    }
}
   🎂讲解:
  • RocketMQProducer类是RocketMQ的生产者类,用于发送消息。
  • send方法用于发送事务消息,首先创建一个TransactionMQProducer对象,设置RocketMQ的Namesrv地址和事务监听器,然后启动生产者。接着创建一个消息对象Message,设置消息的主题、标签和内容,调用sendMessageInTransaction方法发送消息,并返回事务消息的发送结果。
  • sendDelay方法用于发送延迟消息,首先创建一个DefaultMQProducer对象,设置RocketMQ的Namesrv地址,然后启动生产者。接着创建一个消息对象Message,设置消息的主题、标签、内容和延迟时间,调用send方法发送消息,并返回延迟消息的发送结果。
  • sendOrderly方法用于发送顺序消息,首先创建一个DefaultMQProducer对象,设置RocketMQ的Namesrv地址,然后启动生产者。接着遍历消息列表,创建一个消息对象Message,设置消息的主题、标签和内容,调用send方法发送消息,并返回顺序消息的发送结果。
  • sendBatch方法用于发送批量消息,首先创建一个DefaultMQProducer对象,设置RocketMQ的Namesrv地址,然后启动生产者。接着遍历消息列表,创建一个消息对象Message,设置消息的主题、标签和内容,并将消息添加到消息列表中。最后调用send方法发送消息,并返回批量消息的发送结果。
  • TransactionListenerImpl是事务监听器的实现类,用于处理事务消息的本地事务和事务状态检查。在executeLocalTransaction方法中,我们随机生成一个事务状态,模拟本地事务的执行结果。在checkLocalTransaction方法中,我们直接返回COMMIT_MESSAGE,表示事务已经提交。
  • RocketMQProducer类中,我们使用了try-with-resources语句来自动关闭生产者对象,避免了资源泄漏的问题。

 🎂消费者类RocketMQConsumer.java

public class RocketMQConsumer {
    private final String namesrvAddr;
    private final String group;
    private final String topic;
    private final String tag;

    public RocketMQConsumer(String namesrvAddr, String group, String topic, String tag) {
        this.namesrvAddr = namesrvAddr;
        this.group = group;
        this.topic = topic;
        this.tag = tag;
    }

    public void receive() throws Exception {
        try (DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(group)) {
            consumer.setNamesrvAddr(namesrvAddr);
            consumer.subscribe(topic, tag);
            consumer.registerMessageListener(new MessageListenerConcurrently() {
                @Override
                public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                    for (MessageExt message : list) {
                        System.out.printf("接收到消息:%s%n", new String(message.getBody(), StandardCharsets.UTF_8));
                    }
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                }
            });
            consumer.start();
            System.out.println("消费者已启动");
            Thread.sleep(Long.MAX_VALUE);
        }
    }

    public void receiveOrderly() throws Exception {
        try (DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(group)) {
            consumer.setNamesrvAddr(namesrvAddr);
            consumer.subscribe(topic, tag);
            consumer.registerMessageListener(new MessageListenerOrderly() {
                @Override
                public ConsumeOrderlyStatus consumeMessage(List<MessageExt> list, ConsumeOrderlyContext consumeOrderlyContext) {
                    for (MessageExt message : list) {
                        System.out.printf("接收到消息:%s%n", new String(message.getBody(), StandardCharsets.UTF_8));
                    }
                    return ConsumeOrderlyStatus.SUCCESS;
                }
            });
            consumer.start();
            System.out.println("消费者已启动");
            Thread.sleep(Long.MAX_VALUE);
        }
    }
}
  🎂讲解:
  • RocketMQConsumer类是RocketMQ的消费者类,用于接收消息。
  • receive方法用于接收普通消息,首先创建一个DefaultMQPushConsumer对象,设置RocketMQ的Namesrv地址和消费者组,然后订阅主题和标签。接着注册一个消息监听器MessageListenerConcurrently,在consumeMessage方法中处理接收到的消息,并返回消费结果。最后启动消费者,并让线程休眠,等待消息的到来。
  • receiveOrderly方法用于接收顺序消息,首先创建一个DefaultMQPushConsumer对象,设置RocketMQ的Namesrv地址和消费者组,然后订阅主题和标签。接着注册一个消息监听器MessageListenerOrderly,在consumeMessage方法中处理接收到的消息,并返回消费结果。最后启动消费者,并让线程休眠,等待消息的到来。

 🎂测试类RocketMQTest.java

public class RocketMQTest {
    public static void main(String[] args) throws Exception {
        Properties props = new Properties();
        try (InputStream in = RocketMQTest.class.getClassLoader().getResourceAsStream("application.properties")) {
            props.load(in);
        }
        String namesrvAddr = props.getProperty("rocketmq.namesrvAddr");
        String producerGroup = props.getProperty("rocketmq.producer.group");
        String consumerGroup = props.getProperty("rocketmq.consumer.group");
        String topic = props.getProperty("rocketmq.topic");
        String tag = props.getProperty("rocketmq.tag");

        RocketMQProducer producer = new RocketMQProducer(namesrvAddr, producerGroup, topic);
        producer.send("Hello, RocketMQ!");
        producer.sendDelay("Hello, RocketMQ! (delayed)", 3);
        producer.sendOrderly(Arrays.asList("A", "B", "C", "D", "E"));
        producer.sendBatch(Arrays.asList("1", "2", "3", "4", "5"));

        RocketMQConsumer consumer = new RocketMQConsumer(namesrvAddr, consumerGroup, topic, tag);
        consumer.receive();
        consumer.receiveOrderly();
    }
}
  • main函数中,我们首先读取配置文件中的RocketMQ相关配置,然后创建生产者和消费者对象,并调用它们的方法来发送和接收消息。
  • 在配置文件中,我们设置了RocketMQ的Namesrv地址、生产者组、消费者组、主题和标签。这些配置项可以根据实际情况进行修改。
  • rocketmq.namesrvAddr=localhost:9876
    rocketmq.producer.group=producer_group
    rocketmq.consumer.group=consumer_group
    rocketmq.topic=test_topic
    rocketmq.tag=test_tag
     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是汤圆丫

怎么 给1分?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值