为了实现通过REST API动态控制RocketMQ消息消费的功能,我们可以采用以下设计方案。这个方案旨在提供一种机制,允许我们动态地启动、停止、或修改RocketMQ消费者的行为,同时能够通过API实时获取消费状态和消息内容。
核心组件设计
-
消费者管理器(ConsumerManager):
- 负责创建、启动、停止和管理RocketMQ消费者实例。
- 支持按主题(Topic)、标签(Tag)和消费者组(Consumer Group)动态管理消费者。
-
消息存储(MessageStorage):
- 暂时存储已消费的消息,以便API能查询到最近消费的消息。
- 提供基于主题和标签的消息查询接口。
-
动态配置服务(DynamicConfigService):
- 管理消费者配置,如当前活跃的主题和标签。
- 提供接口修改和查询当前的消费配置。
-
REST API控制器(ConsumerController):
- 提供REST API接口,允许动态控制消费者和查询消息。
消费者管理器实现
@Service
public class ConsumerManager {
private Map<String, PushConsumer> consumerMap = new ConcurrentHashMap<>();
@Autowired
private MessageStorage messageStorage;
public void startConsumer(String topic, String tag, String consumerGroup) throws MQClientException {
// 基于topic, tag, consumerGroup创建唯一的消费者ID
String consumerId = consumerGroup + "|" + topic + "|" + tag;
if (consumerMap.containsKey(consumerId)) {
return; // 已存在则不重复创建
}
// 创建并配置消费者
PushConsumer consumer = ... // 省略创建和配置消费者的代码
consumer.subscribe(topic, tag);
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (MessageExt msg : msgs) {
// 存储消息到MessageStorage
messageStorage.storeMessage(consumerGroup, topic, tag, new String(msg.getBody(), StandardCharsets.UTF_8));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
consumer.start();
consumerMap.put(consumerId, consumer);
}
public void stopConsumer(String consumerGroup, String topic, String tag) {
String consumerId = consumerGroup + "|" + topic + "|" + tag;
PushConsumer consumer = consumerMap.remove(consumerId);
if (consumer != null) {
consumer.shutdown();
}
}
}
消息存储实现
@Service
public class MessageStorage {
private List<String> messages = new CopyOnWriteArrayList<>();
public void storeMessage(String consumerGroup, String topic, String tag, String message) {
// 实际实现应当更加复杂,可能包含时间戳、消费者信息等
messages.add(message);
}
public List<String> getMessages() {
return new ArrayList<>(messages);
}
}
REST API控制器实现
@RestController
@RequestMapping("/api/consumer")
public class ConsumerController {
@Autowired
private ConsumerManager consumerManager;
@Autowired
private MessageStorage messageStorage;
@PostMapping("/start")
public ResponseEntity<?> startConsumer(@RequestParam String topic, @RequestParam String tag, @RequestParam String consumerGroup) {
try {
consumerManager.startConsumer(topic, tag, consumerGroup);
return ResponseEntity.ok().body("Consumer started successfully.");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error starting consumer: " + e.getMessage());
}
}
@PostMapping("/stop")
public ResponseEntity<?> stopConsumer(@RequestParam String topic, @RequestParam String tag, @RequestParam String consumerGroup) {
consumerManager.stopConsumer(consumerGroup, topic, tag);
return ResponseEntity.ok().body("Consumer stopped successfully.");
}
@GetMapping("/messages")
public ResponseEntity<?> getMessages() {
List<String> messages = messageStorage.getMessages();
return ResponseEntity.ok().body(messages);
}
}