当前位置: 首页 > 科技观察

新手Tips——为什么Flink的Java模块需要Scala版本后缀

时间:2023-03-19 14:40:53 科技观察

》来自开发者:》Flink对java和scala的开发总是一头雾水,总是不清楚maven依赖的是什么。你能告诉我吗?我知道flink在java之上包裹了一层scala,但是在添加maven依赖的时候,总是让人摸不着头脑……》01Java开发者暂时抛开网友的问题,先从一个Java开发者的黑盒方法说起建立一个简单的例子。对于初学者,我们还是用模板吧……我们用mvn命令切入,如下:mvnarchetype:generate\-DarchetypeGroupId=org.apache.flink\-DarchetypeArtifactId=flink-walkthrough-datastream-java\-DarchetypeVersion=1.13.0\-DgroupId=khkw\-DartifactId=helloJava\-Dversion=0.1\-Dpackage=khkw\-DinteractiveMode=false上面的命令最后看到如下成功信息:接下来我们看一下生成的pom依赖和导入例子中,我是用Idea查看的,所以进入hellojava目录下执行mvnidea:idea,用IDE打开。属性中也声明了scala版本2.11,依赖依赖中也及时使用了scala版本信息。这是网友们比较迷惑的一点,后面会解释。我们在看Java开发DataStream的核心依赖是什么?我们发现核心依赖是flink-streaming-java_2.11。虽然是java开发的,但是确实带有scala的版本后缀。为什么会这样?后面会讲解flink整体的scala/java设计。在这里我只是声明依赖是一次性的工作。如果引入依赖后在后续的开发中没有导入错误,那么可以暂时忍耐。我们关注的是开发过程中是否存在混淆?我们打开FraudDetectionJob作业主类,如下:业务相关的import,开发者自己很清楚。不用说,flink框架相关的import就只有DataStream&StreamExecutionEnvironment,那我们自动import的时候会不会有导入错误的可能呢??这是Flinkjava开发者省心的地方,如下:这里我们发现Java用户没有机会犯错,只有一次。但是对于Scala用户来说就没那么容易了,让我们继续往下看……02Scala开发者我们同样使用mvan命令创建示例工程,如下:mvnarchetype:generate\-DarchetypeGroupId=org.apache。flink\-DarchetypeArtifactId=flink-walkthrough-datastream-scala\-DarchetypeVersion=1.13.0\-DgroupId=khkw\-DartifactId=helloScala\-Dversion=0.1\-Dpackage=khkw\-DinteractiveMode=false创建成功后,我们还打开pom文件查看依赖,如下:这是scala用户很正常的依赖。无论是artifactacId名称还是scala版本,都是非常合理的设计。看看开发流程类的导入情况是否一样清晰?看到上面的情况,初学者应该有点懵了:(,我需要那么多类,怎么选?Scala开发者很容易看到与类同名的Object,所以也有同名的类ScalaJava实现中的名字对于初学者来说可能会有些犹豫,但是既然我们是用Scala开发的,java和scala并存的时候首选Scala实现,那为什么会出现两个重名的实现呢,我们看一下依赖树,感受一下事情是这样的:FlinkRuntime是用Java开发的,而ScalaAPI是在JavaAPI的基础上构建的,所以理论上Scala用户总是有两种选择,虽然选择很明确。03为什么Java模块需要Scala版本后缀?我们还是以网友提出的问题为出发点:“像java-datastream_2.11一样,都是java写的。以后分为2.11。这个问题很好。flink-streaming-java模块的artifactId为什么带2.11?这个flink-streaming-java_2.11就百思不得其解了。我们先看看现状和依赖,如下:[INFO]org.apache.flink:flink-streaming-java_2.11:jar:1.14-SNAPSHOT[INFO]+-org.apache.flink:flink-core:jar:1.14-SNAPSHOT:compile[INFO]|+-org.apache.flink:flink-annotations:jar:1.14-SNAPSHOT:compile[信息]|+-org.apache.flink:flink-metrics-core:jar:1.14-SNAPSHOT:compile[信息]|+-org.apache.flink:flink-shaded-asm-7:jar:7.1-13.0:compile[信息]|+-org.apache.commons:commons-lang3:jar:3.3.2:compile[信息]|+-com.esotericsoftware.kryo:kryo:jar:2.24.0:compile[信息]||\-com.esotericsoftware.minlog:minlog:jar:1.2:compile[信息]|+-commons-collections:commons-collections:jar:3.2.2:compile[信息]|\-org.apache.commons:commons-compress:jar:1.20:compile[INFO]+-org.apache.flink:flink-file-sink-common:jar:1.14-SNAPSHOT:compile[INFO]+-org.apache.flink:flink-runtime_2.11:jar:1.14-SNAPSHOT:编译[信息]|+-org.apache.flink:flink-queryable-state-client-java:jar:1.14-SNAPSHOT:compile[信息]|+-org.apache.flink:flink-hadoop-fs:jar:1.14-SNAPSHOT:compile[信息]|+-commons-io:commons-io:jar:2.8.0:compile[信息]|+-org.apache.flink:flink-shaded-netty:jar:4.1.49.Final-13.0:compile[信息]|+-org.apache.flink:flink-shaded-jackson:jar:2.12.1-13.0:compile[信息]|+-org.apache.flink:flink-shaded-zookeeper-3:jar:3.4.14-13.0:compile[信息]|+-commons-cli:commons-cli:jar:1.3.1:compile[信息]|+-org.javassist:javassist:jar:3.24.0-GA:编译[信息]|+-org.scala-lang:scala-library:jar:2.11.12:compile[信息]|+-com.typesafe.akka:akka-actor_2.11:jar:2.5.21:compile[信息]||+-com.typesafe:config:jar:1.3.0:compile[信息]||\-org.scala-lang.modules:scala-java8-compat_2.11:jar:0.7.0:compile[信息]|+-com.typesafe.akka:akka-stream_2.11:jar:2.5.21:compile[信息]||+-org.reactivestreams:reactive-streams:jar:1.0.2:compile[信息]||\-com.typesafe:ssl配置核心_2.11:jar:0.3.7:编译[信息]||\-org.scala-lang.modules:scala-parser-combinators_2.11:jar:1.1.1:compile[信息]|+-com.typesafe.akka:akka-protobuf_2.11:jar:2.5.21:compile[信息]|+-com.typesafe.akka:akka-slf4j_2.11:jar:2.5.21:compile[信息]|+-org.clapper:grizzled-slf4j_2.11:jar:1.3.2:compile[信息]|+-com.github.scopt:scopt_2.11:jar:3.5.0:compile[信息]|+-org.xerial.snappy:snappy-java:jar:1.1.8.3:compile[信息]|\-org.lz4:lz4-java:jar:1.6.0:compile[INFO]+-org.apache.flink:flink-java:jar:1.14-SNAPSHOT:compile[INFO]+-org.apache.flink:flink-shaded-guava:jar:18.0-13.0:compile[INFO]+-org.apache.commons:commons-math3:jar:3.5:compile[INFO]+-org.apache.flink:flink-core:test-jar:tests:1.14-SNAPSHOT:test[INFO]+-org.apache.flink:flink-test-utils-junit:jar:1.14-SNAPSHOT:test[INFO]+-org.apache.flink:flink-runtime_2。11:test-jar:tests:1.14-SNAPSHOT:test[INFO]+-org.apache.flink:flink-shaded-force-shading:jar:13.0:compile[INFO]+-org.slf4j:slf4j-api:jar:1.7.15:compile[INFO]+-com.google.code.findbugs:jsr305:jar:1.3.9:compile[INFO]+-junit:junit:jar:4.13.2:测试[信息]|\-org.hamcrest:hamcrest-core:jar:1.3:test[信息]+-org.mockito:mockito-core:jar:2.21.0:test[信息]|+-net.bytebuddy:byte-buddy:jar:1.8.15:test[信息]|+-net.bytebuddy:byte-buddy-agent:jar:1.8.15:test[信息]|\-org.objenesis:objenesis:jar:2.1:compile[信息]+-org.powermock:powermock-module-junit4:jar:2.0.4:test[信息]|\-org.powermock:powermock-module-junit4-common:jar:2.0.4:test[信息]|+-org.powermock:powermock-reflect:jar:2.0.4:test[信息]|\-org.powermock:powermock-core:jar:2.0.4:test[信息]+-org.powermock:powermock-api-mockito2:jar:2.0.4:test[信息]|\-org.powermock:powermock-api-support:jar:2.0.4:test[INFO]+-org.hamcrest:hamcrest-all:jar:1.3:test[INFO]+-org.apache.logging.log4j:log4j-slf4j-impl:jar:2.14.1:test[INFO]+-org.apache.logging.log4j:log4j-api:jar:2.14.1:test[INFO]+-org.apache.logging.log4j:log4j-core:jar:2.14.1:test[信息]\-org.apache.logging.log4j:log4j-1.2-api:jar:2.14.1:test[信息]------------------------------------------------------------------[信息]构建成功[信息]--------------------------------------------------------------------[信息]总时间:42.595秒[信息]完成于:2021-06-26T08:57:22+08:00[信息]--------------------------------------------------------------------我们发现依赖flink-runtime_2.11的flink-streaming-java也有scala版本后缀,同样的困惑,为什么纯java写的flinkruntime需要携带scala版本号,继续追,发现flink-runtime还依赖akka-actor/stream/protobuf_2.11,也就是flink依赖的三方库是纯java的但是也搭载了scala版本。按照这个钻法,我们要挖出akka-stream为什么带scala版本后缀,那么这个问题就迎刃而解了,akka的代码50+都是用scala写的,查看https://github.com/akka/阿卡。04未来会怎样?用户是雪亮的,问题开门见山。这个问题确实是Flink社区需要解决的问题,去除Scala依赖的讨论也已经发起。详情:https://lists.apache.org/thread.html/rd7bf0dabe2d75adb9f97a1879638711d04cfce0774d31b033acae0b8%40%3Cdev.flink.apache.org%3E05Flink从哪一层主动使用Scala?那么上面的Java模块需要scala后缀是被动的,那么Flink是在哪一层主动引入Scala呢?这主要是站在Flink开发者受众的角度。虽然Flink的核心是用Java编写的,但更期待更多的非Java开发者能够在不切换开发语言的情况下方便地使用Flink。Scala用户自然可以使用JavaAPI,但是Scala在语言API方面比Java有很多优势。因此,为了不改变Scala用户的开发习惯,Flink社区为Scala用户提供了ScalaAPI,因此Flink主动引入。Scala从API层面切入。Flink社区致力于ScalaAPI,包括所有JavaAPI函数。同时,之前的版本也封装了一些符合Scala编程习惯的简单易用的API包。在Flink的所有模块中,只有flink-scala/flink-stream-scala/flink-table模块涉及到scala的依赖。flink-scala是基础包,包括type、codegen、metric等基础部分,而flink-stream-Scala是纯粹面向Scala用户的DataStreamAPI部分,flink-talbe是对Scala部分的SQL级别封装里面。还有一点,不仅是Java/Scala的用户受众,Flink也期望对多语言有很好的支持。PyFlink在Flink的多语言支持上迈出了第一步~~:)行善者如春园芳草。他们没有看到自己的成长,但他们一天天长大。作恶者,磨刀石,不见其损,日日亏钱。离这很远;人为恶,祸虽未至,福已远!作者介绍孙金城,社区编辑,ApacheFlinkPMC成员,ApacheBeamCommitter,ApacheIoTDBPMC成员,ALCBeijing成员,Apache神鱼导师,Apache软件基金会成员。专注于技术领域的流计算和时序数据存储。