Flink CEP 空气质量监控案例

本文介绍了一个使用 Apache Flink CEP 进行空气质量监测的应用案例。通过从 Kafka 消费数据,定义复杂的事件模式来识别空气质量的变化趋势,并对不同类型的预警进行分类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载至 about 云 http://www.aboutyun.com/thread-27487-1-1.html 

实际业务场景代码会比这个复制,但是类似............

 

package wang.datahub.cep;
import org.apache.flink.api.java.utils.ParameterTool;
import org.apache.flink.cep.CEP;
import org.apache.flink.cep.PatternStream;
import org.apache.flink.cep.pattern.Pattern;
import org.apache.flink.cep.pattern.conditions.IterativeCondition;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010;
import wang.datahub.cep.event.AirQualityRecoder;
import wang.datahub.cep.event.AirWarningRecoder;
import wang.datahub.cep.event.AirWarningTypeRecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CepApp {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        Map properties= new HashMap();
        properties.put("bootstrap.servers", "localhost:9092");
        properties.put("group.id", "test");
        properties.put("enable.auto.commit", "true");
        properties.put("auto.commit.interval.ms", "1000");
        properties.put("auto.offset.reset", "earliest");
        properties.put("session.timeout.ms", "30000");
//        properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
//        properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        properties.put("topic", "test1");
        ParameterTool parameterTool = ParameterTool.fromMap(properties);
        FlinkKafkaConsumer010 consumer010 = new FlinkKafkaConsumer010(
                parameterTool.getRequired("topic"), new WriteIntoKafka.SimpleAirQualityRecoderSchema(), parameterTool.getProperties());
        DataStream<AirQualityRecoder> aqrStream = env
                .addSource(consumer010);
        Pattern<AirQualityRecoder, ?> warningPattern = Pattern.<AirQualityRecoder>begin("first")
                .subtype(AirQualityRecoder.class)
                .where(new IterativeCondition<AirQualityRecoder>(){
                    @Override
                    public boolean filter(AirQualityRecoder value, Context<AirQualityRecoder> ctx) throws Exception {
                        return value.getAirQuality() >= 6;
                    }
                }).or(new IterativeCondition<AirQualityRecoder>(){
                    @Override
                    public boolean filter(AirQualityRecoder value, Context<AirQualityRecoder> ctx) throws Exception {
                        return value.getAirQuality() <= 3;
                    }
                })
 
                .next("second")
                .where(new IterativeCondition<AirQualityRecoder>(){
                    @Override
                    public boolean filter(AirQualityRecoder value, Context<AirQualityRecoder> ctx) throws Exception {
                        return value.getAirQuality() >= 7;
                    }
                }).or(new IterativeCondition<AirQualityRecoder>(){
                    @Override
                    public boolean filter(AirQualityRecoder value, Context<AirQualityRecoder> ctx) throws Exception {
                        return value.getAirQuality() <= 2;
                    }
                })
                .within(Time.seconds(60))
                ;
        PatternStream<AirQualityRecoder> warningPatternStream = CEP.pattern(
                aqrStream.keyBy("city"),//"city"
                warningPattern);
        DataStream<AirWarningRecoder> warnings = warningPatternStream.select(
                (Map<String, List<AirQualityRecoder>> pattern) -> {
                    AirQualityRecoder first = (AirQualityRecoder) pattern.get("first").get(0);
                    AirQualityRecoder second = (AirQualityRecoder) pattern.get("second").get(0);
                    return new AirWarningRecoder(first.getCity(),first,second);
                }
        );
        Pattern<AirWarningRecoder, ?> typePattern = Pattern.<AirWarningRecoder>begin("pass")
                .subtype(AirWarningRecoder.class);
                
        PatternStream<AirWarningRecoder> typePatternStream = CEP.pattern(
                warnings.keyBy(AirWarningRecoder::getCity),
                typePattern
        );
        DataStream<AirWarningTypeRecoder> awt = typePatternStream.select(
                (Map<String, List<AirWarningRecoder>> pattern) -> {
                    AirWarningRecoder awr = (AirWarningRecoder) pattern.get("pass").get(0);
                    AirWarningTypeRecoder awtr = new AirWarningTypeRecoder();
                    awtr.setCity(awr.getCity());
                    awtr.setFirst(awr.getFirst().getAirQuality());
                    awtr.setSecond(awr.getSecond().getAirQuality());
                    int res = Math.abs(awtr.getFirst()-awtr.getSecond());
                    if(res <=2){
                        awtr.setWtype("质量超标");
                    }else{
                        awtr.setWtype("波动较大");
                    }
 
                    return awtr;
                }
        );
        warnings.print();
        awt.print();
        env.execute("cep run!!!");
    }
}

 

 

