Flink批流处理代码初识

关于flink的一些基本介绍这儿就不给大家说了哈,毕竟官网和很多优秀博客都给大家介绍了。此文就给大家介绍flink的批、流代码相关的展示。

flink的入门学习就一定绕不开dataflows的理解,flink dataflows分为source,transformation,sink三大部分。一般来说transformation处会进行大量的逻辑代码操作来达到我们的业务处理目的。source处是接入数据的,没有数据就压根不需要数据处理计算,flink处理的数据都是从source处来的。有数据的输入那么一定就有数据的输出,sink处就是进行数据的输出操作的。我们来看看经典的官网图展示吧。

01_program_dataflow.png

env:就是flink的计算引擎,此处是flink的流计算引擎
addSource:就是flink的source,接入外部数据输入到flink内部的地方
map,keyBy,timeWindow,apply:都是transformation的一部分,根据具体的业务需求进行数据转化和计算操作
addSink:就是flink的sink,将flink内部计算完成后的结果数据输出到外部储存组件

1 批处理

示例数据

flume,flink,redis
storm,hive,kafka,hbase,phoenix,kafka
hive,phoenix,spark,flume,flink,kafka,kafka,flink
kafka,hive,hive,phoenix
kafka,kafka,kafka,storm,redis,spark
hbase,flume,storm
flume,flink,storm,flume,flume,kafka,spark,phoenix
flink,flink,kafka,hbase
kafka,flink,hive,flink
flume,hbase
hbase,hive
hbase,hbase,flink,phoenix
spark,hbase,flume,spark,hive,spark,flink
hbase,redis,hive
phoenix,storm,storm

flink批处理进行单词计数,此处直接上scala代码

package com.leslie.base.batch

import org.apache.flink.api.scala.ExecutionEnvironment
// scala代码需要该行导入信息,否则在代码写编写过程提示缺失隐式转化信息
import org.apache.flink.api.scala._ 

/**
 * @Author: leslie
 * @Description: flink批处理进行word count
 * @Time: 2020/1/3 21:42
 */
object WordCount {
  def main(args: Array[String]): Unit = {
    /*
     * 1 flink批处理引擎
     * 2 source 读取文件
     * 3 transformation 针对每一行数据进行切割处理,在进行单词分组统计
     * 4 sink 打印结果
     */
    // 获取flink的批处理引擎
    val env = ExecutionEnvironment.getExecutionEnvironment

    // 读取文件,指定字符编码为utf-8
    val originalData: DataSet[String] = env.readTextFile(getPath("words.txt"), charsetName = "UTF-8")

    // flatMap算子 读取每一行数据,根据","进行划分成单词数组。再将数组进行压扁操作
    val flatData: DataSet[String] = originalData.flatMap(line => line.split(","))
    // map算子 将每一个单词和其数量1形成元组 如(flink, 1)
    val tupleData: DataSet[(String, Int)] = flatData.map(word => (word, 1))
    // groupBy算子 将DataSet根据 元组 的第一个元素"单词"进行分组。参数0代表元组中的第一个元素
    val groupedData: GroupedDataSet[(String, Int)] = tupleData.groupBy(0)
    // sum算子 将同一分组中 "单词" 进行数量统计。参数1代表元组中的第二个元素
    val sinkData: DataSet[(String, Int)] = groupedData.sum(1)

    // 打印结果
    sinkData.print()
  }

  // 返回resouce目录中的指定文件路径
  def getPath(fileName: String): String = {
    this.getClass.getClassLoader.getResource(fileName).getPath // scala默认将最后一行结果返回
  }
  
}

结果输出

(redis,3)
(hive,8)
(flink,10)
(flume,8)
(hbase,9)
(kafka,11)
(storm,6)
(phoenix,6)
(spark,6)

上边flink批处理中进行数据转换和统计操作可以写成一行,但是平时工作的时候不太建议这样操作。在处理逻辑比较复杂的时候,太简洁的代码不利于后边代码维护。能够写成这样简洁是得益于scala语法的特性和语法糖。

env.readTextFile(getPath("words.txt"))
  .flatMap(_.split(","))
  .map((_, 1))
  .groupBy(0)
  .sum(1)
  .print()

2 流处理

flink流处理进行word count,下边直接给出scala代码

package com.leslie.base.streaming

// scala代码需要该行导入信息,否则在代码写编写过程提示缺失隐式转化信息
import org.apache.flink.api.scala._ 
import org.apache.flink.streaming.api.scala.{DataStream, StreamExecutionEnvironment}

/**
 * @Author: leslie
 * @Description: flink流处理进行word count
 * @Time: 2020/1/3 23:26
 */
object WordCount {
  def main(args: Array[String]): Unit = {
    /*
     * 1 flink流处理引擎
     * 2 source 读取文件
     * 3 transformation 针对每一行数据进行切割处理,在进行单词分组统计
     * 4 sink 打印结果
     */
    // 获取flink流处理引擎
    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment

    val originalData: DataStream[String] = env.socketTextStream("localhost", 8333)
    val sinkData: DataStream[(String, Int)] =
      originalData
        .flatMap(line => line.split(" "))
        .map(word => (word, 1))
        .keyBy(0)
        .sum(1)

    // 打印结果
    sinkData.print()

    // 流处理需要显式执行
    env.execute("flink_streaming_word_count")
  }
}

现在用流程描述和截图来展示一下上边flink程序计算结果展示
step1:使用nc命令在本机上的指定端口启动一个服务
step2:启动flink流计算程序
step3:本机nc服务上输入一段字符串,查看计算结果(红框为对应的输入数据,和flink计算结果)

02_flink_streaming_wrod_count_01.png

setp4:本机nc服务上再输入一段字符串,查看对应的计算结果

03_flink_streaming_word_count_02.png

此时是不是发现有些奇怪,明明第二次的数据输入仅有flink spark kafka各一次,为什么计算的结果为(spark,2),(flink,2),(kafka,1)。乍一看好像只有"kafka"次数计算是正确的,为什么会出现这样的结果呢?
原来我们此处并没有指定flink的窗口,所有的计算都是针对所有的数据来进行的,包括之前已经输入的数据。(窗口的概念以后再进行介绍,此处主要只是给大家展示一下flink的流计算)

你可能感兴趣的:(Flink批流处理代码初识)