RocketMQ push和pull两种消费模式的使用

一、Push模式和Pull模式的区别

Push模式:实时性强,占用系统资源,消费者关联的消息队列一有消息就会向消费者推送
Pull:实时性差,消息的拉取可控,消费者每隔一段时间去关联的消息队列中拉取消息

二、简单的消息发送

MQ中消息的发送有三种方式:同步,异步和单项

同步:

生产者发送消息时需要知道消费者是否消费成功才发送吓一跳消息,是阻塞的模型,可靠性高,但性能不好

异步:

生产者发送消息不需要知道消费者是否消费成功,发送完消息之后可以继续做自己的事儿,消费者是否消费成功是通过回调的方式告知生产者,可靠性和性能都比较高

单项:

生产者发送完消息之后就不管了,他不会等待结果的返回,也不会有结果返回,可靠性低,性能高

同步消息的实现(send或者syncSend,后者更加灵活,可以定义更多的配置,且有返回值,判断消息成功与否)

//这个是SpringBoot测试的写法
@RunWith(SpringRunner.class)
@SpringBootTest(classes = 启动类的字节码文件)
public class MQTest {
    @Autowired
    private RocketMQTemplate mqTemplate;
    @Test
    /**
     * 同步消息send
     */
    public void sendMessage(){
        Message<String> message = MessageBuilder.withPayload("我是一个字符串消息").build();
        //send(目的地的topic:目的地的tags,要发送的消息);
        mqTemplate.send("topic-test:tags-test",message);
        System.out.println("完成消息发送...");
    }
	/**
     * 同步消息syncSend
     */
    @Test
    public void syncSendMessage(){
        Message<String> message = MessageBuilder.withPayload("我是一个字符串消息").build();
     	/**如果你要将消息封装成对象可以通过以下方式
     		Message<你的消息的类型> message = MessageBuilder.withPayload(你的消息对象).build();
     	**/
        //发送同步消息,2s发送不成功就超时
        //syncSend(目的地的topic:目的地的tags,要发送的消息);
        SendResult sendResult = mqTemplate.syncSend("topic-test:tags-test", message, 2000);
        System.out.println(sendResult);
        //判断发送结果状态
        if(sendResult.getSendStatus() == SendStatus.SEND_OK){
            System.out.println("发送成功");
        }else{
            System.out.println("发送失败");
        }
    }
}

异步消息的简单实现

	/**
     * 异步消息的简单实现
     */
    @Test
    public void asyncSendMessage(){
        Message<String> message = MessageBuilder.withPayload("我是一个字符串消息").build();
        /**如果你要将消息封装成对象可以通过以下方式
     		Message<你的消息的类型> message = MessageBuilder.withPayload(你的消息对象).build();
     	**/
        //asyncSend(目的地的topic:目的地的tags,要发送的消息);
        mqTemplate.asyncSend("topic-test:tags-test", message, new SendCallback() {
            //成功的回调
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println(sendResult);
                System.out.println("发送成功");

            }
            //失败的回调
            @Override
            public void onException(Throwable e) {
                System.out.println("发送失败");
                e.printStackTrace();
            }
        });
    }

单项消息的简单实现

	/**
     * 单项消息的简单实现
     */
    @Test
    public void sendOneWayMessage(){
        Message<String> message = MessageBuilder.withPayload("我是一个字符串消息").build();
        /**如果你要将消息封装成对象可以通过以下方式
     		Message<你的消息的类型> message = MessageBuilder.withPayload(你的消息对象).build();
     	**/
        //sendOneWay(目的地的topic:目的地的tags,要发送的消息);
        mqTemplate.sendOneWay("topic-test:tags-test",message);
        System.out.println("完成消息发送...");
    }

三、简单的消息消费

Push模式:

当消息队列中有消息就推给消费者,基于RocketMQ的监听器,实现RocketMQListener接口(接口的泛型就是你要发送的消息的泛型,可以直接使用MessageExt,后续进行强转),重写其中的onMessage方法,在@RocketMQMessageListener注解中进行配置

