本文结合和了nacos,利用nacos配置中心初始化MQ生产者及消费者,后续如果需要增加生产者或消费组,更改配置增加消费业务即可。
#阿里云RocketMQ
rocketmq:
producers: #生产者
pay: #名称自定义,数据结构默认一个topic对应一个mq实例
name-srv-addr:
access-key:
secret-key:
topic:
sendTimeout: 4000
refund: #名称自定义,数据结构默认一个topic对应一个实例
name-srv-addr:
access-key:
secret-key:
topic:
sendTimeout: 4000
consumers: #消费者
pay: #名称自定义,数据结构默认一个消费组对应一个mq实例
name-srv-addr:
access-key:
secret-key:
group-id:
consume-thread-nums: 10
enable: true
consumer-list:
- topic:
tag:
beanName:
定义配置类与nacos配置的数据结构相匹配
@Configuration
@ConfigurationProperties(prefix = "rocketmq")
@EnableConfigurationProperties({RocketMQConfig.class})
@Data
public class RocketMQConfig {
private Map<String, ConsumerItem> consumers;
private Map<String, ProducerItem> producers;
@Data
public static class ProducerItem {
private String groupId;
private String accessKey;
private String secretKey;
private String nameSrvAddr;
private String topic;
private String sendTimeout;
public Properties buildPropertie() {
Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.AccessKey, this.accessKey);
properties.setProperty(PropertyKeyConst.SecretKey, this.secretKey);
properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, this.nameSrvAddr);
//设置发送超时时间,单位毫秒
properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis,
StringUtils.defaultIfEmpty(sendTimeout,"4000"));
return properties;
}
}
@Data
public static class ConsumerItem {
private Boolean enable;
private String groupId;
private String accessKey;
private String secretKey;
private String nameSrvAddr;
private String consumeThreadNums;
private List<RocketMQConsumer> consumerList;
public Properties buildPropertie() {
Properties properties = new Properties();
properties.setProperty(PropertyKeyConst.AccessKey, this.accessKey);
properties.setProperty(PropertyKeyConst.SecretKey, this.secretKey);
properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, this.nameSrvAddr);
properties.setProperty(PropertyKeyConst.ConsumeThreadNums,
StringUtils.defaultIfEmpty(consumeThreadNums,"10"));
properties.setProperty(PropertyKeyConst.GROUP_ID, this.groupId);
return properties;
}
}
@Data
public static class RocketMQConsumer{
private String topic;
private String tag;
private String beanName;
}
}
初始化生产者
@Slf4j
@Component
public class RocketProducer {
@Resource
RocketMQConfig rocketMQConfig;
private static final Map<String,ProducerBean> producerBeanMap;
static {
producerBeanMap = new ConcurrentHashMap<>();
}
public static Producer producerRoute(String topic) {
return Optional.ofNullable(producerBeanMap.get(topic))
.orElseThrow(() ->
new IllegalArgumentException(String.format(
"没有对应的生产者, topic -> %s", topic)));
}
@PostConstruct
public void initProducer() {
producerBeanMap.clear();
Map<String, RocketMQConfig.ProducerItem> producers = rocketMQConfig.getProducers();
producers.forEach((key,item)->{
log.info("消息队列组件|生产者初始化|开始, config -> {}", item);
try {
Properties properties = item.buildPropertie();
ProducerBean producer = new ProducerBean();
producer.setProperties(properties);
producer.start();
producerBeanMap.put(item.getTopic(), producer);
} catch (Exception e) {
throw new RuntimeException(String.format(
"消息队列组件|创建生产者发生错误, key -> %s, config -> %s", key, item), e);
}
log.info("消息队列组件|生产者初始化|结束");
});
}
}
调用案例
Producer producer = RocketProducer.producerRoute("topic");
producer.sendOneway(
new Message(
"topic",
"tag",
JSON.toJSONString(msg).getBytes(StandardCharsets.UTF_8)
));
初始化消费者
@Slf4j
@Component
public class RocketConsumer {
@Resource
RocketMQConfig rocketMQConfig;
@Resource
ApplicationContext applicationContext;
@PostConstruct
public void initConsumer() {
Map<String, RocketMQConfig.ConsumerItem> consumers = rocketMQConfig.getConsumers();
consumers.forEach((key, item) -> {
log.info("消息队列组件|消费者初始化|开始, config -> {}", item);
if (Boolean.TRUE.equals(item.getEnable())) {
try {
ConsumerBean consumerBean = new ConsumerBean();
Properties properties = item.buildPropertie();
consumerBean.setProperties(properties);
//订阅消息
Map<Subscription, MessageListener> subscriptionTable = new HashMap<>();
item.getConsumerList().forEach(config -> {
//订阅普通消息
Subscription subscription = new Subscription();
subscription.setTopic(config.getTopic());
subscription.setExpression(config.getTag());
subscriptionTable.put(subscription, applicationContext.getBean(
config.getBeanName(),MessageListener.class));
});
consumerBean.setSubscriptionTable(subscriptionTable);
consumerBean.start();
} catch (Exception e) {
throw new RuntimeException(String.format("消息队列组件|创建消费者发生错误,
key -> %s, config -> %s", key, item), e);
}
log.info("消息队列组件|消费者初始化|结束");
}
});
}
}
定义消费Bean
@Component
@Slf4j
public class ConsumerListner implements MessageListener {
@Override
public Action consume(Message message, ConsumeContext consumeContext) {
}
}