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,不然將會報錯,這個錯誤雖然是可以解決的,但是會將出現一個別的錯誤,這個我將在下一個博客中說明.

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