栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

rocketMQ的使用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

rocketMQ的使用

首先服务器配置好MQ 其次添加maven依赖,增加mq配置,例如nameserver地址。

创建生产者要素
  1.  NameServer.   //boker的ip+端口。
  2.  生产者组的name名字。
  3. 也可以有其他 键值对。
创建Message要素。
  1. topic   //一个主题。主题会有消费者订阅。
  2. tag     //标签同一个标题下也会有不同的分支。
  3. 要传信息String的code[]。//可以通过json工具转成code【】。
FxTaskCommonMessageDTO fxTaskCommonMessageDTO = new FxTaskCommonMessageDTO();
fxTaskCommonMessageDTO.setType(tag);
fxTaskCommonMessageDTO.setBody(body);
fxTaskCommonMessageDTO.setUniqueId(UUID.randomUUID().toString());
//直接将一个对象转成jsonString的code形式
Message message = new Message(topic, tag,JSON.toJSONBytes(fxTaskCommonMessageDTO));
创建好生产者后,statr()后,不shotdown()是不会停止的。可以将生成的生产者放入一个map中方便随时取用。

用map缓存生产者。

Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.GROUP_ID, producerGroup.getCode());
properties.setProperty(PropertyKeyConst.AccessKey, accessKey);
properties.setProperty(PropertyKeyConst.SecretKey, secretKey);
properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, nameServer);
Producer producer = ONSFactory.createProducer(properties);
producer.start();
producerGroupMap.put(producerGroup.getCode(), producer);

 取生产者。发送消息。

Producer producer = producerGroupMap.get(producerGroup.getCode());
SendResult sendResult = producer.send(message);

创建消费者要素
  1. 消费组的name
  2. NameServer.  ///consumer.setNamesrvAddr("localhost:9876");
  3.  消费者订阅的topic和tag。
  4. 一个消息的处理方式例如:如下处理方式是注册一个监听。
    DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name");
    consumer.setNamesrvAddr("localhost:9876");
    consumer.subscribe("Topic", "zhangkai");
    consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List msgs,
    ConsumeConcurrentlyContext context) {
        System.out.println(fromBytes(msgs.get(0).getBody()));
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
       }
    });
    consumer.start();

    又或者实现    implements MessageListener接口。然后作为消费者的参数bean。

    @RocketMQMessageListener(consumerGroup = MQConstant.GID_NJIA_COMMON, topic = MQConstant.USER_GROWTH_ORDER, selectorExpression = "pay||aftersale||settle")
    //自定义的注解。记录着这个类是一个监听类.他的消费组名,订阅的top,多个tag。
    public class UserOrderGrowthListener implements MessageListener {
        @Override
        public Action consume(Message message, ConsumeContext consumeContext) {
        }
    }
    
    private void createConsumer() {
        Class clazz = AopProxyUtils.ultimateTargetClass(bean);
        RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class);
        consumer.subscribe(annotation.topic(), annotation.selectorExpression(), (MessageListener) bean);
        consumer.start();
    }

    如此就创建好了接收消息的消费者。消费消息只需要对接收消息的body进行操作。

    String msgBody;
    String tag;
    try {
        msgBody = new String(message.getBody());
        tag = message.getTag();
        UserOrderGrowthDTO userOrderGrowthDTO = JSON.parseObject(msgBody, UserOrderGrowthDTO.class);
         //一下对数据进行操作。
    } catch (Exception e) {
        LoggerUtil.error(defaultLogger, e, "订单成长值消息消费失败", userId);
        return Action.ReconsumeLater;
    } finally {
        if (Objects.nonNull(key)) {
           redisCacheManager.releaseLock(key, requestId);
        }
    }

     

完整生产者代码。
@Component
public class DefaultMQProducerTemplate implements InitializingBean {

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

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

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

    private static final Logger logger = LoggerUtil.ROCKET_MQ;

    private static final Map producerGroupMap = Maps.newHashMap();

    private static final Map orderProducerGroupMap = Maps.newHashMap();

