Springboot 集成RocketMQ4.4.0 遇到的问题 以及我的解决方法

RocketMQ4.4.0

最近在做一个小项目的过程中使用了MQ消息队列。

选择哪种MQ我也纠结了很久,最后选择了阿里的开源项目RocketMQ,不过现在已经贡献给Apache社区了。

但是在使用的过程中也是踩了很多坑的,下面我会把我遇到的一些问题罗列出来。

  1. No route info of this topic
  2. 本地连接服务器连接超时,连接失败
  3. topic可以创建,可以发送消息,但是没有被消费
  4. 一个consumer订阅多个topic应该怎么设置。

 

问题多多,但是都是环境的问题,代码基本上都是一样的,所以出了问题首先检查的就是你的环境是否连接正确。

 

下面我把我的代码环境配置罗列一下:

  • 消费者Producer

 

import lombok.extern.slf4j.Slf4j;
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 org.apache.rocketmq.remoting.common.RemotingHelper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * rocketMq 生产者包装
 *
 * @author zhengjf
 * @version 1.0
 * @date 2019/3/5
 */
@Service
@Slf4j
public class MqProducerService {

    @Value("${rocketmq.name-server}")
    private String namesrvAddr;

    @Value("${rocketmq.producer.group}")
    private String producerGroup;

    private DefaultMQProducer producer;

    /**
     * DefaultMQProducer 普通消息生产者对象创建
     *
     * @return void
     * @author zhengjf
     * @date 2019/3/5
     */
    @PostConstruct
    public void initProducer() {
        producer = new DefaultMQProducer(producerGroup);
        producer.setNamesrvAddr(namesrvAddr);
        producer.setRetryTimesWhenSendFailed(3);
        producer.setVipChannelEnabled(false);
        try {
            producer.start();
            log.info("[Producer 已启动]");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 普通消息  同步发送消息,只要不抛异常就是成功
     *
     * @param topic, tags, msg
     * @return java.lang.String
     * @author zhengjf
     * @date 2019/3/5
     */
    public SendResult send(String topic, String tags, String msg) throws Exception {
        Message message = new Message(
                // Message所属的Topic
                topic,
                // Message Tag,可理解为mail中的标签,对消息进行再归类,方便Consumer指定过滤条件在MQ服务器过滤
                tags,
                // Message Body,任何二进制形式的数据,MQ不做任何干预,需要Producer与Consumer协商好一致的序列化和反序列化方式
                msg.getBytes(RemotingHelper.DEFAULT_CHARSET));

        SendResult result = producer.send(message);
        log.info("发送消息后返回:" + result.toString());
        return result;
    }

    /**
     * 延时发送
     * RocketMQ目前指定的延时时间间隔有DelayTimeLevel 1s,5s,10s,30s,1m,2m,3m,4m,5m,6m,7m,8m,9m,10m,20m,30m,1h,2h,用等级来表示时间间隔。
     *
     * @param topic, tags, msg, delayTimeLevel 时间等级(30分钟是16)
     * @return org.apache.rocketmq.client.producer.SendResult
     * @author zhengjf
     * @date 2019/3/5
     */
    public SendResult sendDelayTime(String topic, String tags, String msg, int delayTimeLevel) throws Exception {
        Message message = new Message(
                // Message所属的Topic
                topic,
                // Message Tag,可理解为mail中的标签,对消息进行再归类,方便Consumer指定过滤条件在MQ服务器过滤
                tags,
                // Message Body,任何二进制形式的数据,MQ不做任何干预,需要Producer与Consumer协商好一致的序列化和反序列化方式
                msg.getBytes(RemotingHelper.DEFAULT_CHARSET));

        message.setDelayTimeLevel(delayTimeLevel);
        SendResult result = producer.send(message);
        log.info("发送消息后返回:" + result.toString());
        return result;
    }


    /**
     * 这里用到了这个mq的异步处理,类似ajax,可以得到发送到mq的情况,并做相应的处理
     * 不过要注意的是这个是异步的
     *
     * @param topic, tags, msg
     * @return void
     * @author zhengjf
     * @date 2019/3/5
     */
    public String sendAsync(String topic, String tags, String msg) throws Exception {
        Message message = new Message(
                // Message所属的Topic
                topic,
                // Message Tag,可理解为Gmail中的标签,对消息进行再归类,方便Consumer指定过滤条件在MQ服务器过滤
                tags,
                // Message Body,任何二进制形式的数据,MQ不做任何干预,需要Producer与Consumer协商好一致的序列化和反序列化方式
                msg.getBytes(RemotingHelper.DEFAULT_CHARSET));
        producer.send(message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                log.info("传输成功。" + sendResult.toString());
            }

            @Override
            public void onException(Throwable e) {
                log.error("传输失败", e);
            }
        });
        // 在callback返回之前。
        log.info("send message async." + message.toString());
        return message.toString();
    }

