Commit 19cf311b7e476076333ab8981afd093445e5213c

Authored by YunaiV
1 parent 69e25eea

feat:【IoT 物联网】增加 redis + event-bus 的实现

Showing 13 changed files with 160 additions and 48 deletions
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQConsumerAutoConfiguration.java
@@ -69,9 +69,8 @@ public class YudaoRedisMQConsumerAutoConfiguration { @@ -69,9 +69,8 @@ public class YudaoRedisMQConsumerAutoConfiguration {
69 @ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听 69 @ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听
70 public RedisPendingMessageResendJob redisPendingMessageResendJob(List<AbstractRedisStreamMessageListener<?>> listeners, 70 public RedisPendingMessageResendJob redisPendingMessageResendJob(List<AbstractRedisStreamMessageListener<?>> listeners,
71 RedisMQTemplate redisTemplate, 71 RedisMQTemplate redisTemplate,
72 - @Value("${spring.application.name}") String groupName,  
73 RedissonClient redissonClient) { 72 RedissonClient redissonClient) {
74 - return new RedisPendingMessageResendJob(listeners, redisTemplate, groupName, redissonClient); 73 + return new RedisPendingMessageResendJob(listeners, redisTemplate, redissonClient);
75 } 74 }
76 75
77 /** 76 /**
@@ -141,14 +140,14 @@ public class YudaoRedisMQConsumerAutoConfiguration { @@ -141,14 +140,14 @@ public class YudaoRedisMQConsumerAutoConfiguration {
141 * 140 *
142 * @return 消费者名字 141 * @return 消费者名字
143 */ 142 */
144 - private static String buildConsumerName() { 143 + public static String buildConsumerName() {
145 return String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID()); 144 return String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());
146 } 145 }
147 146
148 /** 147 /**
149 * 校验 Redis 版本号,是否满足最低的版本号要求! 148 * 校验 Redis 版本号,是否满足最低的版本号要求!
150 */ 149 */
151 - private static void checkRedisVersion(RedisTemplate<String, ?> redisTemplate) { 150 + public static void checkRedisVersion(RedisTemplate<String, ?> redisTemplate) {
152 // 获得 Redis 版本 151 // 获得 Redis 版本
153 Properties info = redisTemplate.execute((RedisCallback<Properties>) RedisServerCommands::info); 152 Properties info = redisTemplate.execute((RedisCallback<Properties>) RedisServerCommands::info);
154 String version = MapUtil.getStr(info, "redis_version"); 153 String version = MapUtil.getStr(info, "redis_version");
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/core/job/RedisPendingMessageResendJob.java
@@ -35,7 +35,6 @@ public class RedisPendingMessageResendJob { @@ -35,7 +35,6 @@ public class RedisPendingMessageResendJob {
35 35
36 private final List<AbstractRedisStreamMessageListener<?>> listeners; 36 private final List<AbstractRedisStreamMessageListener<?>> listeners;
37 private final RedisMQTemplate redisTemplate; 37 private final RedisMQTemplate redisTemplate;
38 - private final String groupName;  
39 private final RedissonClient redissonClient; 38 private final RedissonClient redissonClient;
40 39
41 /** 40 /**
@@ -64,13 +63,13 @@ public class RedisPendingMessageResendJob { @@ -64,13 +63,13 @@ public class RedisPendingMessageResendJob {
64 private void execute() { 63 private void execute() {
65 StreamOperations<String, Object, Object> ops = redisTemplate.getRedisTemplate().opsForStream(); 64 StreamOperations<String, Object, Object> ops = redisTemplate.getRedisTemplate().opsForStream();
66 listeners.forEach(listener -> { 65 listeners.forEach(listener -> {
67 - PendingMessagesSummary pendingMessagesSummary = Objects.requireNonNull(ops.pending(listener.getStreamKey(), groupName)); 66 + PendingMessagesSummary pendingMessagesSummary = Objects.requireNonNull(ops.pending(listener.getStreamKey(), listener.getGroup()));
68 // 每个消费者的 pending 队列消息数量 67 // 每个消费者的 pending 队列消息数量
69 Map<String, Long> pendingMessagesPerConsumer = pendingMessagesSummary.getPendingMessagesPerConsumer(); 68 Map<String, Long> pendingMessagesPerConsumer = pendingMessagesSummary.getPendingMessagesPerConsumer();
70 pendingMessagesPerConsumer.forEach((consumerName, pendingMessageCount) -> { 69 pendingMessagesPerConsumer.forEach((consumerName, pendingMessageCount) -> {
71 log.info("[processPendingMessage][消费者({}) 消息数量({})]", consumerName, pendingMessageCount); 70 log.info("[processPendingMessage][消费者({}) 消息数量({})]", consumerName, pendingMessageCount);
72 // 每个消费者的 pending消息的详情信息 71 // 每个消费者的 pending消息的详情信息
73 - PendingMessages pendingMessages = ops.pending(listener.getStreamKey(), Consumer.from(groupName, consumerName), Range.unbounded(), pendingMessageCount); 72 + PendingMessages pendingMessages = ops.pending(listener.getStreamKey(), Consumer.from(listener.getGroup(), consumerName), Range.unbounded(), pendingMessageCount);
74 if (pendingMessages.isEmpty()) { 73 if (pendingMessages.isEmpty()) {
75 return; 74 return;
76 } 75 }
@@ -91,7 +90,7 @@ public class RedisPendingMessageResendJob { @@ -91,7 +90,7 @@ public class RedisPendingMessageResendJob {
91 .ofObject(records.get(0).getValue()) // 设置内容 90 .ofObject(records.get(0).getValue()) // 设置内容
92 .withStreamKey(listener.getStreamKey())); 91 .withStreamKey(listener.getStreamKey()));
93 // ack 消息消费完成 92 // ack 消息消费完成
94 - redisTemplate.getRedisTemplate().opsForStream().acknowledge(groupName, records.get(0)); 93 + redisTemplate.getRedisTemplate().opsForStream().acknowledge(listener.getGroup(), records.get(0));
95 log.info("[processPendingMessage][消息({})重新投递成功]", records.get(0).getId()); 94 log.info("[processPendingMessage][消息({})重新投递成功]", records.get(0).getId());
96 }); 95 });
97 }); 96 });
yudao-module-iot/yudao-module-iot-core/pom.xml
@@ -33,6 +33,11 @@ @@ -33,6 +33,11 @@
33 33
34 <!-- 消息中间件相关(可选依赖) --> 34 <!-- 消息中间件相关(可选依赖) -->
35 <dependency> 35 <dependency>
  36 + <groupId>cn.iocoder.boot</groupId>
  37 + <artifactId>yudao-spring-boot-starter-mq</artifactId>
  38 + </dependency>
  39 +
  40 + <dependency>
36 <groupId>org.springframework.data</groupId> 41 <groupId>org.springframework.data</groupId>
37 <artifactId>spring-data-redis</artifactId> 42 <artifactId>spring-data-redis</artifactId>
38 <optional>true</optional> 43 <optional>true</optional>
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/config/IotMessageBusAutoConfiguration.java
1 package cn.iocoder.yudao.module.iot.core.messagebus.config; 1 package cn.iocoder.yudao.module.iot.core.messagebus.config;
2 2
3 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; 3 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
4 -import cn.iocoder.yudao.module.iot.core.messagebus.core.local.LocalIotMessageBus;  
5 -import cn.iocoder.yudao.module.iot.core.messagebus.core.rocketmq.RocketMQIotMessageBus; 4 +import cn.iocoder.yudao.module.iot.core.messagebus.core.local.IotLocalMessageBus;
  5 +import cn.iocoder.yudao.module.iot.core.messagebus.core.redis.IotRedisMessageBus;
  6 +import cn.iocoder.yudao.module.iot.core.messagebus.core.rocketmq.IotRocketMQMessageBus;
6 import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; 7 import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
7 import lombok.extern.slf4j.Slf4j; 8 import lombok.extern.slf4j.Slf4j;
8 import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties; 9 import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties;
@@ -14,6 +15,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties @@ -14,6 +15,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
14 import org.springframework.context.ApplicationContext; 15 import org.springframework.context.ApplicationContext;
15 import org.springframework.context.annotation.Bean; 16 import org.springframework.context.annotation.Bean;
16 import org.springframework.context.annotation.Configuration; 17 import org.springframework.context.annotation.Configuration;
  18 +import org.springframework.data.redis.core.RedisTemplate;
  19 +import org.springframework.data.redis.core.StringRedisTemplate;
17 20
18 /** 21 /**
19 * IoT 消息总线自动配置 22 * IoT 消息总线自动配置
@@ -34,12 +37,12 @@ public class IotMessageBusAutoConfiguration { @@ -34,12 +37,12 @@ public class IotMessageBusAutoConfiguration {
34 37
35 @Configuration 38 @Configuration
36 @ConditionalOnProperty(prefix = "yudao.iot.message-bus", name = "type", havingValue = "local", matchIfMissing = true) 39 @ConditionalOnProperty(prefix = "yudao.iot.message-bus", name = "type", havingValue = "local", matchIfMissing = true)
37 - public static class LocalIotMessageBusConfiguration { 40 + public static class IotLocalMessageBusConfiguration {
38 41
39 @Bean 42 @Bean
40 - public IotMessageBus localIotMessageBus(ApplicationContext applicationContext) {  
41 - log.info("[localIotMessageBus][创建 Local IoT 消息总线]");  
42 - return new LocalIotMessageBus(applicationContext); 43 + public IotMessageBus iotLocalMessageBus(ApplicationContext applicationContext) {
  44 + log.info("[iotLocalMessageBus][创建 IoT Local 消息总线]");
  45 + return new IotLocalMessageBus(applicationContext);
43 } 46 }
44 47
45 } 48 }
@@ -49,13 +52,28 @@ public class IotMessageBusAutoConfiguration { @@ -49,13 +52,28 @@ public class IotMessageBusAutoConfiguration {
49 @Configuration 52 @Configuration
50 @ConditionalOnProperty(prefix = "yudao.iot.message-bus", name = "type", havingValue = "rocketmq") 53 @ConditionalOnProperty(prefix = "yudao.iot.message-bus", name = "type", havingValue = "rocketmq")
51 @ConditionalOnClass(RocketMQTemplate.class) 54 @ConditionalOnClass(RocketMQTemplate.class)
52 - public static class RocketMQIotMessageBusConfiguration { 55 + public static class IotRocketMQMessageBusConfiguration {
53 56
54 @Bean 57 @Bean
55 - @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")  
56 - public IotMessageBus rocketMQIotMessageBus(RocketMQProperties rocketMQProperties, RocketMQTemplate rocketMQTemplate) {  
57 - log.info("[rocketMQIotMessageBus][创建 RocketMQ IoT 消息总线]");  
58 - return new RocketMQIotMessageBus(rocketMQProperties, rocketMQTemplate); 58 + public IotMessageBus iotRocketMQMessageBus(RocketMQProperties rocketMQProperties,
  59 + RocketMQTemplate rocketMQTemplate) {
  60 + log.info("[iotRocketMQMessageBus][创建 IoT RocketMQ 消息总线]");
  61 + return new IotRocketMQMessageBus(rocketMQProperties, rocketMQTemplate);
  62 + }
  63 +
  64 + }
  65 +
  66 + // ==================== Redis 实现 ====================
  67 +
  68 + @Configuration
  69 + @ConditionalOnProperty(prefix = "yudao.iot.message-bus", name = "type", havingValue = "redis")
  70 + @ConditionalOnClass(RedisTemplate.class)
  71 + public static class IotRedisMessageBusConfiguration {
  72 +
  73 + @Bean
  74 + public IotMessageBus iotRedisMessageBus(StringRedisTemplate redisTemplate) {
  75 + log.info("[iotRedisMessageBus][创建 IoT Redis 消息总线]");
  76 + return new IotRedisMessageBus(redisTemplate);
59 } 77 }
60 78
61 } 79 }
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/LocalIotMessage.java renamed to yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/IotLocalMessage.java
@@ -5,7 +5,7 @@ import lombok.Data; @@ -5,7 +5,7 @@ import lombok.Data;
5 5
6 @Data 6 @Data
7 @AllArgsConstructor 7 @AllArgsConstructor
8 -public class LocalIotMessage { 8 +public class IotLocalMessage {
9 9
10 private String topic; 10 private String topic;
11 11
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/LocalIotMessageBus.java renamed to yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/IotLocalMessageBus.java
@@ -22,7 +22,7 @@ import java.util.Map; @@ -22,7 +22,7 @@ import java.util.Map;
22 */ 22 */
23 @RequiredArgsConstructor 23 @RequiredArgsConstructor
24 @Slf4j 24 @Slf4j
25 -public class LocalIotMessageBus implements IotMessageBus { 25 +public class IotLocalMessageBus implements IotMessageBus {
26 26
27 private final ApplicationContext applicationContext; 27 private final ApplicationContext applicationContext;
28 28
@@ -34,7 +34,7 @@ public class LocalIotMessageBus implements IotMessageBus { @@ -34,7 +34,7 @@ public class LocalIotMessageBus implements IotMessageBus {
34 34
35 @Override 35 @Override
36 public void post(String topic, Object message) { 36 public void post(String topic, Object message) {
37 - applicationContext.publishEvent(new LocalIotMessage(topic, message)); 37 + applicationContext.publishEvent(new IotLocalMessage(topic, message));
38 } 38 }
39 39
40 @Override 40 @Override
@@ -48,7 +48,7 @@ public class LocalIotMessageBus implements IotMessageBus { @@ -48,7 +48,7 @@ public class LocalIotMessageBus implements IotMessageBus {
48 48
49 @EventListener 49 @EventListener
50 @SuppressWarnings({"unchecked", "rawtypes"}) 50 @SuppressWarnings({"unchecked", "rawtypes"})
51 - public void onMessage(LocalIotMessage message) { 51 + public void onMessage(IotLocalMessage message) {
52 String topic = message.getTopic(); 52 String topic = message.getTopic();
53 List<IotMessageSubscriber<?>> topicSubscribers = subscribers.get(topic); 53 List<IotMessageSubscriber<?>> topicSubscribers = subscribers.get(topic);
54 if (CollUtil.isEmpty(topicSubscribers)) { 54 if (CollUtil.isEmpty(topicSubscribers)) {
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/redis/IotRedisMessageBus.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.core.messagebus.core.redis;
  2 +
  3 +import cn.hutool.core.util.TypeUtil;
  4 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  5 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
  6 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
  7 +import jakarta.annotation.PostConstruct;
  8 +import jakarta.annotation.PreDestroy;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.springframework.data.redis.connection.stream.*;
  11 +import org.springframework.data.redis.core.RedisTemplate;
  12 +import org.springframework.data.redis.stream.StreamMessageListenerContainer;
  13 +
  14 +import java.lang.reflect.Type;
  15 +
  16 +import static cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQConsumerAutoConfiguration.buildConsumerName;
  17 +import static cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQConsumerAutoConfiguration.checkRedisVersion;
  18 +
  19 +/**
  20 + * Redis 的 {@link IotMessageBus} 实现类
  21 + *
  22 + * @author 芋道源码
  23 + */
  24 +@Slf4j
  25 +public class IotRedisMessageBus implements IotMessageBus {
  26 +
  27 + private final RedisTemplate<String, ?> redisTemplate;
  28 +
  29 + private final StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer;
  30 +
  31 + public IotRedisMessageBus(RedisTemplate<String, ?> redisTemplate) {
  32 + this.redisTemplate = redisTemplate;
  33 + checkRedisVersion(redisTemplate);
  34 + // 创建 options 配置
  35 + StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, ObjectRecord<String, String>> containerOptions =
  36 + StreamMessageListenerContainer.StreamMessageListenerContainerOptions.builder()
  37 + .batchSize(10) // 一次性最多拉取多少条消息
  38 + .targetType(String.class) // 目标类型。统一使用 String,通过自己封装的 AbstractStreamMessageListener 去反序列化
  39 + .build();
  40 + // 创建 container 对象
  41 + this.redisStreamMessageListenerContainer =
  42 + StreamMessageListenerContainer.create(redisTemplate.getRequiredConnectionFactory(), containerOptions);
  43 + }
  44 +
  45 + @PostConstruct
  46 + public void init() {
  47 + this.redisStreamMessageListenerContainer.start();
  48 + }
  49 +
  50 + @PreDestroy
  51 + public void destroy() {
  52 + this.redisStreamMessageListenerContainer.stop();
  53 + }
  54 +
  55 + @Override
  56 + public void post(String topic, Object message) {
  57 + redisTemplate.opsForStream().add(StreamRecords.newRecord()
  58 + .ofObject(JsonUtils.toJsonString(message)) // 设置内容
  59 + .withStreamKey(topic)); // 设置 stream key
  60 + }
  61 +
  62 + @Override
  63 + public void register(IotMessageSubscriber<?> subscriber) {
  64 + Type type = TypeUtil.getTypeArgument(subscriber.getClass(), 0);
  65 + if (type == null) {
  66 + throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName()));
  67 + }
  68 +
  69 + // 创建 listener 对应的消费者分组
  70 + try {
  71 + redisTemplate.opsForStream().createGroup(subscriber.getTopic(), subscriber.getGroup());
  72 + } catch (Exception ignore) {
  73 + }
  74 + // 创建 Consumer 对象
  75 + String consumerName = buildConsumerName();
  76 + Consumer consumer = Consumer.from(subscriber.getGroup(), consumerName);
  77 + // 设置 Consumer 消费进度,以最小消费进度为准
  78 + StreamOffset<String> streamOffset = StreamOffset.create(subscriber.getTopic(), ReadOffset.lastConsumed());
  79 + // 设置 Consumer 监听
  80 + StreamMessageListenerContainer.StreamReadRequestBuilder<String> builder = StreamMessageListenerContainer.StreamReadRequest
  81 + .builder(streamOffset).consumer(consumer)
  82 + .autoAcknowledge(false) // 不自动 ack
  83 + .cancelOnError(throwable -> false); // 默认配置,发生异常就取消消费,显然不符合预期;因此,我们设置为 false
  84 + redisStreamMessageListenerContainer.register(builder.build(), message -> {
  85 + // 消费消息
  86 + subscriber.onMessage(JsonUtils.parseObject(message.getValue(), type));
  87 + // ack 消息消费完成
  88 + redisTemplate.opsForStream().acknowledge(subscriber.getGroup(), message);
  89 + });
  90 + }
  91 +
  92 +}
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/rocketmq/RocketMQIotMessageBus.java renamed to yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/rocketmq/IotRocketMQMessageBus.java
@@ -4,6 +4,7 @@ import cn.hutool.core.util.TypeUtil; @@ -4,6 +4,7 @@ import cn.hutool.core.util.TypeUtil;
4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; 5 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
6 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber; 6 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
  7 +import jakarta.annotation.PreDestroy;
7 import lombok.RequiredArgsConstructor; 8 import lombok.RequiredArgsConstructor;
8 import lombok.SneakyThrows; 9 import lombok.SneakyThrows;
9 import lombok.extern.slf4j.Slf4j; 10 import lombok.extern.slf4j.Slf4j;
@@ -15,8 +16,6 @@ import org.apache.rocketmq.common.message.MessageExt; @@ -15,8 +16,6 @@ import org.apache.rocketmq.common.message.MessageExt;
15 import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties; 16 import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties;
16 import org.apache.rocketmq.spring.core.RocketMQTemplate; 17 import org.apache.rocketmq.spring.core.RocketMQTemplate;
17 18
18 -import jakarta.annotation.PreDestroy;  
19 -  
20 import java.lang.reflect.Type; 19 import java.lang.reflect.Type;
21 import java.util.ArrayList; 20 import java.util.ArrayList;
22 import java.util.List; 21 import java.util.List;
@@ -28,7 +27,7 @@ import java.util.List; @@ -28,7 +27,7 @@ import java.util.List;
28 */ 27 */
29 @RequiredArgsConstructor 28 @RequiredArgsConstructor
30 @Slf4j 29 @Slf4j
31 -public class RocketMQIotMessageBus implements IotMessageBus { 30 +public class IotRocketMQMessageBus implements IotMessageBus {
32 31
33 private final RocketMQProperties rocketMQProperties; 32 private final RocketMQProperties rocketMQProperties;
34 33
@@ -39,6 +38,21 @@ public class RocketMQIotMessageBus implements IotMessageBus { @@ -39,6 +38,21 @@ public class RocketMQIotMessageBus implements IotMessageBus {
39 */ 38 */
40 private final List<DefaultMQPushConsumer> topicConsumers = new ArrayList<>(); 39 private final List<DefaultMQPushConsumer> topicConsumers = new ArrayList<>();
41 40
  41 + /**
  42 + * 销毁时关闭所有消费者
  43 + */
  44 + @PreDestroy
  45 + public void destroy() {
  46 + for (DefaultMQPushConsumer consumer : topicConsumers) {
  47 + try {
  48 + consumer.shutdown();
  49 + log.info("[destroy][关闭 group({}) 的消费者成功]", consumer.getConsumerGroup());
  50 + } catch (Exception e) {
  51 + log.error("[destroy]关闭 group({}) 的消费者异常]", consumer.getConsumerGroup(), e);
  52 + }
  53 + }
  54 + }
  55 +
42 @Override 56 @Override
43 public void post(String topic, Object message) { 57 public void post(String topic, Object message) {
44 // TODO @芋艿:需要 orderly! 58 // TODO @芋艿:需要 orderly!
@@ -81,19 +95,4 @@ public class RocketMQIotMessageBus implements IotMessageBus { @@ -81,19 +95,4 @@ public class RocketMQIotMessageBus implements IotMessageBus {
81 topicConsumers.add(consumer); 95 topicConsumers.add(consumer);
82 } 96 }
83 97
84 - /**  
85 - * 销毁时关闭所有消费者  
86 - */  
87 - @PreDestroy  
88 - public void destroy() {  
89 - for (DefaultMQPushConsumer consumer : topicConsumers) {  
90 - try {  
91 - consumer.shutdown();  
92 - log.info("[destroy][关闭 group({}) 的消费者成功]", consumer.getConsumerGroup());  
93 - } catch (Exception e) {  
94 - log.error("[destroy]关闭 group({}) 的消费者异常]", consumer.getConsumerGroup(), e);  
95 - }  
96 - }  
97 - }  
98 -  
99 } 98 }
100 \ No newline at end of file 99 \ No newline at end of file
yudao-module-iot/yudao-module-iot-core/src/test/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/LocalIotMessageBusIntegrationTest.java
@@ -17,7 +17,7 @@ import java.util.concurrent.atomic.AtomicInteger; @@ -17,7 +17,7 @@ import java.util.concurrent.atomic.AtomicInteger;
17 import static org.junit.jupiter.api.Assertions.*; 17 import static org.junit.jupiter.api.Assertions.*;
18 18
19 /** 19 /**
20 - * {@link LocalIotMessageBus} 集成测试 20 + * {@link IotLocalMessageBus} 集成测试
21 * 21 *
22 * @author 芋道源码 22 * @author 芋道源码
23 */ 23 */
yudao-module-iot/yudao-module-iot-core/src/test/java/cn/iocoder/yudao/module/iot/core/messagebus/core/rocketmq/RocketMQIotMessageBusTest.java
@@ -21,7 +21,7 @@ import java.util.concurrent.atomic.AtomicReference; @@ -21,7 +21,7 @@ import java.util.concurrent.atomic.AtomicReference;
21 import static org.junit.jupiter.api.Assertions.*; 21 import static org.junit.jupiter.api.Assertions.*;
22 22
23 /** 23 /**
24 - * {@link RocketMQIotMessageBus} 集成测试 24 + * {@link IotRocketMQMessageBus} 集成测试
25 * 25 *
26 * @author 芋道源码 26 * @author 芋道源码
27 */ 27 */
yudao-module-iot/yudao-module-iot-gateway/src/main/resources/application-local.yaml
@@ -31,7 +31,7 @@ yudao: @@ -31,7 +31,7 @@ yudao:
31 # 针对引入的 EMQX 组件的配置 31 # 针对引入的 EMQX 组件的配置
32 # ==================================== 32 # ====================================
33 emqx: 33 emqx:
34 - enabled: true 34 + enabled: false
35 http-port: 8090 # MQTT HTTP 服务端口 35 http-port: 8090 # MQTT HTTP 服务端口
36 mqtt-host: 127.0.0.1 # MQTT Broker 地址 36 mqtt-host: 127.0.0.1 # MQTT Broker 地址
37 mqtt-port: 1883 # MQTT Broker 端口 37 mqtt-port: 1883 # MQTT Broker 端口
@@ -44,7 +44,7 @@ yudao: @@ -44,7 +44,7 @@ yudao:
44 44
45 # 消息总线配置 45 # 消息总线配置
46 message-bus: 46 message-bus:
47 - type: rocketmq # 本地开发使用 RocketMQ 47 + type: redis # 本地开发使用 RocketMQ
48 48
49 --- #################### 日志相关配置 #################### 49 --- #################### 日志相关配置 ####################
50 50
yudao-module-iot/yudao-module-iot-gateway/src/main/resources/application.yaml
@@ -37,14 +37,14 @@ yudao: @@ -37,14 +37,14 @@ yudao:
37 # 针对引入的 EMQX 组件的配置 37 # 针对引入的 EMQX 组件的配置
38 # ==================================== 38 # ====================================
39 emqx: 39 emqx:
40 - enabled: true 40 + enabled: false
41 mqtt-ssl: false 41 mqtt-ssl: false
42 mqtt-topics: 42 mqtt-topics:
43 - "/sys/#" # 系统主题 43 - "/sys/#" # 系统主题
44 44
45 # 消息总线配置 45 # 消息总线配置
46 message-bus: 46 message-bus:
47 - type: rocketmq # 消息总线的类型 47 + type: redis # 消息总线的类型
48 48
49 --- #################### 日志相关配置 #################### 49 --- #################### 日志相关配置 ####################
50 50
yudao-server/src/main/resources/application.yaml
@@ -313,6 +313,6 @@ yudao: @@ -313,6 +313,6 @@ yudao:
313 customer: E77DF18BE109F454A5CD319E44BF5177 313 customer: E77DF18BE109F454A5CD319E44BF5177
314 iot: 314 iot:
315 message-bus: 315 message-bus:
316 - type: rocketmq # 消息总线的类型 316 + type: redis # 消息总线的类型
317 317
318 debug: false 318 debug: false
319 \ No newline at end of file 319 \ No newline at end of file