    @Override
    public void afterPropertiesSet() {
        for (ProducerGroup producerGroup : ProducerGroup.values()) {
            Properties properties = new Properties();
            properties.setProperty(PropertyKeyConst.GROUP_ID, producerGroup.getCode());
            properties.setProperty(PropertyKeyConst.AccessKey, accessKey);
            properties.setProperty(PropertyKeyConst.SecretKey, secretKey);
            properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, nameServer);
            if (ConsumeMode.CONCURRENTLY == producerGroup.getConsumeMode()) {
                // 创建普通生产者
                Producer producer = ONSFactory.createProducer(properties);
                producer.start();
                producerGroupMap.put(producerGroup.getCode(), producer);
            } else {
                // 创建顺序生产者
                OrderProducer producer = ONSFactory.createOrderProducer(properties);
                producer.start();
                orderProducerGroupMap.put(producerGroup.getCode(), producer);
            }
        }
    }

    private static void validate(final Message message, final Admin admin) {
        Assert.isTrue(Objects.nonNull(admin), "生产者不存在");
        Assert.isTrue(Objects.nonNull(message), "消息不能为空");
    }

    
    public SendResult sendOrder(final Message message, String shardingKey, final ProducerGroup producerGroup) {
        OrderProducer orderProducer = orderProducerGroupMap.get(producerGroup.getCode());
        validate(message, orderProducer);
        try {
            // 同步发送消息,只要不抛异常就是成功
            return orderProducer.send(message, shardingKey);
        } catch (ONSClientException e) {
            // 消息发送失败,需要进行重试处理,可重新发送这条消息或持久化这条数据进行补偿处理
        }
        return null;
    }

    public SendResult send(final Message message, final ProducerGroup producerGroup) {
        return send(message, producerGroup, true);
    }

    public SendResult sendDelayMessage(final Message message, final LocalDateTime startDeliverTime, final ProducerGroup producerGroup) {
        // 设置消息需要被投递的时间
        message.setStartDeliverTime(LocalDateTimeUtil.getMilliByTime(startDeliverTime));
        return send(message, producerGroup, true);
    }

    
    public SendResult send(final Message message, final ProducerGroup producerGroup, final boolean compensate) {
        Producer producer = producerGroupMap.get(producerGroup.getCode());
        validate(message, producer);
        // 需要重试
        int retryTimes = 1;
        int maxRetryTimes = 3;
        String traceId = UUID.randomUUID().toString();
        do {
            try {
                // 同步发送消息,只要不抛异常就是成功
                if (retryTimes == 1) {
                    LoggerUtil.info(logger, "[RocketMQSend]", "start", traceId, producerGroup.getCode(), message.getTopic(), message);
                }
                SendResult sendResult = producer.send(message);
                LoggerUtil.info(logger, "[RocketMQSend]", "success", traceId, producerGroup.getCode(), sendResult.getTopic(), sendResult.getMessageId());
                return sendResult;
            } catch (ONSClientException e) {
                // 消息发送失败,需要进行重试处理,可重新发送这条消息或持久化这条数据进行补偿处理
                LoggerUtil.warn(logger, e, "[RocketMQSend]", "failed", traceId, producerGroup.getCode(), message.getTopic(), "retryTimes=" + retryTimes);
                if (retryTimes >= maxRetryTimes) {
                    if (compensate) {
                        messageCompensation(message, producerGroup);
                        return new SendResult();
                    } else {
                        throw new ONSClientException("超出重试次数");
                    }
                }
                retryTimes++;
            }
        } while (true);
    }

    
    public void sendAsync(final Message message, final ProducerGroup producerGroup) {
        String traceId = UUID.randomUUID().toString();
        LoggerUtil.info(logger, "[RocketMQSendAsync]", "start", traceId, producerGroup.getCode(), message.getTopic(), message);
        Producer producer = producerGroupMap.get(producerGroup.getCode());
        validate(message, producer);
        SendCallback sendCallback = new SendCallback() {
            @Override
            public void onSuccess(final SendResult sendResult) {
                // 消费发送成功
                LoggerUtil.info(logger, "[RocketMQSendAsync]", "success", traceId, sendResult.getTopic(), sendResult.getMessageId());
            }

            @Override
            public void onException(OnExceptionContext context) {
                // 消息发送失败,需要进行重试处理,可重新发送这条消息或持久化这条数据进行补偿处理
                LoggerUtil.warn(logger, context.getException(), "[RocketMQSendAsync]", "failed", traceId, producerGroup.getCode(), context.getTopic(), context.getMessageId());
                messageCompensation(message, producerGroup);
            }
        };
        producer.sendAsync(message, sendCallback);
    }


    
    public void sendOneWay(final Message message, final ProducerGroup producerGroup) {
        Producer producer = producerGroupMap.get(producerGroup.getCode());
        validate(message, producer);
        producer.sendOneway(message);
    }

    
    private void messageCompensation(Message message, ProducerGroup producerGroup) {
        String messageBody = new String(message.getBody());
        MQMessageCompensationDO compensationDO = new MQMessageCompensationDO(producerGroup.getCode(), message.getTopic(), message.getTag(), message.getKey(), messageBody);
        int success = mqMessageCompensationMapper.insertMessage(compensationDO);
        if (success <= 0) {
            LoggerUtil.error(logger, "[RocketMQSend]持久化失败");
            throw new ONSClientException("持久化失败");
        }
    }
}
 

