我对Apache Flink相对较新,我正在尝试创建一个生成AWS S3存储桶文件的简单项目。基于文档看起来我需要安装Hadoop才能执行此操作。
如何设置本地环境以允许我测试此功能?我在本地安装了Apache Flink和Hadoop。我已经为Hadoop的core-site.xml配置添加了必要的更改,并且还将我的HADOOP_CONF路径添加到了我的flink.yaml配置中。当我尝试通过Flink UI在本地提交作业时,我总是收到错误
2016-12-29 16:03:49,861 INFO org.apache.flink.util.NetUtils - Unable to allocate on port 6123, due to error: Address already in use
2016-12-29 16:03:49,862 ERROR org.apache.flink.runtime.jobmanager.JobManager - Failed to run JobManager.
java.lang.RuntimeException: Unable to do further retries starting the actor system
at org.apache.flink.runtime.jobmanager.JobManager$.retryOnBindException(JobManager.scala:2203)
at org.apache.flink.runtime.jobmanager.JobManager$.runJobManager(JobManager.scala:2143)
at org.apache.flink.runtime.jobmanager.JobManager$.main(JobManager.scala:2040)
at org.apache.flink.runtime.jobmanager.JobManager.main(JobManager.scala)
我假设我错过了我的环境设置方式。是否可以在本地进行此操作?任何帮助,将不胜感激。
答案 0 :(得分:3)
虽然您需要Hadoop库,但您无需安装Hadoop即可在本地运行并写入S3。我刚刚尝试使用基于Avro架构编写Parquet输出并将生成的SpecificRecord生成到S3。我通过SBT和Intellij Idea在本地运行以下代码的版本。需要的部分:
1)使用以下文件指定所需的Hadoop属性(注意:不建议定义AWS访问密钥/密钥。最好在具有正确IAM角色的EC2实例上运行以读取/写入S3存储桶。但需要本地测试)
<configuration>
<property>
<name>fs.s3.impl</name>
<value>org.apache.hadoop.fs.s3a.S3AFileSystem</value>
</property>
<!-- Comma separated list of local directories used to buffer
large results prior to transmitting them to S3. -->
<property>
<name>fs.s3a.buffer.dir</name>
<value>/tmp</value>
</property>
<!-- set your AWS ID using key defined in org.apache.hadoop.fs.s3a.Constants -->
<property>
<name>fs.s3a.access.key</name>
<value>YOUR_ACCESS_KEY</value>
</property>
<!-- set your AWS access key -->
<property>
<name>fs.s3a.secret.key</name>
<value>YOUR_SECRET_KEY</value>
</property>
</configuration>
2)进口: import com.uebercomputing.eventrecord.EventOnlyRecord
import org.apache.flink.api.scala.hadoop.mapreduce.HadoopOutputFormat
import org.apache.flink.api.scala.{ExecutionEnvironment, _}
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat
import org.apache.hadoop.conf.{Configuration => HadoopConfiguration}
import org.apache.hadoop.fs.Path
import org.apache.hadoop.mapreduce.Job
import org.apache.parquet.avro.AvroParquetOutputFormat
3)Flink代码使用具有上述配置的HadoopOutputFormat:
val events: DataSet[(Void, EventOnlyRecord)] = ...
val hadoopConfig = getHadoopConfiguration(hadoopConfigFile)
val outputFormat = new AvroParquetOutputFormat[EventOnlyRecord]
val outputJob = Job.getInstance
//Note: AvroParquetOutputFormat extends FileOutputFormat[Void,T]
//so key is Void, value of type T - EventOnlyRecord in this case
val hadoopOutputFormat = new HadoopOutputFormat[Void, EventOnlyRecord](
outputFormat,
outputJob
)
val outputConfig = outputJob.getConfiguration
outputConfig.addResource(hadoopConfig)
val outputPath = new Path("s3://<bucket>/<dir-prefix>")
FileOutputFormat.setOutputPath(outputJob, outputPath)
AvroParquetOutputFormat.setSchema(outputJob, EventOnlyRecord.getClassSchema)
events.output(hadoopOutputFormat)
env.execute
...
def getHadoopConfiguration(hadoodConfigPath: String): HadoopConfiguration = {
val hadoopConfig = new HadoopConfiguration()
hadoopConfig.addResource(new Path(hadoodConfigPath))
hadoopConfig
}
4)构建使用的依赖项和版本:
val awsSdkVersion = "1.7.4"
val hadoopVersion = "2.7.3"
val flinkVersion = "1.1.4"
val flinkDependencies = Seq(
("org.apache.flink" %% "flink-scala" % flinkVersion),
("org.apache.flink" %% "flink-hadoop-compatibility" % flinkVersion)
)
val providedFlinkDependencies = flinkDependencies.map(_ % "provided")
val serializationDependencies = Seq(
("org.apache.avro" % "avro" % "1.7.7"),
("org.apache.avro" % "avro-mapred" % "1.7.7").classifier("hadoop2"),
("org.apache.parquet" % "parquet-avro" % "1.8.1")
)
val s3Dependencies = Seq(
("com.amazonaws" % "aws-java-sdk" % awsSdkVersion),
("org.apache.hadoop" % "hadoop-aws" % hadoopVersion)
)
1)创建一个Hadoop配置目录(将其引用为hadoop-conf-dir),其中包含文件core-site.xml。
例如:
mkdir /home/<user>/hadoop-config
cd /home/<user>/hadoop-config
vi core-site.xml
#content of core-site.xml
<configuration>
<property>
<name>fs.s3.impl</name>
<value>org.apache.hadoop.fs.s3a.S3AFileSystem</value>
</property>
<!-- Comma separated list of local directories used to buffer
large results prior to transmitting them to S3. -->
<property>
<name>fs.s3a.buffer.dir</name>
<value>/tmp</value>
</property>
<!-- set your AWS ID using key defined in org.apache.hadoop.fs.s3a.Constants -->
<property>
<name>fs.s3a.access.key</name>
<value>YOUR_ACCESS_KEY</value>
</property>
<!-- set your AWS access key -->
<property>
<name>fs.s3a.secret.key</name>
<value>YOUR_SECRET_KEY</value>
</property>
</configuration>
2)创建一个目录(将引用为flink-conf-dir),其中包含文件flink-conf.yaml。
例如:
mkdir /home/<user>/flink-config
cd /home/<user>/flink-config
vi flink-conf.yaml
//content of flink-conf.yaml - continuing earlier example
fs.hdfs.hadoopconf: /home/<user>/hadoop-config
3)编辑用于运行S3 Flink作业的IntelliJ Run配置 - 运行 - 编辑配置 - 并添加以下环境变量:
FLINK_CONF_DIR and set it to your flink-conf-dir
Continuing the example above:
FLINK_CONF_DIR=/home/<user>/flink-config
4)使用该环境变量集运行代码:
events.writeAsText("s3://<bucket>/<prefix-dir>")
env.execute
答案 1 :(得分:0)
我必须执行以下操作才能在本地运行到S3的flink作业:
1-在我的flink / plugins / flink-s3-fs-hadoop目录中添加了flink-s3-fs-hadoop-1.9.1.jar
2-修改了flink / conf / flink-conf.yaml以包括 s3.access-key:AWS_ACCESS_KEY s3.secret-key:AWS_SECRET_KEY fs.hdfs.hadoopconf:/ etc / hadoop-config
我在hadoop-config文件夹中有core-site.xml文件,但是它不包含任何配置,因此可能不需要fs.hdfs.hadoopconf。
答案 2 :(得分:0)
在 sbt 中,我只需要添加 S3 库依赖项即可像本地文件系统一样使用它
SBT 文件:
"org.apache.flink" % "flink-s3-fs-hadoop" % flinkVersion.value
阅读示例:
public static void main(String[] args) throws Exception {
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<String> text = env.readTextFile("s3://etl-data-ia/test/fileStreamTest.csv");
text.print();
env.execute("test");}
答案 3 :(得分:0)
要使用 flink-s3-fs-hadoop 插件,您应该复制相应的 JAR 将文件从 opt 目录复制到 Flink 的 plugins 目录 在启动 Flink 之前分发。
我知道的另一种方法是通过环境变量启用它 ENABLE_BUILT_IN_PLUGINS="flink-s3-fs-hadoop-[flink-version].jar"
例如:flink-s3-fs-hadoop-1.12.2.jar
对于这两种方式,我们都必须在 flink-conf.yaml 文件中定义 S3 配置
<块引用>Flink 会在内部将其转换回 fs.s3a.connection.maximum。无需使用 Hadoop 的 XML 配置文件传递配置参数。
s3.endpoint: <end-point>
s3.path.style.access : true
至于 AWS 凭证,它们必须在环境变量或。在 flink-conf.yaml 中配置
s3.endpoint: <end-point>
s3.path.style.access : true
s3.access-key: <key>
s3.secret-key: <value>
s3.region: <region>
一旦设置完毕,您就可以像@EyalP 提到的那样从 S3 读取,或写入 S3(即使用数据集)
dataset.map(new MapToJsonString())
.writeAsText("s3://....",
FileSystem.WriteMode.OVERWRITE);
如果您想在本地进行测试(没有真实的 AWS 帐户),我建议您检查 localstack。它完全支持各种 AWS 服务(包括 S3)。如果你这样做,那么 AWS 凭证就不是必需的(可以提供为空),端点将是本地堆栈本身。