从零开始搭建flink流式计算项目-2小试牛刀-物联网场景下,如何实现设备采集参数监控报警功能


##### 监控报警规则 `alarmRule`



/**
* 报警规则
*/
@Data
public class AlarmRule {

/\*\*

* 规则ID
*/
private Integer id;

/\*\*

* 设备ID
*/
private Integer deviceId;

/\*\*

* 监控的变量名称
*/
private String varName;

/\*\*

* 最小值
*/
private Double min;

/\*\*

* 最大值
*/
private Double max;

}


##### 报警事件



/**
* 报警消息
*/
@Data
public class AlarmMessage {

/\*\*

* 设备
*/
private Integer deviceId;

/\*\*

* 报警时间
*/
private Long timestamp;
/**
* 触发报警的采集变量名称
*/
private String alarmVar;

/\*\*

* 触发报警的采集值
*/
private Number alarmValue;
}


#### 开始实现



public class IotMonitorJob {

public static void main(String[] args) throws Exception {


    StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment();
    environment.setParallelism(1);

    // 采集数据Stream
    DataStreamSource<IotData> iotDataStream = getIotStream(environment);
    // 报警规则Stream
    DataStreamSource<AlarmRule> ruleConfig = getRuleConfig(environment);
    // 缓存报警规则 并监控报警数据
    SingleOutputStreamOperator<AlarmMessage> alarmStream = iotDataStream.connect(ruleConfig)
            .keyBy(IotData::getDeviceId, AlarmRule::getDeviceId)
            .process(new CoProcessFunction<IotData, AlarmRule, AlarmMessage>() {

                // 用临时保存设备的报警规则 ,这里的状态交由flink维护
                private MapState<Integer, AlarmRule> alarmRuleValueState;

                @Override
                public void open(Configuration parameters) throws Exception {
                    super.open(parameters);
                    // 初始化 ValueState
                    alarmRuleValueState = getRuntimeContext().getMapState(new MapStateDescriptor<>("alarm-rule-state", Integer.class, AlarmRule.class));
                }

                @Override
                public void processElement1(IotData iotData, CoProcessFunction<IotData, AlarmRule, AlarmMessage>.Context context, Collector<AlarmMessage> collector) throws Exception {
                    Map<String, Double> data = iotData.getData();

                    // 遍历每个规则
                    alarmRuleValueState.values().forEach(rule -> {

                        String varName = rule.getVarName();
                        // 获取变量值
                        Double val = data.get(varName);
                        if (val == null) {
                            // 变量里没有值
                            return;
                        }

                        if (val <= rule.getMin() || val > rule.getMax()) {
                            // 超过限制,输出报警信息
                            AlarmMessage alarmMessage = new AlarmMessage();
                            alarmMessage.setDeviceId(iotData.getDeviceId());
                            alarmMessage.setTimestamp(iotData.getTimestamp());
                            alarmMessage.setAlarmVar(varName);
                            alarmMessage.setAlarmValue(val);
                            collector.collect(alarmMessage);
                        }
                    });


                }

                @Override
                public void processElement2(AlarmRule alarmRule, CoProcessFunction<IotData, AlarmRule, AlarmMessage>.Context context, Collector<AlarmMessage> collector) throws Exception {
                    // 接收到AlarmRule, 仅更新 alarmRuleValueState
                    alarmRuleValueState.put(alarmRule.getId(), alarmRule);
                }
            });


    alarmStream.print();
    environment.execute();
}

/\*\*

* 获取物联采集数据
*
* @param environment
* @return
*/
private static DataStreamSource getIotStream(StreamExecutionEnvironment environment) {
return environment.addSource(new SourceFunction<>() {
private boolean running = true;

        @Override
        public void run(SourceContext<IotData> sourceContext) throws Exception {
            while (running) {

                // 模拟100个设备 每秒一次上报数据

                long ts = System.currentTimeMillis();
                ts = ts - ts % 1000;

                for (int i = 0; i < 100; i++) {
                    IotData iotData = new IotData();
                    iotData.setTimestamp(ts);
                    iotData.setDeviceId(i);

                    Map<String, Double> data = new HashMap<>();
                    data.put("var1", RandomUtils.nextDouble());
                    data.put("var2", RandomUtils.nextDouble());
                    iotData.setData(data);

                    sourceContext.collect(iotData);
                }

                Thread.sleep(1000 - ts % 1000);
            }
        }

        @Override
        public void cancel() {
            running = false;
        }
    });
}


/\*\*

* 获取规则配置
*/
public static DataStreamSource getRuleConfig(StreamExecutionEnvironment environment) {
// 仅针对部分设备监控

    List<AlarmRule> ruleList = new ArrayList<>();
    for (int i = 0; i < 20; i++) {
        AlarmRule alarmRule1 = new AlarmRule();
        alarmRule1.setDeviceId(i);
        alarmRule1.setVarName("var1");
        alarmRule1.setMax(20.0);
        alarmRule1.setMin(0.0);
        ruleList.add(alarmRule1);

        AlarmRule alarmRule2 = new AlarmRule();
        alarmRule2.setDeviceId(i);
        alarmRule2.setVarName("var2");
        alarmRule2.setMax(10.0);
        alarmRule2.setMin(0.0);
        ruleList.add(alarmRule2);

    }
    return environment.fromCollection(ruleList);
}

}


### 启动job



![img](https://img-blog.csdnimg.cn/img_convert/c89617a673c65356f61381eb1a0f98d6.png)
![img](https://img-blog.csdnimg.cn/img_convert/19b9c278226cf26a9682f3ced36f1613.png)
![img](https://img-blog.csdnimg.cn/img_convert/3921ccfce1c9d8c0c23cac9444c21459.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

.(img-c29JDESq-1714284358986)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值