RocketMQ去除IF-ELSE写法

RocketMQ很好使,如果用同一个消费组来消费多个topic时,我们需要先将所要监听的topic绑定到消费组上,然后就可以监听了,但是这种写法适合于用一个消费组,后期每添加一个topic就会多一个if-else来判断,所以有了下面这种方法.

第一步:首先我们定义一个BaseConsumer

public abstract class BaseConsumer {
	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	private DefaultMQPushConsumer consumer;
	
	protected String namesrvAddr;
	
	protected String consumerGroup;
	
	protected String topic;
	
	protected String subExpression;
	
	//最小线程
	protected int consumeThreadMin;
	
	//最大线程
	protected int consumeThreadMax;
	
	protected BaseConsumer(String namesrvAddr, String topic, String consumerGroup, String subExpression,int consumeThreadMin,int consumeThreadMax){
		this.namesrvAddr = namesrvAddr;
		this.consumerGroup = consumerGroup;
		this.topic = topic;
		this.subExpression = subExpression;
		this.consumeThreadMin = consumeThreadMin;
		this.consumeThreadMax = consumeThreadMax;
	}
	
	protected abstract boolean consumeMsg(List<MessageExt> msgs,ConsumeConcurrentlyContext context);
	
	@PostConstruct
	public final void start() throws MQClientException{
		consumer = new DefaultMQPushConsumer();
		consumer.setConsumerGroup(this.consumerGroup);
		consumer.setNamesrvAddr(this.namesrvAddr);
		consumer.subscribe(topic, subExpression);
		consumer.setConsumeThreadMin(this.consumeThreadMin);
		consumer.setConsumeThreadMax(this.consumeThreadMax);
		consumer.setInstanceName(RuntimeUtil.getRocketMqUniqeInstanceName());
		consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
		consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
		//设置大于4次后就不消费了
			if (msgs.get(0).getReconsumeTimes() > 4) {
				return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
			}
			return consumeMsg(msgs,context)?ConsumeConcurrentlyStatus.CONSUME_SUCCESS:ConsumeConcurrentlyStatus.RECONSUME_LATER;
		});
		consumer.start();
	}
	
	@PreDestroy
	public final void destroy(){
		consumer.shutdown();
	}
}

第二步:再写个需要使用的消费者,继承它.

public class TestConsumer extends BaseConsumer {

    public TestConsumer(String namesrvAddr, String topic, String consumerGroup, String subExpression, int consumeThreadMin, int consumeThreadMax) {
        super(namesrvAddr, topic, consumerGroup, subExpression, consumeThreadMin, consumeThreadMax);
    }

    @Override
    protected boolean consumeMsg(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        MessageExt msg = msgs.get(0);
        // 当前的偏移量
//        long offset = msg.getQueueOffset();
//        String maxOffset = msg.getProperty(MessageConst.PROPERTY_MAX_OFFSET);
//         当前的未消费量
//        long diff = Long.parseLong(maxOffset) - offset;
        String message = new String(msg.getBody(), StandardCharsets.UTF_8);
        logger.info("test:{}", message);
        return true;
    }
}

第三步:然后声明个Bean,把自己的mq地址,topic,consumerGroup,tag,线程数,填入里面,即可食用.

@Configuration
public class BeanConfig {
    @Bean
    public TestConsumer testConsumer() {
        return new TestConsumer(namesrvAddr,
                "TopicTest",
                "TestCG",
                "*",
                5,
                10);
    }
}

这种方法好处在于,再加入新的topic时,可以直接继承BaseConsumer即可,比较方便管理,不再监听某一Topic时,可以直接将@Bean注释掉就可以了.

但是有一点需要注意,每增加一个新的Topic,你需要用一个新的ConsumerGroup,不然将会报错,这个错误虽然是可以解决的,但是会将出现一个别的错误,这个我将在下一个博客中说明.

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