Springboot集成RocketMQ进行消息发送订阅

在进行业务开发过程中肯定会存在业务数据的传递调用,正常情况下的做法可能有很多,webService、REST接口等等,都可以实现此类的需求,但是接口会存在什么问题呢,有可能挂掉或者网络问题等等原因。如果多个业务都需要同一个数据,那么就要调用多次接口,如果推送到MQ中,其他业务按需进行订阅数据,这样就减少系统间的接口调用等等。那么下面就来说一下Springboot集成RocketMQ进行消息的生产订阅。

首先在POM中加入RocketMQ的依赖。
此处使用的是阿里云线上的RocketMQ,不是自己搭建的(特此说明)。

<!-- rocketMQ -->
<!-- 因为需要使用fastjson的1.2.58版本,去掉MQ中的fastjson依赖 -->
<dependency>
    <groupId>com.aliyun.openservices</groupId>
    <artifactId>ons-client</artifactId>
    <version>1.8.0.Final</version>
    <exclusions>
        <exclusion>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </exclusion>
    </exclusions>
</dependency>

然后进行application.yml的配置:

rocketMQ:
  # 线上MQ的GroupId固定以GID_开头
  groupId: GID_Form
  topic: form
  consumerTag: form
  # MQ 提供:广播订阅和集群订阅模式
  messageModel: BROADCASTING #广播订阅方式

然后进行RocketMQ的配置类开发:

import com.aliyun.openservices.ons.api.PropertyKeyConst;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration
public class RocketMQConfig {

    public Properties getProperties() {
        Properties properties = new Properties();
        // AccessKey 线上MQ 会生成
        properties.setProperty("AccessKey", "*****");
        // SecretKey 线上MQ 会生成
        properties.setProperty("SecretKey", "******");
        properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis, "3000");
        // 顺序消息消费失败进行重试前的等待时间,单位(毫秒)
        properties.put(PropertyKeyConst.SuspendTimeMillis, "100");
        // 消息消费失败时的最大重试次数
        properties.put(PropertyKeyConst.MaxReconsumeTimes, "20");
        // address地址 线上MQ 会提供
        properties.put(PropertyKeyConst.NAMESRV_ADDR, "");
        return properties;
    }

}

然后进行消息的生产service类:

import com.aliyun.openservices.ons.api.Message;
import com.**.**.form.rocketProducer.RocketProducer;
import com.**.**.form.service.PushMessageService;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Iterator;

@Service
@Transactional
public class PushMessageServiceImpl implements PushMessageService {

    private final static Logger logger = LoggerFactory.getLogger(PushMessageServiceImpl.class);

    @Value(value = "${rocketMQ.topic}")
    String topic;

    @Value(value = "${rocketMQ.consumerTag}")
    String messageTag;

    @Value(value = "${rocketMQ.groupId}")
    String groupId;

    @Autowired
    RocketProducer rocketProducer;

    @Override
    public boolean pushMessage(String requestParam) {
        boolean sendStatus = true;
        if (!StringUtils.isEmpty(requestParam)) {
            JSONObject jsonObject = JSONObject.fromObject(requestParam);
            // RocketMQ 每条消息的messageKey,可以不进行填写,也可以重复,为了方面后续查询,设置为不重复
            String businessId = jsonObject.getString(BUSINESS_ID_KEY);
            String messageBody = jsonObject.toString();
            Message message = new Message(topic, messageTag, messageBody.getBytes());
            message.setKey(businessId);
            boolean value = rocketProducer.sendNormalMessage(message, groupId);
            if (!value) {
                sendStatus = false;
                logger.info("推送消息失败,数据为:" + requestParam);
            }
        }
        return sendStatus;
    }

}

发送消息类:

package com.**.**.form.rocketProducer;

import com.aliyun.openservices.ons.api.*;
import com.**.**.form.config.RocketMQConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Properties;

@Component
@SuppressWarnings({"unused"})
public class RocketProducer {

    private static final Logger logger = LoggerFactory.getLogger(RocketProducer.class);

    @Autowired
    RocketMQConfig rocketMQConfig;

    /**
     * @Description 发送普通消息
     */
    public boolean sendNormalMessage(Message message, String groupId) {
        Properties properties = rocketMQConfig.getProperties();
        properties.setProperty(PropertyKeyConst.GROUP_ID, groupId);
        Producer producer = ONSFactory.createProducer(properties);
        // 在发送消息前,必须调用 start 方法来启动 Producer,只需调用一次即可
        producer.start();
        try {
            SendResult sendResult = producer.send(message);
            // 同步发送消息,只要不抛异常就是成功
            if (sendResult != null) {
                logger.info("消息发送成功:messageID:" + sendResult.getMessageId());
                return true;
            }
        } catch (Exception e) {
            // 消息发送失败,需要进行重试处理,可重新发送这条消息或持久化这条数据进行补偿处理
            logger.info("发送消息失败:" + e);
        } finally {
            producer.shutdown();
        }
        return false;
    }

}

然后进行消息订阅类:

import com.aliyun.openservices.ons.api.*;
import com.**.**.form.config.RocketMQConfig;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Properties;

@Component
@Slf4j
public class RocketMQConsumer {

    public static final Logger logger = LoggerFactory.getLogger(RocketMQConsumer.class);

    @Autowired
    RocketMQConfig rocketMQConfig;

    @Value(value = "${rocketMQ.groupId}")
    String groupId;

    @Value(value = "${rocketMQ.topic}")
    String topic;
    
    @Value(value = "${rocketMQ.consumerTag}")
    String consumerTag;

    @Value(value = "${rocketMQ.messageModel}")
    String messageModel;

    public void normalSubscribe() {
        final Properties properties = rocketMQConfig.getProperties();
        properties.put(PropertyKeyConst.GROUP_ID, groupId);
        if (!StringUtils.isEmpty(messageModel)){
            properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.BROADCASTING);
        }
        // 批量消费,每次拉取10条
        consumer.subscribe(topic, consumerTag, (message, context) -> {
            System.out.println("Receive: " + new String(message.getBody()));
            String messageBody = new String(message.getBody());
            JSONObject jsonObject = JSONObject.fromObject(messageBody);
            try {
                // 订阅到消息体后进行自己的业务
            } catch (Exception e) {
                e.printStackTrace();
                if (!PropertyValueConst.BROADCASTING.equals(properties.getProperty(PropertyKeyConst.MessageModel))){
                    return Action.ReconsumeLater;
                } else {
                    return Action.CommitMessage;
                }
            }
            return Action.CommitMessage;
        });

        consumer.start();
    }

}

消息订阅需要程序启动时进行一次订阅,否则订阅不到消息:

import com.**.**.rocketmq.consumer.RocketMQConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class RocketConsumerListener implements CommandLineRunner {

    private static final Logger logger = LoggerFactory.getLogger(RocketConsumerListener.class);

    @Autowired
    RocketMQConsumer rocketMQConsumer;

    @Override
    public void run(String... args) throws Exception {
        //System.out.println("=======rocketMQ消费者启动=======");
        logger.info("======RocketMQ消费者启动======");
        rocketMQConsumer.normalSubscribe();
    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值