Commit c6b58b0ebfbfdac305f8ae9d32de6156faba8131
1 parent
6a1798bf
【代码评审】IoT:数据桥梁实现
Showing
5 changed files
with
19 additions
and
14 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/AbstractCacheableDataBridgeExecute.java
| ... | ... | @@ -7,12 +7,7 @@ import lombok.extern.slf4j.Slf4j; |
| 7 | 7 | |
| 8 | 8 | import java.time.Duration; |
| 9 | 9 | |
| 10 | -// TODO @芋艿:因为下面的,都是有状态的,所以通过 guava 缓存连接,然后通过 RemovalNotification 实现关闭。例如说,一次新建有效期是 10 分钟; | |
| 11 | -// TODO @芋艿:mq-redis | |
| 12 | -// TODO @芋艿:mq-数据库 | |
| 13 | -// TODO @芋艿:kafka | |
| 14 | -// TODO @芋艿:rocketmq | |
| 15 | -// TODO @芋艿:rabbitmq | |
| 10 | +// TODO @芋艿:数据库 | |
| 16 | 11 | // TODO @芋艿:mqtt |
| 17 | 12 | // TODO @芋艿:tcp |
| 18 | 13 | // TODO @芋艿:websocket |
| ... | ... | @@ -25,6 +20,7 @@ import java.time.Duration; |
| 25 | 20 | @Slf4j |
| 26 | 21 | public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridgeExecute { |
| 27 | 22 | |
| 23 | + // TODO @huihui:AbstractCacheableDataBridgeExecute<Producer> 这样,下面的 Object, Object 就有了类型;另外 IotDataBridgeDO.Config 可以替代一个 Object 哇, | |
| 28 | 24 | /** |
| 29 | 25 | * Producer 缓存 |
| 30 | 26 | */ |
| ... | ... | @@ -43,12 +39,14 @@ public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridg |
| 43 | 39 | } |
| 44 | 40 | }) |
| 45 | 41 | .build(new CacheLoader<Object, Object>() { |
| 42 | + | |
| 46 | 43 | @Override |
| 47 | 44 | public Object load(Object config) throws Exception { |
| 48 | 45 | Object producer = initProducer(config); |
| 49 | 46 | log.info("[PRODUCER_CACHE][配置({}) 对应的 producer 已创建并启动]", config); |
| 50 | 47 | return producer; |
| 51 | 48 | } |
| 49 | + | |
| 52 | 50 | }); |
| 53 | 51 | |
| 54 | 52 | /** |
| ... | ... | @@ -77,4 +75,4 @@ public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridg |
| 77 | 75 | */ |
| 78 | 76 | protected abstract void closeProducer(Object producer); |
| 79 | 77 | |
| 80 | -} | |
| 81 | 78 | \ No newline at end of file |
| 79 | +} | |
| 82 | 80 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotDataBridgeExecute.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotKafkaMQDataBridgeExecute.java
| ... | ... | @@ -10,6 +10,7 @@ import org.springframework.kafka.core.DefaultKafkaProducerFactory; |
| 10 | 10 | import org.springframework.kafka.core.KafkaTemplate; |
| 11 | 11 | import org.springframework.stereotype.Component; |
| 12 | 12 | |
| 13 | +import java.time.Duration; | |
| 13 | 14 | import java.time.LocalDateTime; |
| 14 | 15 | import java.util.HashMap; |
| 15 | 16 | import java.util.Map; |
| ... | ... | @@ -25,13 +26,15 @@ import java.util.concurrent.TimeoutException; |
| 25 | 26 | @Slf4j |
| 26 | 27 | public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExecute { |
| 27 | 28 | |
| 29 | + private static final Duration SEND_TIMEOUT = Duration.ofMillis(10); | |
| 30 | + | |
| 28 | 31 | @Override |
| 29 | 32 | public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) { |
| 30 | - // 1.1 校验数据桥梁的类型 == KAFKA | |
| 33 | + // 1. 校验数据桥梁的类型 == KAFKA | |
| 31 | 34 | if (!IotDataBridgTypeEnum.KAFKA.getType().equals(dataBridge.getType())) { |
| 32 | 35 | return; |
| 33 | 36 | } |
| 34 | - // 1.2 执行 Kafka 发送消息 | |
| 37 | + // 2. 执行 Kafka 发送消息 | |
| 35 | 38 | executeKafka(message, (IotDataBridgeDO.KafkaMQConfig) dataBridge.getConfig()); |
| 36 | 39 | } |
| 37 | 40 | |
| ... | ... | @@ -43,7 +46,7 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec |
| 43 | 46 | |
| 44 | 47 | // 2. 发送消息并等待结果 |
| 45 | 48 | kafkaTemplate.send(config.getTopic(), message.toString()) |
| 46 | - .get(10, TimeUnit.SECONDS); // 添加超时等待 | |
| 49 | + .get(SEND_TIMEOUT.getSeconds(), TimeUnit.SECONDS); // 添加超时等待 | |
| 47 | 50 | log.info("[executeKafka][message({}) 发送成功]", message); |
| 48 | 51 | } catch (TimeoutException e) { |
| 49 | 52 | log.error("[executeKafka][message({}) config({}) 发送超时]", message, config, e); |
| ... | ... | @@ -55,13 +58,12 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec |
| 55 | 58 | @Override |
| 56 | 59 | protected Object initProducer(Object config) { |
| 57 | 60 | IotDataBridgeDO.KafkaMQConfig kafkaConfig = (IotDataBridgeDO.KafkaMQConfig) config; |
| 58 | - | |
| 61 | + | |
| 59 | 62 | // 1.1 构建生产者配置 |
| 60 | 63 | Map<String, Object> props = new HashMap<>(); |
| 61 | 64 | props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaConfig.getBootstrapServers()); |
| 62 | 65 | props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); |
| 63 | 66 | props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); |
| 64 | - | |
| 65 | 67 | // 1.2 如果配置了认证信息 |
| 66 | 68 | if (kafkaConfig.getUsername() != null && kafkaConfig.getPassword() != null) { |
| 67 | 69 | props.put("security.protocol", "SASL_PLAINTEXT"); |
| ... | ... | @@ -70,7 +72,6 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec |
| 70 | 72 | "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"" |
| 71 | 73 | + kafkaConfig.getUsername() + "\" password=\"" + kafkaConfig.getPassword() + "\";"); |
| 72 | 74 | } |
| 73 | - | |
| 74 | 75 | // 1.3 如果启用 SSL |
| 75 | 76 | if (Boolean.TRUE.equals(kafkaConfig.getSsl())) { |
| 76 | 77 | props.put("security.protocol", "SSL"); | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRabbitMQDataBridgeExecute.java
| ... | ... | @@ -51,6 +51,7 @@ public class IotRabbitMQDataBridgeExecute extends AbstractCacheableDataBridgeExe |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | 53 | @Override |
| 54 | + @SuppressWarnings("resource") | |
| 54 | 55 | protected Object initProducer(Object config) throws Exception { |
| 55 | 56 | IotDataBridgeDO.RabbitMQConfig rabbitConfig = (IotDataBridgeDO.RabbitMQConfig) config; |
| 56 | 57 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamMQDataBridgeExecute.java
| ... | ... | @@ -42,6 +42,7 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | @SuppressWarnings("unchecked") |
| 45 | + // TODO @huihui:try catch 交给父类来做,子类不处理异常 | |
| 45 | 46 | private void executeRedisStream(IotDeviceMessage message, IotDataBridgeDO.RedisStreamMQConfig config) { |
| 46 | 47 | try { |
| 47 | 48 | // 1. 获取 RedisTemplate |
| ... | ... | @@ -71,6 +72,7 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid |
| 71 | 72 | serverConfig.setPassword(redisConfig.getPassword()); |
| 72 | 73 | } |
| 73 | 74 | |
| 75 | + // TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。 | |
| 74 | 76 | // 2.1 创建 RedissonClient |
| 75 | 77 | RedissonClient redisson = Redisson.create(redissonConfig); |
| 76 | 78 | // 2.2 创建并配置 RedisTemplate |
| ... | ... | @@ -89,6 +91,7 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid |
| 89 | 91 | |
| 90 | 92 | @Override |
| 91 | 93 | protected void closeProducer(Object producer) { |
| 94 | + // TODO @huihui:try catch 交给父类来做。子类不处理异常 | |
| 92 | 95 | if (producer instanceof RedisTemplate) { |
| 93 | 96 | RedisConnectionFactory factory = ((RedisTemplate<?, ?>) producer).getConnectionFactory(); |
| 94 | 97 | try { |
| ... | ... | @@ -101,7 +104,7 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid |
| 101 | 104 | } |
| 102 | 105 | } |
| 103 | 106 | |
| 104 | - | |
| 107 | + // TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。 | |
| 105 | 108 | public static RedisSerializer<?> buildRedisSerializer() { |
| 106 | 109 | RedisSerializer<Object> json = RedisSerializer.json(); |
| 107 | 110 | // 解决 LocalDateTime 的序列化 | ... | ... |