消费者配置
import com.aliyun.openservices.ons.api.Consumer;
import com.aliyun.openservices.ons.api.MessageListener;
import com.aliyun.openservices.ons.api.ONSFactory;
import com.aliyun.openservices.ons.api.PropertyKeyConst;
import com.aliyun.openservices.ons.api.order.MessageOrderListener;
import com.aliyun.openservices.ons.api.order.OrderConsumer;
import com.google.common.collect.Maps;
import org.apache.logging.log4j.Logger;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;

import java.util.Map;
import java.util.Properties;

@Configuration
public class ConsumeConfiguration implements ApplicationContextAware, SmartInitializingSingleton {

    private static final Logger logger = LoggerUtil.COMMON_DEFAULT;

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

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

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

    private ConfigurableApplicationContext applicationContext;

    private Map> consumerGroupMap = Maps.newHashMap();

    private Map> orderConsumerGroupMap = Maps.newHashMap();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = (ConfigurableApplicationContext) applicationContext;
    }

    @Override
    public void afterSingletonsInstantiated() {
        Map beans = this.applicationContext.getBeansWithAnnotation(RocketMQMessageListener.class);
        beans.forEach(this::registerConsumer);
        createConsumer();
    }

    private void registerConsumer(String beanName, Object bean) {
        Class clazz = AopProxyUtils.ultimateTargetClass(bean);
        RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class);
        String consumerGroup = annotation.consumerGroup();
        String topic = annotation.topic();
        Map> groupMap;
        if (ConsumeMode.CONCURRENTLY == annotation.consumeMode()) {
            groupMap = consumerGroupMap;
            if (!MessageListener.class.isAssignableFrom(bean.getClass())) {
                throw new IllegalStateException(clazz + " is not instance of " + MessageListener.class.getName());
            }
        } else {
            groupMap = orderConsumerGroupMap;
            if (!MessageOrderListener.class.isAssignableFrom(bean.getClass())) {
                throw new IllegalStateException(clazz + " is not instance of " + MessageOrderListener.class.getName());
            }
        }
        if (!groupMap.containsKey(consumerGroup)) {
            groupMap.put(consumerGroup, Maps.newHashMap());
        }
        // 指针引用
        Map messageListenerMap = groupMap.get(consumerGroup);

        // 判断该consumerGroup是否有重复topic
        if (messageListenerMap.keySet().contains(topic)) {
            throw new IllegalStateException("[" + topic + "]" + " topic conflicts with existing," + bean.toString());
        }
        messageListenerMap.put(topic, bean);
        LoggerUtil.info(logger, "RegisterRocketMQ", beanName, annotation);
    }

    private void createConsumer() {
        // 普通消息订阅
        for (Map.Entry> entry : consumerGroupMap.entrySet()) {
            String consumerGroup = entry.getKey();
            Map messageListenerMap = entry.getValue();
            Properties consumerProperties = createProperties(consumerGroup);
            Consumer consumer = ONSFactory.createConsumer(consumerProperties);
            // 订阅多个topic
            for (Map.Entry topicEntry : messageListenerMap.entrySet()) {
                Object bean = topicEntry.getValue();
                Class clazz = AopProxyUtils.ultimateTargetClass(bean);
                RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class);
                consumer.subscribe(annotation.topic(), annotation.selectorExpression(), (MessageListener) bean);
            }
            consumer.start();
            LoggerUtil.info(logger, "Consumer start success.", consumerGroup);
        }

        // 顺序消息订阅
        for (Map.Entry> entry : orderConsumerGroupMap.entrySet()) {
            String consumerGroup = entry.getKey();
            Map messageListenerMap = entry.getValue();
            Properties consumerProperties = createProperties(consumerGroup);
            OrderConsumer consumer = ONSFactory.createOrderedConsumer(consumerProperties);
            // 订阅多个topic
            for (Map.Entry topicEntry : messageListenerMap.entrySet()) {
                Object bean = topicEntry.getValue();
                Class clazz = AopProxyUtils.ultimateTargetClass(bean);
                RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class);
                consumer.subscribe(annotation.topic(), annotation.selectorExpression(), (MessageOrderListener) bean);
            }
            consumer.start();
            LoggerUtil.info(logger, "Order Consumer start success.", consumerGroup);
        }
    }

    private Properties createProperties(String consumerGroup) {
        Properties consumerProperties = new Properties();
        consumerProperties.setProperty(PropertyKeyConst.GROUP_ID, consumerGroup);
        consumerProperties.setProperty(PropertyKeyConst.AccessKey, accessKey);
        consumerProperties.setProperty(PropertyKeyConst.SecretKey, secretKey);
        consumerProperties.setProperty(PropertyKeyConst.NAMESRV_ADDR, nameServer);
        return consumerProperties;
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1028968.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号