@Component//交给Spring管理
@RocketMQMessageListener(
    	//消费者的组名,可以任意指定,唯一即可
        consumerGroup = "consumer-group-xxx",
    	//主题,要和你要消费的消息的topic保持一致
        topic = "topic-test",
    	//tags。要和你要消费的消息的tags保持一致
        selectorExpression = "tags-test",
        //消息消费模式:默认是CLUSTERING集群,还支持BROADCASTING广播,集群就是一对一,广播就是一对多(生产者-消费者)
        messageModel = MessageModel.CLUSTERING)
//MessageExt:Message对象的子类
public class TestConsumer implements RocketMQListener<MessageExt> {

    @Override
    public void onMessage(MessageExt message) {
        //这里拿到的消息 message.getBody 是byte[]格式。
        if(message.getBody() == null ||message.getBody().length == 0)return;
		//拿到消息:如果发送的消息是字符串,那么需要把byte[]转为字符串
        String msg = new String(message.getBody(), StandardCharsets.UTF_8);
        /**如果你传递到RocketMQ中的消息是自定义的对象,那么可以用以下方式读取
        	JSON.parseObject(msg, 你的消息的字节码对象);
        **/
    }
}

Pull模式:使用DefaultMQPullConsumer 的pull方法进行拉取

 	/**
     * 主动拉取消息
     */
    @Autowired
    private DefaultMQPullConsumer pullConsumer;
    @Test
    public void pullMessage(){
        try {
            String orderTags ="tags-test";
            //topic
            String topic = "topic-test";
            //订阅消息队列,指定topic
            Set<MessageQueue> messageQueues = pullConsumer.fetchSubscribeMessageQueues(topic);
            List result = new ArrayList<>();
            for (MessageQueue messageQueue : messageQueues) {
                //long offset = pullConsumer.searchOffset(messageQueue, System.currentTimeMillis());
                //通过偏移量来获取消息
                long offset = pullConsumer.fetchConsumeOffset(messageQueue, true);
                //拉取消息 maxNums是每次最多拉取的消息条数
                PullResult pullResult = pullConsumer.pull(messageQueue, orderTags, offset, 32);
                //找到消息
                if (pullResult != null && pullResult.getPullStatus().equals(PullStatus.FOUND)) {
                    List<MessageExt> messageExtList = pullResult.getMsgFoundList();
                    if (messageExtList == null || messageExtList.size() == 0) continue;
                    for (MessageExt messageExt : messageExtList) {
                        //拿到消息内容,转换为你的消息对象
                        String message = new String(messageExt.getBody(), StandardCharsets.UTF_8);
                         你的消息类型 yourMessage = JSON.parseObject(message, 你的消息类型的字节码对象);
                        //添加到结果列表
                        result.add(yourMessage);
                        //重要:修改消息的消费位置,如果位置不后移,消息会一直被消费
                        pullConsumer.updateConsumeOffset(messageQueue, pullResult.getNextBeginOffset());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new GlobalException("MQ消息拉取失败");
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RocketMQpush模式是指服务端主动将消息推送给消费者客户端。在RocketMQ中,对于每个指定的topic,默认的队列数量是4个。当producer发送消息到topic时,会随机选择一个队列来投递消息,队列序号是0~3。\[2\] 推送的实现方式有两种,一种是采用回调的形式,服务端有事件源后,启动一个线程,遍历所有客户端列表,依次调用其钩子函数。这种方式需要服务端缓存所有客户端列表,并且每次事件源发布都需要调用一次,对资源的浪费较大。另一种方式是利用长轮询的拉来模拟推,实现类似于推的效果。RocketMQ采用的就是这种方式。\[3\] 在push模式下,RocketMQ的源码实现涉及到消息的投递、消费者的注册和消息的推送等过程。具体的源码分析需要深入研究RocketMQ的源码。 #### 引用[.reference_title] - *1* *3* [RocketMQ 消费PUSH 模式详解](https://blog.csdn.net/bingfengxiyang703/article/details/103904900)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [RocketMq 消费消息的两种方式 pullpush](https://blog.csdn.net/zhangcongyi420/article/details/90548393)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值