消息中间件RocketMQ(四):如何替换RocketMQTemplate

生产者

1.依赖

	
        org.apache.rocketmq
        rocketmq-client
        4.5.1
    
    
        org.apache.rocketmq
        rocketmq-common
        4.5.1
    

2.配置文件

  • 为了方便修改 并不是springboot的配置
# NameServer地址
apache.rocketmq.namesrvAddr=192.168.56.129:9876
# 生产者的组名
apache.rocketmq.producer.producerGroup=test_Producer

发送非事务消息
1.配置类

import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

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

@Component
public class MsgProducer {

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

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

    private DefaultMQProducer mqProducer;

	//调用方注入MsgProducer后 通过这个方法获取配置好的DefaultMQProducer
    public DefaultMQProducer getMqProducer(){
        return mqProducer;
    }

    @PostConstruct
    public void initMQ(){
        mqProducer=new DefaultMQProducer(producerGroup);
        mqProducer.setNamesrvAddr(namesrvAddr);
        mqProducer.setVipChannelEnabled(false);
        try {
            mqProducer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }
    }

    @PreDestroy
    public void destory(){
        mqProducer.shutdown();
    }
}

2.发送消息

  • 简单消费
 	@Autowired
    private MsgProducer msgProducer;

    public void sendMsg() throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
        //消息体
        String msg="hello";
        //包装成消息
        Message message=new Message("test_topic_2","test",msg.getBytes());
        //调用配置好的DefaultMQProducer发送消息
        SendResult result=msgProducer.getMqProducer().send(message);
    }
  • 异步消费

    • 就是send()的参数多加个callback 省略…
  • 顺序消费

	@Autowired
    private MsgProducer msgProducer;

    public void sendMsg() throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
    	//发100条消息测试
        for(int i=1;i<=100;i++){
        	/**
        	 * 消息 
        	 * 因为默认自动创建的topic有四个队列 所以type表示队列id、value表示值
        	 * 如果按照队列读取 那么同一个type下的value一定按照接收的顺序从小到大
        	 * /
            String msg="type:"+i%4+" value:"+i;
            Message message=new Message("test_topic_2","test",msg.getBytes());
            
            SendResult result=msgProducer.getMqProducer().send(message, new MessageQueueSelector() {
                        @Override
                        //args一般是唯一id 用send的第三个参数传入(这里指的i)
                        public MessageQueue select(List mqs, Message msg, Object arg) {
                        
                            int queueNum = Integer.valueOf(String.valueOf(arg)) % 4;
                            System.out.println("队列id:"+queueNum+" 消息:"+new String(msg.getBody()));
                            
                            return mqs.get(queueNum);
                        }
                    },i);
        }
    }

事务消息
1.配置类

@Component
public class TxMsgProducer {

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

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

    private TransactionMQProducer mqProducer;

    public DefaultMQProducer getMqProducer(){
        return mqProducer;
    }

    @PostConstruct
    public void initMQ(){
        mqProducer=new TransactionMQProducer(producerGroup);
        mqProducer.setNamesrvAddr(namesrvAddr);
        mqProducer.setVipChannelEnabled(false);
        mqProducer.setNamesrvAddr(namesrvAddr);
        //下面两个时新增的
        mqProducer.setExecutorService(getExecutorService());
        mqProducer.setTransactionListener(new TransactionListenerImpl());

        try {
            mqProducer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }
    }

    @PreDestroy//在程序运行结束时执行
    public void destory(){
        mqProducer.shutdown();
    }


    /**
     * 事务监听
     */
    class TransactionListenerImpl implements TransactionListener {
        /**
         * 第一次判断是否提交或回滚
         *
         * @param message
         * @param arg
         * @return
         */
        @Override
        public LocalTransactionState executeLocalTransaction(Message message, Object arg){

            //message就是那个半发送的消息 arg是在transcationProducter.send(Message,Object)时的另外一个携带参数)

            //执行本地事务或调用其他为服务

            if(true) return LocalTransactionState.COMMIT_MESSAGE;

            if(true) return LocalTransactionState.ROLLBACK_MESSAGE;

            //如果在检查事务时数据库出现宕机可以让broker过一段时间回查 和return null 效果相同
            return LocalTransactionState.UNKNOW;
        }

        /**
         * 返回UNKOWN时回查!
         * @param messageExt
         * @return
         */
        @Override
        public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
            //只去返回commit或者rollback
            return LocalTransactionState.COMMIT_MESSAGE;
        }


    }

    /**
     * 定义一个线程池 让broker用来执行回调和回查
     * 
     * @return
     */
    public ExecutorService getExecutorService(){
        return new ThreadPoolExecutor(2, 5, 100, TimeUnit.SECONDS, new ArrayBlockingQueue(2000));
    }
    
}

2.发送消息

@Autowired
    private TxMsgProducer msgProducer;

    public void sendMsg() throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
        String msg="hello";
        Message message=new Message("test_topic_2","test",msg.getBytes());
        //调用配置好的TxMsgProducer 发送消息
        SendResult result=msgProducer.getMqProducer().send(message);
    }

消费者

1.依赖

	
        org.apache.rocketmq
        rocketmq-client
        4.5.1
    
    
        org.apache.rocketmq
        rocketmq-common
        4.5.1
    

2.配置文件

  • 为了方便修改 并不是springboot的配置
# NameServer地址
apache.rocketmq.namesrvAddr=192.168.56.129:9876
# 消费者的组名
apache.rocketmq.consumer.PushConsumer=test_Consumer

3.消费消息

@Component
public class MsgConsumer {

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

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

    private DefaultMQPushConsumer consumer;

    @PostConstruct
    public void init() throws MQClientException {
        consumer=new DefaultMQPushConsumer(consumerGroup);
        consumer.setNamesrvAddr(namesrvAddr);

        //设置consumer所订阅的Topic和Tag,*代表全部的Tag
        consumer.subscribe("test_topic_2", "*");

        /**
         * CONSUME_FROM_LAST_OFFSET 默认策略,从该队列最尾开始消费,跳过历史消息
         * CONSUME_FROM_FIRST_OFFSET 从队列最开始开始消费,即历史消息(还储存在broker的)全部消费一遍
         * /
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
        
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeOrderlyContext consumeOrderlyContext) {
                try{
                    System.out.println("接受:"+new String(list.get(0).getBody()));
                }catch (Exception e){
                    return ConsumeConcurrentlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;
                }
                return ConsumeConcurrentlyStatus.SUCCESS;
            }
        });
        consumer.start();
    }


    @PreDestroy
    public void destory(){
        consumer.shutdown();
    }
}
  • 顺序消费
    • 只用把 consumer.registerMessageListener(new MessageListenerConcurrently(){}) 改成consumer.registerMessageListener(new MessageListenerOrderly(){})
  • 事务消费
    • 不用改变消费者 如果事务的监听rollback了 消费者的消费结果会自动回滚
  • 广播消费
    consumer.setMessageMode(MessageMode.BROADCASTING)
    consumer.setOffsetStore(OffsetStore.LocalFileOffsetStore)
    

你可能感兴趣的:(消息队列,搜索引擎)