RocketMQ学习

1.什么是MQ,为什么要用MQ

MQ:MessageQueue,消息队列。 队列,是一种FIFO 先进先出的数据结构。消息由生产者发送

到MQ 进行排队,然后按原来的顺序交由消息的消费者进行处理。QQ和微信就是典型的MQ。

MQ的作用主要有以下三个方面:

异步

例子:快递员发快递,直接到客户家效率会很低。引入菜鸟驿站后,快递员只需要把快递放到菜鸟

驿站,就可以继续发其他快递去了。客户再按自己的时间安排去菜鸟驿站取快递。

作用:异步能提高系统的响应速度、吞吐量。

编辑

编辑

解耦

例子:《Thinking in JAVA》很经典,但是都是英文,我们看不懂,所以需要编辑社,将文章翻译

成其他语言,这样就可以完成英语与其他语言的交流。

作用:

  • 服务之间进行解耦,才可以减少服务之间的影响。提高系统整体的稳定性以及可扩展性。

  • 另外,解耦后可以实现数据分发。生产者发送一个消息后,可以由一个或者多个消费者进行消费,并且消费者的增加或者减少对生产者没有影响。

编辑

削峰

例子:长江每年都会涨水,但是下游出水口的速度是基本稳定的,所以会涨水。引入三峡大坝后,

可以把水储存起来,下游慢慢排水。

作用:以稳定的系统资源应对突发的流量冲击

编辑

编辑

2.MQ的优缺点

上面MQ的所用也就是使用MQ的优点。 但是引入MQ也是有他的缺点的:

  • 系统可用性降低

系统引入的外部依赖增多,系统的稳定性就会变差。一旦MQ宕机,对业务会产生影响。这就需要考虑 如何保证MQ的高可用。

  • 系统复杂度提高

引入MQ后系统的复杂度会大大提高。以前服务之间可以进行同步的服务调用,引入MQ后,会变为异步调用,数据的链路就会变得更复杂。并且还会带来其他一些问题。比如:如何保证消费不会丢失?不会被重复调用?怎么保证消息的顺序性等问题。

  • 消息一致性问题

A系统处理完业务,通过MQ发送消息给B、C系统进行后续的业务处理。如果B系统处理成功,C系统处理失败怎么办?这就需要考虑如何保证消息数据处理的一致性。

3.几大产品MQ的特点比较

编辑

4.RockerMQ的几种发送模式

--------------------------------------------------------消费者--------------------------------------------------

publicclassConsumer {

    publicstaticvoidmain(String[] args)throws InterruptedException, MQClientException {

        /*
         * Instantiate with specified consumer group name.
         */DefaultMQPushConsumerconsumer=newDefaultMQPushConsumer("please_rename_unique_group_name_4");

        /*
         * Specify name server addresses.
         * <p/>
         *
         * Alternatively, you may specify name server addresses via exporting environmental variable: NAMESRV_ADDR
         * <pre>
         * {@code
         * consumer.setNamesrvAddr("name-server1-ip:9876;name-server2-ip:9876");
         * }
         * </pre>
         */
        consumer.setNamesrvAddr("192.168.232.128:9876");
        /*
         * Specify where to start in case the specified consumer group is a brand new one.
         */
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);

        /*
         * Subscribe one more more topics to consume.
         */
        consumer.subscribe("TopicTest", "*");

        /*
         *  Register callback to execute on arrival of messages fetched from brokers.
         */
        consumer.registerMessageListener(newMessageListenerConcurrently() {

            @Overridepublic ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                ConsumeConcurrentlyContext context) {
                System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });

        /*
         *  Launch the consumer instance.
         */
        consumer.start();

        System.out.printf("Consumer Started.%n");
    }
}

---------------------------------------------------生产者----------------------------------------------------

