Springboot集成RocketMq

序言
  在日常开发中,有很多时候都会使用异步的方式去请求方法,以提高代码的执行效率。比如用户购买某件商品,然后需要插入购买记录,物品-1,微信公众号消息推送之类,流程会很多,也会需要很多时间,而SpringBoot为异步提供了更加简单的使用方式,通过两个注解即可实现异步调用方法。
  SpringBoot为我们提供了很多使用便利,我们只需要一个@Enablexxx注解 + 功能注解,便能轻松简单的实现功能,比如异步调用和定时任务。


**假定使用场景:**用户购买完一件商品,需要短信通知 + 微信消息推送(不考虑失败场景),不需要返回值。

利用@Async开启异步化(不能在同一个类下)

但是Springboot的异步化有缺点

假如异步化里面的内容很复杂,导致线程一直占用

一般来说会集成一个线程池,超过多少的话,则还是会变成同步

这时候就需要引入我们MQ的消息队列 

MQ就是消息队列,和redis一样是个中间件,需要单独安装

常用的MQ有rocketmq,kafka,rabbitmq等

 MQ发送和接收        为二台服务器,可以将二个逻辑放在二台服务器上

客户端(发送方)往一个主题里面放松一个消息,服务端(接收端/消费端)可以去监听这个主题

生产者(Producer)
生产者:也称为消息发布者,负责生产并发送消息至RocketMQ。

消费者(Consumer)
消费者:也称为消息订阅者,负责从RocketMQ接收并消费消息。

消息(Message)
消息:生产或消费的数据,对于RocketMQ来说,消息就是字节数组。

主机(Broker)
RocketMQ的核心,用于暂存和传输消息。

RocketMQ的概念模型
分组(Group)
生产者:标识发送同一类消息的Producer,通常发送逻辑一致。发送普通消息的时候,仅标识使用,并无特别用处。主要作用用于事务消息,事务消息中如果某条发送某条消息的producer-A宕机,使得事务消息一直处于PREPARED状态并超时,则broker会回查同一个group的其它producer,确认这条消息应该commit还是rollback。

消费者:标识一类Consumer的集合名称,这类Consumer通常消费一类消息,且消费逻辑一致。同一个Consumer Group下的各个实例将共同消费topic的消息,起到负载均衡的作用。

消费进度以Consumer Group为粒度管理,不同Consumer Group之间消费进度彼此不受影响,即消息A被Consumer Group1消费过,也会再给Consumer Group2消费。

主题(Topic)
标识一类消息的逻辑名字,消息的逻辑管理单位。无论消息生产还是消费,都需要指定Topic。

区分消息的种类;一个发送者可以发送消息给一个或者多个Topic;一个消息的接收者可以订阅一个或者多个Topic消息。

标签(Tag)
RocketMQ支持给在发送的时候给topic打tag,同一个topic的消息虽然逻辑管理是一样的。但是消费topic的时候,如果你消费订阅的时候指定的是tagA,那么tagB的消息将不会投递。

消息队列(Message Queue)
简称Queue或Q。消息物理管理单位。一个Topic将有若干个Q。若一个Topic创建在不同的Broker,则不同的broker上都有若干Q,消息将物理地存储落在不同Broker结点上,具有水平扩展的能力。

无论生产者还是消费者,实际的生产和消费都是针对Q级别。例如Producer发送消息的时候,会预先选择(默认轮询)好该Topic下面的某一条Q发送;Consumer消费的时候也会负载均衡地分配若干个Q,只拉取对应Q的消息。

每一条message queue均对应一个文件,这个文件存储了实际消息的索引信息。并且即使文件被删除,也能通过实际纯粹的消息文件(commit log)恢复回来。

偏移量(Offset)
RocketMQ中,有很多offset的概念。一般我们只关心暴露到客户端的offset。不指定的话,就是指Message Queue下面的offset。

Message queue是无限长的数组。一条消息进来下标就会涨1,而这个数组的下标就是offset,Message queue中的max offset表示消息的最大offset。

Consumer offset可以理解为标记Consumer Group在一条逻辑Message Queue上,消息消费到哪里即消费进度。但从源码上看,这个数值是消费过的最新消费的消息offset+1,即实际上表示的是下次拉取的offset位置

 一.下载并安装ROCKETMQ,并启动

 二.导入依赖

         RocketMQ
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.0.2</version>
        </dependency>

三.注入RocketMQTemplate

     @Resource
     private RocketMQTemplate rocketMQTemplate;

设置主题为VOTE_TOPIC 

          // 推送消息
            Doc docDb = docMapper.selectByPrimaryKey(id);
            String logId = MDC.get("LOG_ID");
//            wsService.sendInfo("【" + docDb.getName() + "】被点赞!", logId);
             rocketMQTemplate.convertAndSend("VOTE_TOPIC", "【" + docDb.getName() + "】被点赞!");

四.设置消息端

通过注解@RocketMQMessageListener(consumerGroup = "default", topic = "VOTE_TOPIC")

来收到主题为“VOTE_TOPIC”的消息

 package com.jiawa.wiki.rocketmq;

 import com.jiawa.wiki.websocket.WebSocketServer;
 import org.apache.rocketmq.common.message.MessageExt;
 import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
 import org.apache.rocketmq.spring.core.RocketMQListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;

 import javax.annotation.Resource;

 @Service
 @RocketMQMessageListener(consumerGroup = "default", topic = "VOTE_TOPIC")
 public class VoteTopicConsumer implements RocketMQListener<MessageExt> {

     private static final Logger LOG = LoggerFactory.getLogger(VoteTopicConsumer.class);

     @Resource
     public WebSocketServer webSocketServer;

     @Override
     public void onMessage(MessageExt messageExt) {
         byte[] body = messageExt.getBody();
         LOG.info("ROCKETMQ收到消息:{}", new String(body));
         webSocketServer.sendInfo(new String(body));
     }
 }

成功获取消息!!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值