    @PreDestroy
    public void shutDownProducer() {
        if (producer != null) {
            producer.shutdown();
        }
    }
}

 

  • 消费者监听
import com.mjs.common.common.OrderStatusEnum;
import com.mjs.mojisishop.entity.OrderInfo;
import com.mjs.mojisishop.mapper.OrderInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 监听MQ的主题消息,进行消费。可以监听多个
 *
 * @author zhengjf
 * @version 1.0
 * @date 2019/3/5
 */
@Component
@Slf4j
public class ConsumerListener {

    @Value("${rocketmq.name-server}")
    private String namesrvAddr;

    @Value("${rocketmq.consumer.group}")
    private String consumerGroup;

    @Autowired
    OrderInfoMapper orderInfoMapper;

    @PostConstruct
    public void defaultMQPushConsumer() throws Exception {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerGroup);
        consumer.setNamesrvAddr(namesrvAddr);
        consumer.subscribe("order", "pay");

        // 如果是第一次启动,从队列头部开始消费
        // 如果不是第一次启动,从上次消费的位置继续消费
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        // 开启内部类实现监听
        consumer.registerMessageListener((MessageListenerConcurrently) (list, context) -> {
            try {
                for (MessageExt messageExt : list) {
                    String messageBody = new String(messageExt.getBody(), RemotingHelper.DEFAULT_CHARSET);
                    log.info("消费者受到消息:[Consumer] msgID(" + messageExt.getMsgId() + ") msgBody : " + messageBody);
                 
                }
            } catch (Exception e) {
                e.printStackTrace();
                return ConsumeConcurrentlyStatus.RECONSUME_LATER;
            }
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });


        consumer.subscribe("test222", "pay");
        consumer.registerMessageListener((MessageListenerConcurrently) (list, context) -> {
            try {
                for (MessageExt messageExt : list) {
                    String messageBody = new String(messageExt.getBody(), RemotingHelper.DEFAULT_CHARSET);
                    log.info("消费者受到消息:[Consumer] msgID(" + messageExt.getMsgId() + ") msgBody : " + messageBody);
                }
            } catch (Exception e) {
                e.printStackTrace();
                return ConsumeConcurrentlyStatus.RECONSUME_LATER;
            }
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });


        consumer.start();
        log.info("[Consumer 已启动]");
    }
}

 

就是这么简单的两个文件就可以了。

  • pom

my   mq.version 4.4.0

        
            org.apache.rocketmq
            rocketmq-client
            ${mq.version}
        
        
            org.apache.rocketmq
            rocketmq-common
            ${mq.version}
        

        
            org.apache.rocketmq
            rocketmq-remoting
            ${mq.version}
        

 

代码说完了就说以下我的环境配置。

首先我的mq放在阿里云服务器上

cd  /home/tools/rocketmq-all-4.4.0-bin-release

关闭namesrv服务:

sh bin/mqshutdown namesrv


关闭broker服务 :

sh bin/mqshutdown broker


启动namesrv服务:

nohup sh bin/mqnamesrv & 

启动broker服务:公网ip
nohup sh bin/mqbroker -c conf/broker.conf & 

我的broker.conf  内容有修改,所以上面启动的时候没有指定nameserver地址

在默认的配置下面添加两项

公网ip啊。要不然本地的服务就连接不上mq服务器,没办法发送消费消息

#nameServer地址,分号分割
namesrvAddr = 57.111.156.132:9876
brokerIP1 = 57.111.156.132

还有一个要注意的就是如果你本地连接云服务器的mq,要把本地的防火墙还有云服务的防火墙关了。

 

如果要查看mq的日志,一般都放在/root/logs/rocketmqlogs中,这是我的日志路径,也可能不同用户不同地址

有broker.log、namesrv.log。。。。。。。

你可能感兴趣的:(rocketmq)