//简单样例:同步发送消息publicclassProducer {
    publicstaticvoidmain(String[] args)throws MQClientException, InterruptedException {

        DefaultMQProducerproducer=newDefaultMQProducer("ProducerGroupName");
        //nameserver有两种方式指定//1.setNamesrvAddr//producer.setNamesrvAddr("192.168.232.128:9876");//2.配置环境变量
        producer.start();

        for (inti=0; i < 20; i++)
            try {
                {
                    Messagemsg=newMessage("TopicTest",
                        "TagA",
                        "OrderID188",
                        "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
                    //同步传递消息,消息会发给集群中的一个Broker节点。//                    SendResult sendResult = producer.send(msg);//                    System.out.printf("%s%n", sendResult);
                    producer.sendOneway(msg);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        producer.shutdown();
    }
}

单向发送,同步发送,异步发送

单向发送:生产者把消息往mq那里一发,后续就不管了,这种效率最高,sendOneway 没有返回值

同步发送:你发的消息,有没有成功,mq是知道的,必须等到发送完毕且结果返回

代码改成 有返回值
SendResult sendResult = producer.send(msg); System.out.printf("%s%n", sendResult);

异步发送:producer在发送完之后,就不管了,去做自己的事情,但是它会给MQ一个回调函数

主要代码
producer.send(msg, new SendCallback() { @Override public void onSuccess(SendResult sendResult) { countDownLatch.countDown(); System.out.printf("%-10d OK %s %n", index, sendResult.getMsgId()); }
注意还使用了countdownlatch 为了保证全部消息发送完毕后 ,再停止producer服务
//简单样例:异步发送消息publicclassAsyncProducer {
    publicstaticvoidmain(
        String[] args)throws MQClientException, InterruptedException, UnsupportedEncodingException {
        //实例化一个实例DefaultMQProducerproducer=newDefaultMQProducer("Jodie_Daily_test");
//        producer.setNamesrvAddr("192.168.232.128:9876");
        producer.start();
        producer.setRetryTimesWhenSendAsyncFailed(0);

        intmessageCount=100;
        //由于是异步发送,这里引入一个countDownLatch,保证所有Producer发送消息的回调方法都执行完了再停止Producer服务。finalCountDownLatchcountDownLatch=newCountDownLatch(messageCount);
        for (inti=0; i < messageCount; i++) {
            try {
                finalintindex= i;
                Messagemsg=newMessage("TopicTest",
                    "TagA",
                    "OrderID188",
                    "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
                producer.send(msg, newSendCallback() {
                    @OverridepublicvoidonSuccess(SendResult sendResult) {
                        countDownLatch.countDown();
                        System.out.printf("%-10d OK %s %n", index, sendResult.getMsgId());
                    }

                    @OverridepublicvoidonException(Throwable e) {
                        countDownLatch.countDown();
                        System.out.printf("%-10d Exception %s %n", index, e);
                        e.printStackTrace();
                    }
                });
                System.out.println("消息发送完成");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        countDownLatch.await(5, TimeUnit.SECONDS);
        producer.shutdown();
    }
}

5.rocketMQ的两种接收模式

推模式,拉模式

拉模式:消费者主动去broker上拉去消息

publicclassPullConsumer {
    privatestaticfinal Map<MessageQueue, Long> OFFSE_TABLE = newHashMap<MessageQueue, Long>();

    publicstaticvoidmain(String[] args)throws MQClientException {
        DefaultMQPullConsumerconsumer=newDefaultMQPullConsumer("please_rename_unique_group_name_5");
        consumer.setNamesrvAddr("192.168.232.128:9876");
        consumer.start();

        Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues("TopicTest");
        for (MessageQueue mq : mqs) {
            System.out.printf("Consume from the queue: %s%n", mq);
            SINGLE_MQ:
            while (true) {
                try {
                    PullResultpullResult=//参数2:offset 偏移量//参数3:每一次最多拿32条消息
                        consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
                    System.out.printf("%s%n", pullResult);
                    putMessageQueueOffset(mq, pullResult.getNextBeginOffset());
                    switch (pullResult.getPullStatus()) {
                        case FOUND:
                            break;
                        case NO_MATCHED_MSG:
                            break;
                        case NO_NEW_MSG:
                            break SINGLE_MQ;
                        case OFFSET_ILLEGAL:
                            break;
                        default:
                            break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        consumer.shutdown();
    }

    privatestaticlonggetMessageQueueOffset(MessageQueue mq) {
        Longoffset= OFFSE_TABLE.get(mq);
        if (offset != null)
            return offset;

        return0;
    }

    privatestaticvoidputMessageQueueOffset(MessageQueue mq, long offset) {
        OFFSE_TABLE.put(mq, offset);
    }

}

傻瓜模式,不需要自己去设置offset

publicclassLitePullConsumerAssign {

    publicstaticvolatilebooleanrunning=true;

    publicstaticvoidmain(String[] args)throws Exception {
        DefaultLitePullConsumerlitePullConsumer=newDefaultLitePullConsumer("please_rename_unique_group_name");
        litePullConsumer.setAutoCommit(false);
        litePullConsumer.start();
        Collection<MessageQueue> mqSet = litePullConsumer.fetchMessageQueues("TopicTest");
        List<MessageQueue> list = newArrayList<>(mqSet);
        List<MessageQueue> assignList = newArrayList<>();
        for (inti=0; i < list.size() / 2; i++) {
            assignList.add(list.get(i));
        }
        litePullConsumer.assign(assignList);
        litePullConsumer.seek(assignList.get(0), 10);
        try {
            while (running) {
                List<MessageExt> messageExts = litePullConsumer.poll();
                System.out.printf("%s %n", messageExts);
                litePullConsumer.commitSync();
            }
        } finally {
            litePullConsumer.shutdown();
        }

    }
}

这个可以定制自己的消费的起点

DefaultLitePullConsumer

publicclassLitePullConsumerSubscribe {

    publicstaticvolatilebooleanrunning=true;

    publicstaticvoidmain(String[] args)throws Exception {
        DefaultLitePullConsumerlitePullConsumer=newDefaultLitePullConsumer("lite_pull_consumer_test");
        litePullConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        litePullConsumer.subscribe("TopicTest", "*");
        litePullConsumer.start();
        try {
            while (running) {
                List<MessageExt> messageExts = litePullConsumer.poll();
                System.out.printf("%s%n", messageExts);
            }
        } finally {
            litePullConsumer.shutdown();
        }
    }
}

推模式:由broker收到消息后,主动推送给消费者

主要代码
consumer.registerMessageListener(new MessageListenerConcurrently() { @Override public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) { System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } });
首先listener监听
然后执行里面的方法,返回他的状态ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

publicclassPushConsumer {

    publicstaticvoidmain(String[] args)throws InterruptedException, MQClientException {
        DefaultMQPushConsumerconsumer=newDefaultMQPushConsumer("CID_JODIE_1");
//        consumer.setNamesrvAddr("192.168.232.128:9876");
        consumer.subscribe("TopicTest", "*");
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        //wrong time format 2017_0422_221800
        consumer.setConsumeTimestamp("20181109221800");
        consumer.registerMessageListener(newMessageListenerConcurrently() {

            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        consumer.start();
        System.out.printf("Consumer Started.%n");
    }
}
  1. 消息顺序

主要使用监听器newMessageListenerOrderly 来保证先从一个一个队列拿,就能保证局部有序

局部有序,全局不一定有序

核心代码
SendResult sendResult = producer.send(msg, new MessageQueueSelector() { @Override public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) { Integer id = (Integer) arg; int index = id % mqs.size(); return mqs.get(index); } }, orderId);
要保证同一个orderID 都放在同一个队列里面去
publicclassProducer {
    publicstaticvoidmain(String[] args)throws UnsupportedEncodingException {
        try {
           DefaultMQProducerproducer=newDefaultMQProducer("please_rename_unique_group_name");
//         producer.setNamesrvAddr("192.168.232.128:9876");
           producer.start();

            for (inti=0; i < 10; i++) {
              intorderId= i;

              for(intj=0 ; j <= 5 ; j ++){
                Messagemsg=new Message("OrderTopicTest", "order_"+orderId, "KEY" + orderId,
                ("order_"+orderId+" step " + j).getBytes(RemotingHelper.DEFAULT_CHARSET));
                SendResultsendResult= producer.send(msg, newMessageQueueSelector() {
                @Override
                public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                          Integerid= (Integer) arg;
                          intindex= id % mqs.size();
                          return mqs.get(index);
                      }
                  }, orderId);

                  System.out.printf("%s%n", sendResult);
                }
            }

            producer.shutdown();
        } catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

--------------------------------------------消费者--------------------------------------

核心代码
consumer.registerMessageListener(new MessageListenerOrderly() { @Override public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) { context.setAutoCommit(true); for(MessageExt msg:msgs){ System.out.println("收到消息内容 "+new String(msg.getBody())); } return ConsumeOrderlyStatus.SUCCESS; } });
new MessageListenerOrderly()这个是会帮我们从同一个消息队列里面拿消息,
MessageListenerConcurrently是做不到这点的
publicclassConsumer {

    publicstaticvoidmain(String[] args)throws MQClientException {
        DefaultMQPushConsumerconsumer=newDefaultMQPushConsumer("please_rename_unique_group_name_3");
        consumer.setNamesrvAddr("192.168.232.128:9876");
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);

        consumer.subscribe("OrderTopicTest", "*");

        consumer.registerMessageListener(newMessageListenerOrderly() {
            @Overridepublic ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {
                context.setAutoCommit(true);
                for(MessageExt msg:msgs){
                    System.out.println("收到消息内容 "+newString(msg.getBody()));
                }
                return ConsumeOrderlyStatus.SUCCESS;
            }
        });

//        这样是保证不了最终消费顺序的。
//        consumer.registerMessageListener(new MessageListenerConcurrently() {
//            @Override
//            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
//                for(MessageExt msg:msgs){
//                    System.out.println("收到消息内容 "+new String(msg.getBody()));//                }
//                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;//            }
//        });

        consumer.start();
        System.out.printf("Consumer Started.%n");
    }

}

7.广播消息

会收到所有的producer的消息

核心代码
consumer.setMessageModel(MessageModel.BROADCASTING);
在所有的producer共享
publicclassPushConsumer {

    publicstaticvoidmain(String[] args)throws InterruptedException, MQClientException {
        DefaultMQPushConsumerconsumer=newDefaultMQPushConsumer("please_rename_unique_group_name_1");

        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);

        consumer.setMessageModel(MessageModel.BROADCASTING);

        consumer.subscribe("TopicTest", "*");

        consumer.registerMessageListener(newMessageListenerConcurrently() {

            @Overridepublic ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                ConsumeConcurrentlyContext context) {
                System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });

        consumer.start();
        System.out.printf("Broadcast Consumer Started.%n");
    }
}

8.延迟消息

核心代码
//messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2 hmsg.setDelayTimeLevel(3);
publicclassProducer {
    publicstaticvoidmain(String[] args)throws MQClientException, InterruptedException {

        /*
         * Instantiate with a producer group name.
         */DefaultMQProducerproducer=newDefaultMQProducer("please_rename_unique_group_name");

        /*
         * Specify name server addresses.
         * <p/>
         *
         * Alternatively, you may specify name server addresses via exporting environmental variable: NAMESRV_ADDR
         * <pre>
         * {@code
         * producer.setNamesrvAddr("name-server1-ip:9876;name-server2-ip:9876");
         * }
         * </pre>
         */
        producer.setNamesrvAddr("192.168.232.128:9876");
        /*
         * Launch the instance.
         */
        producer.start();

        for (inti=0; i < 2; i++) {
            try {

                /*
                 * Create a message instance, specifying topic, tag and message body.
                 */Messagemsg=newMessage("TopicTest"/* Topic */,
                    "TagA"/* Tag */,
                    ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
                );
                //messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
                msg.setDelayTimeLevel(3);
                /*
                 * Call send message to deliver message to one of brokers.
                 */SendResultsendResult= producer.send(msg);

                System.out.printf("%s%n", sendResult);
            } catch (Exception e) {
                e.printStackTrace();
                Thread.sleep(1000);
            }
        }

        /*
         * Shut down once the producer instance is not longer in use.
         */
        producer.shutdown();
    }
}
  1. 批量消息

批量消息有限制,不能超过1兆,必须是相同的topic,相同的waitStoreMsgOk,且不能是延迟消息,事务消息

将多条消息合成一个批量消息,一次性发送出去,减少网络IO

核心代码 List<Message> messages = new ArrayList<>(); messages.add(new Message(topic, "Tag", "OrderID001", "Hello world 0".getBytes())); messages.add(new Message(topic, "Tag", "OrderID002", "Hello world 1".getBytes())); messages.add(new Message(topic, "Tag", "OrderID003", "Hello world 2".getBytes())); producer.send(messages);
publicclassSimpleBatchProducer {

    publicstaticvoidmain(String[] args)throws Exception {
        DefaultMQProducerproducer=newDefaultMQProducer("BatchProducerGroupName");
        producer.start();

        //If you just send messages of no more than 1MiB at a time, it is easy to use batch//Messages of the same batch should have: same topic, same waitStoreMsgOK and no schedule supportStringtopic="BatchTest";
        List<Message> messages = newArrayList<>();
        messages.add(newMessage(topic, "Tag", "OrderID001", "Hello world 0".getBytes()));
        messages.add(newMessage(topic, "Tag", "OrderID002", "Hello world 1".getBytes()));
        messages.add(newMessage(topic, "Tag", "OrderID003", "Hello world 2".getBytes()));

        producer.send(messages);
        producer.shutdown();
    }
}

10.过滤消息

好处:在发送之前进行过滤,只发送对方想要的消息,减少IO

------------------------------------------------------消费者------------------------------------------------

consumer.subscribe("TagFilterTest", "TagA || TagC");
publicclassTagFilterConsumer {

    publicstaticvoidmain(String[] args)throws InterruptedException, MQClientException, IOException {

        DefaultMQPushConsumerconsumer=newDefaultMQPushConsumer("please_rename_unique_group_name");

        consumer.subscribe("TagFilterTest", "TagA || TagC");

        consumer.registerMessageListener(newMessageListenerConcurrently() {

            @Overridepublic ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                ConsumeConcurrentlyContext context) {
                System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });

        consumer.start();

        System.out.printf("Consumer Started.%n");
    }
}

------------------------------------------------------生产者------------------------------------------------

publicclassTagFilterProducer {

    publicstaticvoidmain(String[] args)throws Exception {

        DefaultMQProducerproducer=newDefaultMQProducer("please_rename_unique_group_name");
        producer.start();

        String[] tags = newString[] {"TagA", "TagB", "TagC"};

        for (inti=0; i < 15; i++) {
            Messagemsg=newMessage("TagFilterTest",
                tags[i % tags.length],
                "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));

            SendResultsendResult= producer.send(msg);
            System.out.printf("%s%n", sendResult);
        }

        producer.shutdown();
    }
}

SQL过滤

consumer.subscribe("SqlFilterTest", MessageSelector.bySql("(TAGS is not null and TAGS in ('TagA', 'TagB'))" + "and (a is not null and a between 0 and 3)"));
可以像写SQL语句一样去过滤
publicclassSqlFilterConsumer {

    publicstaticvoidmain(String[] args)throws Exception {

        DefaultMQPushConsumerconsumer=newDefaultMQPushConsumer("please_rename_unique_group_name");

        // Don't forget to set enablePropertyFilter=true in broker
        consumer.subscribe("SqlFilterTest",
            MessageSelector.bySql("(TAGS is not null and TAGS in ('TagA', 'TagB'))" +
                "and (a is not null and a between 0 and 3)"));

        consumer.registerMessageListener(newMessageListenerConcurrently() {

            @Overridepublic ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                ConsumeConcurrentlyContext context) {
                System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });

        consumer.start();
        System.out.printf("Consumer Started.%n");
    }
}

11.事务消息

事务消息只跟发送者有关,和消费者没太大关系

TransactionListener transactionListener = new TransactionListenerImpl(); 这个类里面做的事情 String tags = msg.getTags(); if(StringUtils.contains(tags,"TagA")){ return LocalTransactionState.COMMIT_MESSAGE; }else if(StringUtils.contains(tags,"TagB")){ return LocalTransactionState.ROLLBACK_MESSAGE; }else{ return LocalTransactionState.UNKNOW; } TransactionMQProducer producer = new TransactionMQProducer("please_rename_unique_group_name");
SendResult sendResult = producer.sendMessageInTransaction(msg, null);
publicclassTransactionProducer {
    publicstaticvoidmain(String[] args)throws MQClientException, InterruptedException {
        TransactionListenertransactionListener=newTransactionListenerImpl();
        TransactionMQProducerproducer=newTransactionMQProducer("please_rename_unique_group_name");
//        producer.setNamesrvAddr("127.0.0.1:9876");ExecutorServiceexecutorService=newThreadPoolExecutor(2, 5, 100, TimeUnit.SECONDS, newArrayBlockingQueue<Runnable>(2000), newThreadFactory() {
            @Overridepublic Thread newThread(Runnable r) {
                Threadthread=newThread(r);
                thread.setName("client-transaction-msg-check-thread");
                return thread;
            }
        });

        producer.setExecutorService(executorService);
        producer.setTransactionListener(transactionListener);
        producer.start();

        String[] tags = newString[] {"TagA", "TagB", "TagC", "TagD", "TagE"};
        for (inti=0; i < 10; i++) {
            try {
                Messagemsg=newMessage("TopicTest", tags[i % tags.length], "KEY" + i,
                        ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
                SendResultsendResult= producer.sendMessageInTransaction(msg, null);
                System.out.printf("%s%n", sendResult);

                Thread.sleep(10);
            } catch (MQClientException | UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        for (inti=0; i < 100000; i++) {
            Thread.sleep(1000);
        }
        producer.shutdown();
    }
}
publicclassTransactionListenerImplimplementsTransactionListener {
    privateAtomicIntegertransactionIndex=newAtomicInteger(0);

    private ConcurrentHashMap<String, Integer> localTrans = newConcurrentHashMap<>();

    @Overridepublic LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
//        int value = transactionIndex.getAndIncrement();//        int status = value % 3;//        localTrans.put(msg.getTransactionId(), status);//        return LocalTransactionState.UNKNOW;Stringtags= msg.getTags();
        if(StringUtils.contains(tags,"TagA")){
            return LocalTransactionState.COMMIT_MESSAGE;
        }elseif(StringUtils.contains(tags,"TagB")){
            return LocalTransactionState.ROLLBACK_MESSAGE;
        }else{
            return LocalTransactionState.UNKNOW;
        }
    }

    @Overridepublic LocalTransactionState checkLocalTransaction(MessageExt msg) {
//        Integer status = localTrans.get(msg.getTransactionId());//        if (null != status) {//            switch (status) {//                case 0://                    return LocalTransactionState.UNKNOW;//                case 1://                    return LocalTransactionState.COMMIT_MESSAGE;//                case 2://                    return LocalTransactionState.ROLLBACK_MESSAGE;//                default://                    return LocalTransactionState.COMMIT_MESSAGE;//            }//        }//        return LocalTransactionState.COMMIT_MESSAGE;Stringtags= msg.getTags();
        if(StringUtils.contains(tags,"TagC")){
            return LocalTransactionState.COMMIT_MESSAGE;
        }elseif(StringUtils.contains(tags,"TagD")){
            return LocalTransactionState.ROLLBACK_MESSAGE;
        }else{
            return LocalTransactionState.UNKNOW;
        }
    }
}
  1. rocketMQ和SpringBoot的整合

(1)引入依赖

(2)配置文件

12.rocketMQ和SpringCloud的整合

1.导包

2.启动类

编辑

3.配置类

input 消息接收者 对应启动类上面的Source.class
output 消息发送者 对应启动类上面的Sink.class

name-server 指定地址

编辑


编辑

生产者

source.output().send(message)

编辑

消费者

编辑

如果哪天不用rocketMQ,换成别的,我们只需要换掉pom依赖,改一下配置即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值