• 阿里云RocketMQ的消费者简单实现


    业务场景之类的请看另一篇生产者的实现;

    package com.ttt.eee;
    
    import com.aliyun.openservices.ons.api.Action;
    import com.aliyun.openservices.ons.api.Consumer;
    import com.aliyun.openservices.ons.api.ONSFactory;
    import com.aliyun.openservices.ons.api.PropertyKeyConst;
    
    import java.nio.charset.Charset;
    import java.util.Properties;
    import java.util.Scanner;
    
    public class MQTestConsumer {
    
        public static void main(String[] args) {
            Properties properties = new Properties();
            // 您在控制台创建的 Group ID,其实就是网上说的groupName
            properties.put(PropertyKeyConst.GROUP_ID, "eee");
            // AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建
            properties.put(PropertyKeyConst.AccessKey, "sss");
            // SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建
            properties.put(PropertyKeyConst.SecretKey, "bbb");
            // 设置 TCP 接入域名,到控制台的实例基本信息中查看
            properties.put(PropertyKeyConst.NAMESRV_ADDR,
                           "http://ttt.mq-internet-access.mq-internet.aliyuncs.com:80");
            // 集群订阅方式 (默认)
            // properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.CLUSTERING);
            // 广播订阅方式
            // properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.BROADCASTING);
            Consumer consumer = ONSFactory.createConsumer(properties);
            // TODO tag如果是*表示订阅所有的tag消息,注意在producer里是叫tags,这里却叫subExpresion
            // *表示订阅所有Tag,TagA||TagB表示订阅 TagA和TagB
            consumer.subscribe("xxx-change", "*", (message, context) -> {
                // context的用处暂时不知道
                System.out.println("Receive: " + message);
                System.out.println("具体消息为:" + new String(message.getBody(), Charset.forName("UTF-8")));
                // 正常消费返回这个,如果消费消息后业务处理出现问题一般返回:Action.ReconsumeLater表示这条消息晚点处理;
                return Action.CommitMessage;
            });
            //订阅另外一个 Topic
            // TODO 一个Consumer可以订阅多个topic ??,不过既然是官网的例子应该是可以的
            /*consumer.subscribe("TopicTestMQ-Other", "*", new MessageListener() { //订阅全部 Tag
                public Action consume(Message message, ConsumeContext context) {
                    System.out.println("Receive: " + message);
                    return Action.CommitMessage;
                }
            });*/
            consumer.start();
            System.out.println("Consumer Started");
    
            var scanner = new Scanner(System.in);
            scanner.next();
    
            consumer.shutdown();
            System.out.println("closed producer conn.");
        }
    
    }

    集合到Spring里是:

    @Bean(initMethod = "start", destroyMethod = "shutdown")
        public ConsumerBean xxxNotify(XxxNotifyListener xxxNotifyListener) {
            return this.getConsumer(gid, topic, xxxNotifyListener);
        }
    
        private ConsumerBean getConsumer(String gid, String topic, MessageListener messageListener) {
            Properties properties = new Properties();
            properties.setProperty("addr", addr);
            properties.setProperty("AccessKey", accessKey);
            properties.setProperty("SecretKey", secretKey);
            properties.setProperty("GROUP_ID", gid);
    
            Map<Subscription, MessageListener> subscriptionTable = new HashMap<>();
            Subscription subscription = new Subscription();
            subscription.setTopic(topic);
            // 这里还可以设置subExpression来描述tag(重要:这里有个很大的坑,就是我这里设置了tag是tagA
    //,但是producer发送的是tagB的,尽管这里确实不会到consume方法里进行业务消费,但这个消息在消息队列里也是没有了,它不会将tagB的消息返回到mq里待消费
    // 上面的总结可能不准确,这里当初是两个消费者用的一个groupId导致的,这个有机会再测试一下;
    // 经过测试如果在创建Consumer时就指定 tags,那么这个consumer只消费这个tags的消息,非此tags的消息是不会消费掉的,其他group是可以消费那些消息的;
    // 而对于一个topic里有两个消费组,且aGroup消费TagA,bGroup消费TagB,那么必须在创建consumer时就指定tags,而不能通过consume方法里面判断tag,然后
    // 不符合要求的则
    return Action.ReconsumeLater,这样是有问题的,比如bGroup消费了这个消息,发现不是自己的tag准备return ...Later,此时aGroup也
    // 消费了这个消息,发现是自己的tag,然后做了业务处理,这个时候bGroup就返回了...Later,那么这条消息就可能被aGroup重复消费;

    subscriptionTable.put(subscription, messageListener); ConsumerBean consumer = new ConsumerBean(); consumer.setProperties(properties); consumer.setSubscriptionTable(subscriptionTable); return consumer; }

    MessageListener里是用来实现消费这个消息后的具体业务逻辑的;

  • 相关阅读:
    大二下第十三周学习笔记
    对C++多态的一次小分析
    vs2015中用汇编(转)
    挖个坑
    ListCtrl
    获得进程完整路径的第二种方法
    The Meeting Place Cannot Be Changed(二分+eps精度)
    CodeForces 494A
    Anya and Ghosts CodeForces
    寒假给自己立个flag
  • 原文地址:https://www.cnblogs.com/silentdoer/p/11101736.html
Copyright © 2020-2023  润新知