Flink开发大致分为四步骤:Environment、Source、Transform、Sink
新建maven项目,添加pom依赖:
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-scala_2.11</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala_2.11</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka_2.11</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.11</artifactId>
<version>1.7.2</version>
</dependency>
1、Environment
Flink Job在提交执行计算时,需要首先建立和Flink框架之间的联系,也就指的是当前的flink运行环境,只有获取了环境信息,才能将task调度到不同的taskManager执行。而这个环境对象的获取方式相对比较简单。
// 批处理环境
val env = ExecutionEnvironment.getExecutionEnvironment
// 流式数据处理环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
2、Source
Flink框架可以从不同的来源获取数据,将数据提交给框架进行处理, 我们将获取数据的来源称之为数据源。
2.1 从内存读取数据
一般情况下,可以将数据临时存储到内存中,形成特殊的数据结构后,作为数据源使用。这里的数据结构采用集合类型是比较普遍的。
import org.apache.flink.streaming.api.scala._
object SourceTest {
def main(args: Array[String]): Unit = {
//创建环境
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
//从内存中读取(使用集合类型)
val stream1: DataStream[String] = env.fromCollection(List(
"hello java",
"hello flink",
"hello XML",
"hello spark",
"hello scala",
"hello flume",
"hello kafka",
"hello storm",
"hello mysql",
"hello Linux",
"hello python",
"hello HTML",
"hello javascript"
))
//打印
stream1.print()
//启动流
env.execute("demo")
}
}
输出结果前面的数字代表的是处理的线程,默认是调用所有线程处理,如果只想启用2个线程处理,可以设置并行度:env.setParallelism(2)
。关于设置并行度,除了刚开始就设置并行度以外,其实每一步转化操作都可以设置并行度,如下:
val resultDataStream: DataStream[(String, Int)] = inputDataStream
.flatMap(_.split(" ")).setMaxParallelism(2)
.map((_, 1)).setParallelism(3)
.keyBy(0)
.sum(1).setParallelism(2)
resultDataStream.print().setParallelism(1)
虽然可以这样设置,但我们一般不会这样做,既然有那么多线程资源可以使用,我们为什么不全部使用呢。假如我们需要将打印结果写入文件,如果并行度大于1,会打印出线程和尖括号,这时候就可以在打印时设置并行度为1,如:resultDataStream.print().setParallelism(1)
,此时打印出来的结果就没有线程和尖括号了。
2.2 从文件中读取数据
通常情况下,我们会从存储介质中获取数据,比较常见的就是将日志文件作为数据源。
import org.apache.flink.streaming.api.scala._
object SourceFile {
def main(args: Array[String]): Unit = {
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
//从文件中读取
val fileDS: DataStream[String] = env.readTextFile("input/data.txt")
//打印
fileDS.print()
//启动
env.execute("demo2")
}
}
- 在读取文件时,文件路径可以是目录也可以是单一文件。
- 路径可以是绝对路径,也可以是相对路径。如果采用相对文件路径,会从当前系统参数user.dir中获取路径。
- 如果在IDEA中执行代码,那么系统参数user.dir自动指向项目根目录。
- 如果是standalone集群环境,默认为集群节点根目录。
- 路径可以是本地文件路径(如示例)也可以是分布式系统路径,如HDFS
val fileDS: DataStream[String] =env.readTextFile( "hdfs://hadoop20:9000/test/data.txt")
假如读取的是HDFS上的文件,
2.3 kafka读取数据
Kafka作为消息传输队列,是一个分布式的,高吞吐量,易于扩展地基于主题发布/订阅的消息系统。在现今企业级开发中,Kafka 和 Flink成为构建一个实时的数据处理系统的首选。
import java.util.Properties
import org.apache.flink.streaming.api.scala._
import org.apache.flink.api.common.serialization.SimpleStringSchema
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer
import org.apache.kafka.clients.consumer.ConsumerConfig
object SourceKafka {
def main(args: Array[String]): Unit = {
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
val prop = new Properties()
prop.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.136.20:9092")
prop.setProperty(ConsumerConfig.GROUP_ID_CONFIG,"flink-kafka-demo")
prop.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer")
prop.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringDeserializer")
prop.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"latest")
val kafkaDS: DataStream[String] = env.addSource(
new FlinkKafkaConsumer[String](
"kafkaflinkTopic", //kafka的topic
new SimpleStringSchema(),
prop)
)
kafkaDS.print()
env.execute("kafkaFlinkDemo")
}
}
2.4 从端口读取数据
import org.apache.flink.api.java.utils.ParameterTool
import org.apache.flink.streaming.api.datastream.DataStreamSource
import org.apache.flink.streaming.api.scala._
object SocketFile {
def</