import org.apache.flink.api.java.utils.ParameterTool
import org.apache.flink.streaming.api.scala._
object StreamWordCount {
def main(args: Array[String]): Unit = {
// 创建流处理的执行环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
// 利用传入参数来指定hostname和port
val paramTool: ParameterTool = ParameterTool.fromArgs(args)
val host = paramTool.get("host")
val port = paramTool.getInt("port")
val dataStream = env.socketTextStream(host, port)
// 对每条数据进行处理
val wordCountDataStream = dataStream.flatMap(_.split(" "))
.filter(_.nonEmpty)
.startNewChain()/*开始一个新的任务链(一般在forward(one-to-one)模式,并且任务执行并行度相同的情况下,如果不设置此参数,则任务会合并)*/
.map((_, 1))
.keyBy(0)
.sum(1)
wordCountDataStream.print()
.setParallelism(1) //设定输出时候的并行执行个数(并行度)
// 启动executor
env.execute("stream word count job")
}
}
配置flink参数设置(会被文件中的代码设置覆盖):
#每个 TaskManager 提供的任务 slots 数量
taskmanager.numberOfTaskSlots: 2
# 程序默认并行计算的个数,最大并行计算个数为所有的taskmanager上面的slots总和
parallelism.default: 1
当我们看到,在filter后面设置了startNewChain()之后,原本并行度相同,并且式forward(one-to-one)的执行计划,被划分为两个任务链。(在不设置的时候,flink默认会把所有one-to-one并且并行度相同的任务合成在一起。)
如果去掉代码中filter后面的 .startNewChain(),则如果forward(one-to-one)并且并行度相同的任务必然合并。
设置合并任务链的常用方式有两种:
1.在设置环境的时候设置本job中默认所有的任务不合并任务链:
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.disableOperatorChaining()
2.上面的那种方式,设置在某一个步骤的时候不合并任务链
.filter(_.nonEmpty).startNewChain()
flink读取文件时,根据官方文档:Under the hood, Flink splits the file reading process into two sub-tasks, namely directory monitoring and data reading. Each of these sub-tasks is implemented by a separate entity. Monitoring is implemented by a single, non-parallel (parallelism = 1) task,读取并行度只能为1,socketsource并行度同样只能为1。任务输出时候print并行度也只能是1(这个可以理解但是很难描述为什么),因此整个wordcount的任务计划图如下(去掉了startNewChain之后):
并行度为1:
并行度为2:
并行度为3:
注:可能语言组织不好,只为了自己理解和学习,不喜勿喷