• Flink 合流操作——Connect


    流的联合虽然简单,不过受限于数据类型不能改变,灵活性大打折扣,所以实际应用较少出现。除了联合(union),Flink还提供了另外一种方便的合流操作——连接(connect)。顾名思义,这种操作就是直接把两条流像接线一样对接起来

    1、连接流(ConnectedStreams)

    为了处理更加灵活,连接操作允许流的数据类型不同。但我们知道一个DataStream中的数据只能有唯一的类型,所以连接得到的并不是DataStream,而是一个“连接流”(ConnectedStreams)。连接流可以看成是两条流形式上的“统一”,被放在了一个同一个流中;事实上内部仍保持各自的数据形式不变,彼此之间是相互独立的。要想得到新的DataStream,还需要进一步定义一个“同处理”(co-process)转换操作,用来说明对于不同来源、不同类型的数据,怎样分别进行处理转换、得到统一的输出类型。所以整体上来,两条流的连接就像是“一国两制”,两条流可以保持各自的数据类型、处理方式也可以不同,不过最终还是会统一到同一个DataStream中。

    在代码实现上,需要分为两步:首先基于一条DataStream调用.connect()方法,传入另外一条DataStream作为参数,将两条流连接起来,得到一个ConnectedStreams;然后再调用同处理方法得到DataStream。这里可以的调用的同处理方法有.map()/.flatMap(),以及.process()方法

    参考代码

    public class ConnectStreamTest {
        public static void main(String[] args) throws Exception {
            //1、获取执行环境
            StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
            //1.1、便于测试设置并行度为1,生产环境应该设置为kafka topic de 分区数
            env.setParallelism(1);
            //2、读取数据
            DataStreamSource<Integer> integerStream = env.fromElements(1, 2, 3);
            DataStreamSource<Long> LongStream = env.fromElements(4L, 5L, 6L, 7L);
            //3、进行连接并 实现 CoxxxFunction
            LongStream.connect(integerStream).map(new CoMapFunction<Long, Integer, String>() {
                @Override
                public String map1(Long value) throws Exception {
                    return " long " + value.toString();
                }
    
                @Override
                public String map2(Integer value) throws Exception {
                    return " Integer " + value.toString();
                }
            }).print();
            //4、开启任务
            env.execute();
        }
    }

    运行效果

     long 4
     Integer 1
     long 5
     Integer 2
     long 6
     Integer 3
     long 7
    
    Process finished with exit code 0

    上面的代码中,ConnectedStreams有两个类型参数,分别表示内部包含的两条流各自的数据类型;由于需要“一国两制”,因此调用.map()方法时传入的不再是一个简单的MapFunction,而是一个CoMapFunction,表示分别对两条流中的数据执行map操作。这个接口有三个类型参数,依次表示第一条流、第二条流,以及合并后的流中的数据类型。需要实现的方法也非常直白:.map1()就是对第一条流中数据的map操作,.map2()则是针对第二条流。这里我们将一条Integer流和一条Long流合并,转换成String输出。所以当遇到第一条流输入的整型值时,调用.map1();而遇到第二条流输入的长整型数据时,调用.map2():最终都转换为字符串输出,合并成了一条字符串流。值得一提的是,ConnectedStreams也可以直接调用.keyBy()进行按键分区的操作,得到的还是一个ConnectedStreams

    connectedStreams.keyBy(keySelector1, keySelector2);
    这里传入两个参数keySelector1和keySelector2,是两条流中各自的键选择器;当然也可以直接传入键的位置值(keyPosition),或者键的字段名(field),这与普通的keyBy用法完全一致。ConnectedStreams进行keyBy操作,其实就是把两条流中key相同的数据放到了一起,然后针对来源的流再做各自处理,这在一些场景下非常有用。另外,我们也可以在合并之前就将两条流分别进行keyBy,得到的KeyedStream再进行连接(connect)操作,效果是一样的。要注意两条流定义的键的类型必须相同,否则会抛出异常。两条流的连接(connect),与联合(union)操作相比,最大的优势就是可以处理不同类型的流的合并,使用更灵活、应用更广泛。当然它也有限制,就是合并流的数量只能是2,而union可以同时进行多条流的合并。这也非常容易理解:union限制了类型不变,所以直接合并没有问题;而connect是“一国两制”,后续处理的接口只定义了两个转换方法,如果扩展需要重新定义接口,所以不能“一国多制”。
  • 相关阅读:
    《Three.js 入门指南》3.1.1
    《Three.js 入门指南》3.1.1
    《Three.js 入门指南》3.1.1
    《Three.js 入门指南》3.1.1
    《Three.js 入门指南》3.1.1
    《Three.js 入门指南》3.0
    《Three.js 入门指南》2.4.1- 照相机
    《Three.js 入门指南》2.3.1- 照相机
    《Three.js 入门指南》2- 照相机
    《Three.js 入门指南》1.3
  • 原文地址:https://www.cnblogs.com/wdh01/p/16643167.html
Copyright © 2020-2023  润新知