阿里RoceketMQ使用

一、配置文件

#該應用是否啓用生產者
rocketmq:
  producer:
    isOnOff: on
    #發送同一類消息的設置爲同一個group,保證唯一,默認不需要設置,rocketmq會使用ip@pid(pid代表jvm名字)作爲唯一標示
    groupName: ${spring.application.name}
    #mq的nameserver地址
    namesrvAddr: 127.0.0.1:9876
    #消息最大長度 默認1024*4(4M)
    maxMessageSize: 4096
    #發送消息超時時間,默認3000
    sendMsgTimeout: 3000
    #發送消息失敗重試次數,默認2
    retryTimesWhenSendFailed: 2

  ###consumer
  ##該應用是否啓用消費者
  consumer:
    isOnOff: on
    groupName: ${spring.application.name}
    #mq的nameserver地址
    namesrvAddr: 127.0.0.1:9876
    #該消費者訂閱的主題和tags("*"號表示訂閱該主題下所有的tags),格式:topic~tag1||tag2||tag3;topic2~*;
    topics: futaotopic~*;
    consumeThreadMin: 20
    consumeThreadMax: 64
    #設置一次消費消息的條數,默認爲1條
    consumeMessageBatchMaxSize: 1
#失敗重試次數
reConsumerTimes: 3

二、生產者配置

/**
 * @program: wx-job
 * @description: RoceketMQ
 * @author: pengyd
 * @create: 2019-10-10 14:44
 **/
@Configuration
@Slf4j
public class MQProducerConfig {

    @Value("${rocketmq.producer.groupName}")
    private String producerGroupName;

    @Value("${rocketmq.producer.namesrvAddr}")
    private String producerNameSrvAddr;

    @Value("${rocketmq.producer.maxMessageSize}")
    private int maxMessageSize;

    @Value("${rocketmq.producer.sendMsgTimeout}")
    private int sendMsgTimeout;

    @Value("${rocketmq.producer.retryTimesWhenSendFailed}")
    private int retryTimesWhenSendFailed;


    @Bean
    public DefaultMQProducer producer(){
        if (this.producerGroupName.isEmpty()) {
            throw new RuntimeException("producerGroupName  isEmpty ");
        }
        if (this.producerNameSrvAddr.isEmpty()) {
            throw  new RuntimeException("producerNameSrvAddr  isEmpty ");
        }
        DefaultMQProducer defaultMQProducer = new DefaultMQProducer(producerGroupName);
        defaultMQProducer.setNamesrvAddr(producerNameSrvAddr);
        defaultMQProducer.setMaxMessageSize(maxMessageSize);
        defaultMQProducer.setSendMsgTimeout(sendMsgTimeout);
        defaultMQProducer.setVipChannelEnabled(false);
        //消息發送到mq服務器失敗重試次數
        defaultMQProducer.setRetryTimesWhenSendFailed(retryTimesWhenSendFailed);
        try {
            defaultMQProducer.start();
            log.info("rocketMq Producer start success; nameServer:{},producerGroupName:{}", producerNameSrvAddr, producerGroupName);
        } catch (Exception e) {
            log.error("rocketMq Producer start fail;{}", e.getMessage(), e);
        }
        return defaultMQProducer;
    }


}

 三、消費者配置

/**
 * @program: wx-job
 * @description: RoceketMQ
 * @author: pengyd
 * @create: 2019-10-10 14:44
 **/
@Configuration
@Slf4j
public class MQConsumerConfig {

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

    @Value("${rocketmq.consumer.groupName}")
    private String consumerGroupName;

    @Value("${rocketmq.consumer.consumeThreadMin}")
    private int consumeThreadMin;

    @Value("${rocketmq.consumer.consumeThreadMax}")
    private int consumeThreadMax;

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

    @Value("${rocketmq.consumer.consumeMessageBatchMaxSize}")
    private int consumeMessageBatchMaxSize;

    private static final String TOPIC = "test";

    private static final String TAG = "test";