### Flink CEP 实际应用案例 #### 使用场景一:异常温度检测 在一个工业监控系统中,为了确保设备安全运行,需要实时监测环境温度。当在三分钟内出现三次及以上温度超过40摄氏度的情况时,则触发警报机制[^2]。 ```java // 定义输入数据源 DataStream<TemperatureEvent> temperatureStream = ...; // 创建Pattern用于定义匹配条件 Pattern<TemperatureEvent, ?> pattern = Pattern.<TemperatureEvent>begin("start") .where(new SimpleCondition<TemperatureEvent>() { @Override public boolean filter(TemperatureEvent value) throws Exception { return value.getTemperature() > 40; } }) .timesOrMore(3) .within(Time.minutes(3)); // 应用模式到事件流上并设置处理逻辑 PatternStream<TemperatureEvent> patternStream = CEP.pattern(temperatureStream.keyBy(event -> event.sensorId), pattern); patternStream.flatSelect((FlatSelectFunction<Map<String, TemperatureEvent>, String>) (map, out) -> out.collect("Warning: Abnormal high temperatures detected within three minutes.") ); ``` #### 场景二:电商订单管理 对于电商平台而言,在线支付环节至关重要。如果客户下单后十五分钟内未完成付款操作,则该笔交易应被自动取消以释放库存资源。 ```java // 假设存在两个不同的数据流分别表示新创建的订单以及对应的支付状态更新记录 DataStream<OrderCreatedEvent> orderEvents = ...; DataStream<PaymentStatusChangedEvent> paymentEvents = ...; // 合并两条不同类型的日志消息成为一条联合的日志项 ConnectedStreams<OrderCreatedEvent, PaymentStatusChangedEvent> connectedStreams = orderEvents.connect(paymentEvents); KeyedProcessFunction<Long, CoTuple2<OrderCreatedEvent, Optional<PaymentStatusChangedEvent>>, String> processFunc = new KeyedProcessFunction<>() { private ValueState<Boolean> isPaid; @Override public void open(Configuration parameters) throws Exception { isPaid = getRuntimeContext().getState( new ValueStateDescriptor<>("is-paid", Types.BOOLEAN)); } @Override public void processElement(CoTuple2<OrderCreatedEvent, Optional<PaymentStatusChangedEvent>> element, Context context, Collector<String> collector) throws Exception { Long orderId = element.f0.orderId(); if (!element.f1.isPresent()) { // 当收到的是OrderCreatedEvent而非PaymentStatusChangedEvent时执行此分支 TimerService timerService = context.timerService(); long currentTimeMillis = System.currentTimeMillis(); final long fifteenMinutesLaterTimestamp = currentTimeMillis + TimeUnit.MINUTES.toMillis(15L); timerService.registerProcessingTimeTimer(fifteenMinutesLaterTimestamp); collector.collect(String.format("New Order Created with ID %d.", orderId)); } else { // 收到了PaymentStatusChangedEvent说明已经完成了支付动作 Boolean paidFlag = true; isPaid.update(paidFlag); collector.collect(String.format("Order Paid Successfully for ID %d.", orderId)); } if(isPaid.value()){ context.timerService().deleteProcessingTimeTimer(context.timestamp()); } } @Override public void onTimer(long timestamp, OnTimerContext ctx, Collector<String> out) throws Exception { Long orderId = ((CoTuple2<OrderCreatedEvent, Optional<PaymentStatusChangedEvent>>)ctx.getCurrentKey()).f0.orderId(); if(!isPaid.value()){ out.collect(String.format("Canceling Unpaid Order after 15 Minutes Timeout. OrderID=%d", orderId)); } } }; connectedStreams.process(processFunc).print(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值