【Flink实战】Flink中的分流

Flink中的分流

在Flink中将数据流切分为多个子数据流,子数据流称为”旁路输出数据流“。

拆分流
正常处理
异常处理
数据读取
合法入库
异常监控

拆分流数据的方式

  • Split,已经废弃,不推荐使用
  • Fliter
  • SideOut,推荐使用

Fliter分流的Java实现

    public static void main(String[] args) throws Exception {
        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // 指标明细
        DataStream<String> detailMessage = KafkaConfigUtil.buildSource(env)
                .map((MapFunction<String, String>) kafkaMessage -> {
                    JSONObject jsonobject = null;
                    try {
                        jsonobject = JSONObject.parseObject(kafkaMessage);
                    } catch (Exception e) {
                        LOG.warn("报文格式错误:{}", kafkaMessage);
                    }
                    if (null == jsonobject || jsonobject.isEmpty()) {
                        LOG.warn("报文内容不合法:{}", JSONObject.toJSONString(jsonobject));
                    } else {
                        if (!EventsServiceEnum.MapReduce.getValue().equals(jsonobject.get("service"))
                                && !EventsServiceEnum.Spark.getValue().equals(jsonobject.get("service"))) {
                            LOG.warn("报文所属服务不存在:{}", JSONObject.toJSONString(jsonobject));
                        }
                    }
                    return JSONObject.toJSONString(jsonobject);
                });
        // 将原始流中包含demo的数据筛选出来
        DataStream<String> diagnosisMessages = detailMessage
                .filter((FilterFunction<String>) kafkaMessage -> (kafkaMessage.contains("demo")))
                .map((MapFunction<String, String>) sparkMessage -> {
                    // 为达到实验效果,进行日志输出
                    LOG.info("[is demo message]:{}", sparkMessage);
                    return sparkMessage;
                });

        env.execute("Flink Streaming Java API Skeleton");
    }

SideOut分流的Java实现

    public static void main(String[] args) throws Exception {
        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        System.out.println("【SideOutputDemo】");
        
        // 指标明细
        DataStream<String> mainMessage = KafkaConfigUtil.buildSource(env)
                .map((MapFunction<String, String>) kafkaMessage -> {
                    JSONObject jsonobject = null;
                    try {
                        jsonobject = JSONObject.parseObject(kafkaMessage);
                    } catch (Exception e) {
                        LOG.warn("报文格式错误:{}", kafkaMessage);
                    }
                    if (null == jsonobject || jsonobject.isEmpty()) {
                        LOG.warn("报文内容不合法:{}", JSONObject.toJSONString(jsonobject));
                    } else {
                        if (!EventsServiceEnum.MapReduce.getValue().equals(jsonobject.get("service"))
                                && !EventsServiceEnum.Spark.getValue().equals(jsonobject.get("service"))) {
                            LOG.warn("报文所属服务不存在:{}", JSONObject.toJSONString(jsonobject));
                        }
                    }
                    return JSONObject.toJSONString(jsonobject);
                });

        // 定义一个切分(旁路输出)
        final OutputTag<String> outputTag = new OutputTag<String>("Spark_END") {
        };

        SingleOutputStreamOperator<String> sp = mainMessage
                .process(new ProcessFunction<String, String>() {
                    @Override
                    public void processElement(
                            String s
                            , Context context
                            , Collector<String> collector) throws Exception {
                        // 向常规流(主流)中添加数据
                        collector.collect(s);
                        // 向旁路输出流中添加数据
                        if (s.contains(AppPhaseEnum.Spark_APP_End.getValue())) {
                            context.output(outputTag, s);
                        }
                    }
                });
        sp.map((MapFunction<String, String>) sparkMessage -> {
            LOG.info("主流的数据: {}", sparkMessage);
            return sparkMessage;
        });

        DataStream<String> tag = sp.getSideOutput(outputTag);
        tag.map((MapFunction<String, String>) sparkMessage -> {
            LOG.info("旁路[{}]的数据: {}", outputTag.getId(), sparkMessage);
            return sparkMessage;
        });

        env.execute("Flink Streaming Java API Skeleton");
    }

SideOutPut 是 Flink 框架推荐的分流方法,在使用 SideOutPut 时,需要按照以下步骤进行:

  1. 为每个分支流定义一个 SideOutPut。

  2. 为定义好的 SideOutPut发出数据。只有以下特定的函数才能通过Context上下文对象,向旁路输出的SideOutPut发送数据。

    1. ProcessFunction:处理函数,单流输入函数
    2. KeyedProcessFunction:处理函数,单流输入函数
    3. CoProcessFunction:处理函数,双流流输入函数
    4. KeyedCoProcessFunction:处理函数,双流流输入函数
    5. ProcessWindowFunction:窗口函数,全量计算函数
    6. ProcessAllWindowFunction:窗口函数,全量计算函数,它与 ProcessWindowFunction 类似,但是它会对窗口中的所有数据进行处理,而不是仅处理触发窗口计算的数据。

    例子中使用ProcessFunction实现流拆分。

  3. 根据SideOutPut 的ID标识获取旁路输出流,进行数据继续处理。

拆分方式对比
Split不支持链式拆分,切分得到的流,是不能进行再次切分的
Fliter多分支流,需要多次遍历原始流进行筛选。浪费集群的资源
SideOut以多次进行拆分的,支持链式拆分。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Flink是一个用于对无界和有界数据进行有状态计算的开源处理框架。它被设计在所有常见的集群环境运行,以内存执行速度和任意规模来执行计算。Flink的重要特点之一是事件驱动型应用,它从一个或多个事件提取数据,并根据到来的事件触发计算、状态更新或其他外部动作。与Spark Streaming的微批次不同,Flink是基于事件的处理模式。\[1\] 在使用Flink进行实战时,可以使用Java编写代码。首先,需要在Maven构建加入Flink的依赖,包括flink-javaflink-clients。然后,可以编写Java代码来实现具体的Flink应用,比如WordCount。\[3\] 在配置文件flink-conf.yaml,可以修改classloader.check-leaked-classloader为false来禁用类加载器泄漏检查。然后,可以使用命令行工具flink run来提交Flink应用,使用yarn-per-job模式来在YARN上运行。需要指定主类和应用的jar包路径。\[2\] 总结起来,Flink是一个用于处理的开源框架,可以使用Java编写实战代码,并通过命令行工具在YARN上运行。 #### 引用[.reference_title] - *1* [JavaFlink原理、实战、源码分析(一)原理部分](https://blog.csdn.net/qq_36250202/article/details/112978869)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [flink经典实战案例](https://blog.csdn.net/qq_46447060/article/details/120025923)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顧棟

若对你有帮助,望对作者鼓励一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值