flink的DataStreamAPI

一、WordCount流程

 1 import org.apache.flink.streaming.api.scala._
 2 
 3 object StreamWordCount {
 4   def main(args:Array[String]):Unit={
 5     //创建流处理的执行环境
 6     val env=StreamExecutionEnvironment.getExecutionEnvironment;
 7 
 8     //接受一个socket文本流即创建数据源
 9     val dataStream=env.socketTextStream("localhost",7777);
10 
11     //对每条数据进行处理
12     val wordCountDataStream=dataStream.flatMap(_.split(" "))
13       .filter(_.nonEmpty)
14       .map(line=>(line,1))
15       .keyBy(line=>line._1)
16       .sum(1);
17    //输出结果,可以直接输出也可以将处理的结果存储到外部系统中如kafka
18     wordCountDataStream.print();
19     //flink的操作是惰性的,需要启动executor。
20     env.execute("stream WC job")
21   }
22 }

二、流程解析:env —> transform —> source

(1)创建环境Environment

  1、getExecutionEnvironment:创建一个执行环境,表示当前执行程序的上下文。 如果程序是独立调用的,则此方法返回本地执行环境;如果从命令行客户端调用程序以提交到集群,则此方法返回此集群的执行环境,getExecutionEnvironment会根据查询运行的方式决定返回什么样的运行环境,是最常用的一种创建执行环境的方式。

  val env= ExecutionEnvironment.getExecutionEnvironment,如果没有设置并行度,会以flink-conf.yaml中的配置为准,默认是1。

  2、createLocalEnvironment:返回本地执行环境,需要在调用时指定默认的并行度。

  val env = StreamExecutionEnvironment.createLocalEnvironment(1),返回本地执行环境,需要在调用时指定默认的并行度。

  3、createRemoteEnvironment:返回集群执行环境,将Jar提交到远程服务器。需要在调用时指定JobManager的IP和端口号,并指定要在集群中运行的Jar包。

  val env = ExecutionEnvironment.createRemoteEnvironment("jobmanager-hostname", 6123,"C://jar//flink//wordcount.jar")

(2)source

  1、基于集合的source

   1)val dataStream1=env.fromElements("spark", "flink")

   2)val dataStream2=env.fromCollection(Array("spark", "flink"))

  2、基于文件的source

   1)读取本地文件:val stream1= env.readTextFile("data2.csv")

   2)读取HDFS文件:val stream2=env.readTextFile("hdfs://hadoop:9000/input/flink/README.txt")

  3、基于网络套接字的source:val dataStream=env.socketTextStream("localhost",7777)

  4、自定义的source

   1)创建kafka数据流:val kafka09 = new FlinkKafkaConsumer09[String](kafkaTopicName,new SimpleStringSchema(), properties)

   2)将kafka数据流当成:添加数据源addSource(kafka09):val text = env.addSource(kafka09).setParallelism(4)

(3)transform算子操作

  1、map:val streamMap = stream.map { x => x * 2 }

  2、flatMap:val streamFlatMap = stream.flatMap(x=>x.split(",")) //花括号与小括号均可以。

  3、filter:val streamFilter=stream.filter(x=>x%2==1)

  4、keyBy:DataSet 中使用 groupBy 指定 key,而在 DataStream 中使用 keyBy 指定 key,DataStream → KeyedStream:逻辑上将一个流拆分成不相交的分区,每个分区包含具有相同hash(key)的元素,把所有相同key的数据聚合在一起。keyBy指定key的三种方法

   1)根据字段位置keyBy(0),主要对tuple类型,pojo类会出错,注意:这个是相对于最外元素而言。对于tuple类型还可以指定key的位置keyBy(x=>x._1)

   2)根据字段名称,主要是pojo类。stream.map(x=>Person(x,2)).keyBy("name"),也可以多字段分区如keyBy("name","age")

   3)自定义keyselector

  5、Reduce:KeyedStream → DataStream:一个分组数据流的聚合操作,合并当前的元素和上次聚合的结果,产生一个新的值。

    val sumLambdaStream = dataStream.keyBy("name").reduce((s1, s2) => Score(s1.name, "Sum", s1.score + s2.score))

    val inputDataSet=env.fromCollection(List(1,2,3,4,5)).reduce((x,y)=>x+y).print()

  6、Split:DataStream → SplitStream:根据某些特征把一个DataStream拆分成两个或者多个DataStream;select:SplitStream→DataStream:从一个SplitStream中获取一个或者多个DataStream。

    val logStream = dstream.split {log =>
      var flags: List[String] = null
      if ("Apple".equals(log)) {
        flags = List(log)
      } else {
        flags = List("Android")
      }
      flags

    }
    val apple = logStream.select("Apple")

  7、Connect:DataStream,DataStream → ConnectedStreams:连接两个保持他们类型的数据流,两个数据流被Connect之后,只是被放在了一个同一个流中,内部依然保持各自的数据和形式不发生任何变化,两个流相互独立。因此对ConnectedStreams中的每一个Stream单独进行处理。

      val connStream = androidStream.connect(appleStream)

      val allStream = connStream.map(

        (log1: String) => log1 + "1",

        (log2: String) => log2 + "2"

      )

      allStream.print("连接流:")

  8、union:DataStream → DataStream:对两个或者两个以上的DataStream进行union操作,产生一个包含所有DataStream元素的新DataStream。注意:如果你将一个DataStream跟它自己做union操作,在新的DataStream中,你将看到每一个元素都出现两次。

      val unionStream = appleStream.union(androidStream)

     unionStream.print("union:")

  注意:Union之前两个流的类型必须是一样,Connect可以不一样。Connect只能操作两个流,Union可以操作多个。

(4)sink

  1、基于kafka的sink

  def getProducer(topic: String): FlinkKafkaProducer011[String] = {
    new FlinkKafkaProducer011[String]("note01:9092,note02:9092,note03:9092",topic,new SimpleStringSchema())
  }

  val kafkaSink = KafKaUtil.getProducer("time")
  unionStream.map(x => x+"sink").addSink(kafkaSink)

  2、基于Redis

  3、基于jdbc和Elasticsearch 

posted on 2020-05-29 17:59  hdc520  阅读(70)  评论(0编辑  收藏

导航