    @Bean
    public DefaultMQPushConsumer consumer() {
        if (this.consumerGroupName.isEmpty()) {
            throw new RuntimeException("consumerGroupName  isEmpty ");
        }
        if (this.consumerNamesrvAddr.isEmpty()) {
            throw new RuntimeException("consumerNamesrvAddr  isEmpty ");
        }
        if (this.topics.isEmpty()) {
            throw new RuntimeException("topics  isEmpty ");
        }
        try {
            //DefaultMQPushConsumer DefaultMQPullConsumer
            DefaultMQPushConsumer defaultMQPushConsumer = new DefaultMQPushConsumer(consumerGroupName);
            defaultMQPushConsumer.setNamesrvAddr(consumerNamesrvAddr);
            defaultMQPushConsumer.setConsumeThreadMin(consumeThreadMin);
            defaultMQPushConsumer.setVipChannelEnabled(false);
//            defaultMQPushConsumer.createTopic();
            defaultMQPushConsumer.setConsumeThreadMax(consumeThreadMax);
            //消費模式 集羣還是廣播,默認爲集羣(自動負載均衡)
            //廣播消費: 消息會發給Consume Group中的每一個消費者進行消費,如果設置爲廣播消息會導致NOT_ONLINE異常,https://github.com/apache/rocketmq/issues/296
            defaultMQPushConsumer.setMessageModel(MessageModel.CLUSTERING);
            //設置Consumer第一次啓動是從隊列頭部開始消費還是隊列尾部開始消費
            //如果非第一次啓動,那麼按照上次消費的位置繼續消費
            defaultMQPushConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
            //設置一次消費消息的條數,默認爲1條
            defaultMQPushConsumer.setConsumeMessageBatchMaxSize(consumeMessageBatchMaxSize);
            //訂閱topic
            defaultMQPushConsumer.subscribe(TOPIC, TAG);
            //defaultMQPushConsumer.registerMessageListener(mqMessageListenerProcessor)
            defaultMQPushConsumer.registerMessageListener(new MessageListenerConcurrently() {
                @Override
                public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                    MessageExt msg = list.get(0);
                    System.out.println("接收到的消息爲:" + new String(msg.getBody(), StandardCharsets.UTF_8));
                    if (msg.getTopic().equals(TOPIC) && msg.getTags().equals(TAG)) {
                        //判斷該消息是否重複消費(RocketMQ不保證消息不重複,如果你的業務需要保證嚴格的不重複消息,需要你自己在業務端去重)
                        //獲取該消息重試次數
                        if (msg.getReconsumeTimes() >= 3) {
                            //消息已經重試了3次,如果不需要再次消費,則返回成功
                            //TODO("如果重試了三次還是失敗則執行對於失敗的業務邏輯")
                            log.error("消息重試消費失敗:{}", msg);
                            System.out.println(ConsumeConcurrentlyStatus.CONSUME_SUCCESS);
                        } else {
                            //如果失敗重試次數還沒到三次則繼續重試
                            System.out.println(ConsumeConcurrentlyStatus.RECONSUME_LATER);
                        }
                        //TODO("開始正常的業務邏輯")
                        System.out.println("開始正常的業務邏輯:" + new String(msg.getBody(), StandardCharsets.UTF_8));
                    }
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                }
            });
            defaultMQPushConsumer.start();
            log.info("rocketMq Consumer start success; namesrvAddr:{},groupName:{},topics:{}", consumerNamesrvAddr, consumerGroupName, topics);
            return defaultMQPushConsumer;
        } catch (Exception e) {
            log.error("rocketMq Consumer start fail;{}", e.getMessage(), e);
            return new DefaultMQPushConsumer();
        }
    }

 四、簡單使用

/**
 * FileName: MQController
 * Author: pengyd
 * Date: 2019/12/26
 * function:
 */
@RequestMapping("/mq")
@Controller
public class MQController {
    private static Logger logger = LoggerFactory.getLogger(MQController.class);

    @Resource
    private DefaultMQProducer producer;


    @RequestMapping("/mqSend")
    @ResponseBody
    public String mqSend() {
        logger.info("開始發送rocketmq");
        //組裝消息內容
        Message message = new Message("test",
                "test",
                (new Date().toString() + "這是測試mq").getBytes());
        try {
            producer.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "success";
    }

}

五、over

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章