Springboot 整合 RocketMQ

一、RocketMQ整体结构

  • Producer:消息的发送者;举例:发信者。
  • Consumer:消息接受者;举例:收信者。
  • Broker:暂存和传输消息;举例:邮局。
  • Nameserver:管理broker;举例:各个邮局的管理机构
  • Topic:区分消息的种类;一个发送者可以发送一个或多个Topic;一个消息的接收者可以订阅一个或多个Topic消息。
  • Message Queue:相当于是Topic的分区;用于并行发送和接收消息。

二、在Linux服务器环境上搭建RocketMQ服务端

1、下载安装包

官网地址:http://rocketmq.apache.org/dowloading/releases/

2、解压压缩包,重命名文件夹为rocketmq (本人下载的 4.6.1版本)

unzip rocketmq-all-4.6.1-bin-release .zip

mv rocketmq-all-4.6.1-bin-release rocketmq

3、启动NameServer:

nohup sh mqnamesrv &

4、启动broker:

nohup sh mqbroker -n 192.168.12.250:9876  autoCreateTopicEnable=true  &

【注】autoCreateTopicEnable=true 表示可以动态创建topic

三、springboot项目中添加配置

1、pom.xml文件中引入依赖

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

2、配置文件application.yml中添加配置

#RocketMQ:
rocketmq:
  producer:
    isOnOff: on
    groupName: group1
    namesrvAddr: 192.168.12.250:9876
    topic: TRAFFIC_EVENT
    #tag: test
    maxMessageSize: 100
    sendMsgTimeout: 1000
  consumer:
    namesrvAddr: 192.168.12.250:9876
    groupName: group1
    topic: TRAFFIC_EVENT
    #tag: test
    consumeThreadMin: 20
    consumerThreadMax: 64

3、生产者

方式一、同步发送
Producer 向 broker 发送消息,阻塞当前线程等待 broker 响应 发送结果。

方式二、异步发送
Producer 首先构建一个向 broker 发送消息的任务,把该任务提交给线程池,等执行完该任务时,回调用户自定义的回调函数,执行处理结果。

方式三、Oneway 发送
Oneway 方式只负责发送请求,不等待应答,Producer 只负责把请求发出去,而不处理响应结果。

// 1、同步发送
SendResult sendResult = producer.send(msg);
//2、异步发送
producer.send(msg, new SendCallback() {
    @Override
    public void onSuccess(SendResult sendResult) {
    }
    @Override
    public void onException(Throwable e) {
    }
});
//3、 Oneway发送
producer.sendOneway(msg);

4、消费者

方式一:PushConsumer
       push方式里,consumer把轮询过程封装了,并注册MessageListener监听器,取到消息后,唤醒MessageListener的consumeMessage()来消费,对用户而言,感觉消息是被推送过来的。
缺点:实时性高,但增加服务端负载,消费端能力不同,如果push的速度过快,消费端会出现很多问题

方式二:PullConsumer
        pull方式里,取消息的过程需要用户自己写,首先通过打算消费的Topic拿到MessageQueue的集合,遍历MessageQueue集合,然后针对每个MessageQueue批量取消息,一次取完后,记录该队列下一次要取的开始offset,直到取完了,再换另一个MessageQueue。
缺点:消费者从server端拉消息,主动权在消费端,可控性好,但是时间间隔不好设置,间隔太短,则空请求会多,浪费资源,间隔太长,则消息不能及时处理
 

推荐使用PushConsumer,直接上代码!

@Component
@Slf4j
public class MQPushConsumer implements MessageListenerConcurrently {
     private final DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");

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

    /**
     * 初始化
     */
    @PostConstruct //java5中引入,指在项目启动的时候执行这个方法
    public void start() {
        try {
            consumer.setNamesrvAddr(rocketmqNameServer);
            consumer.setVipChannelEnabled(false);
            //从消费队列头开始消费
            consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
            //consumer.setMessageModel(MessageModel.CLUSTERING);
            //订阅主题
            consumer.subscribe("TRAFFIC_EVENT","*");
            consumer.registerMessageListener(this);
            consumer.start();
            log.info("[启动日志]:MQ消费者已启动");
        } catch (MQClientException e) {
            e.printStackTrace();
        }
    }

    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
        int index=0;
        try {
                for (;index<list.size();index++) {
                    MessageExt msg = list.get(index);
                    String messageBody = new String(msg.getBody(), RemotingHelper.DEFAULT_CHARSET);

                    log.info("MQ:消费者接受新消息:{}{}{}{}{}", msg.getMsgId(), msg.getTopic(), msg.getTags(), msg.getKeys(), messageBody);
                    //拿到json通过websocket发给前端
                    if (!StringUtils.isEmpty(messageBody) && MyWebSocket.getOnlineCount() >0) {
                        MyWebSocket.sendInfo(messageBody);
                        log.info("[webSocket发送]" + messageBody);
                    }
                }
            } catch (Exception e) {
               log.error(e.getMessage(),e);
            }finally {

                if (index < list.size()) {
                    consumeConcurrentlyContext.setAckIndex(index+1);
                }
            }
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }

    @PreDestroy //在关闭spring容器后释放一些资源*
    public void stop() {
        if (null != consumer) {
            consumer.shutdown();
            log.error("MQ: 关闭消费者");
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值