現在、Avro経由で寄木細工を書くために以下のコードを使用しています。このコードはそれをファイルシステムに書き込みますが、S3に書き込みたいです。
try {
StopWatch sw = StopWatch.createStarted();
Schema avroSchema = AvroSchemaBuilder.build("pojo", message.getTransformedMessage().get(0));
final String parquetFile = "parquet/data.parquet";
final Path path = new Path(parquetFile);
ParquetWriter writer = AvroParquetWriter.<GenericData.Record>builder(path)
.withSchema(avroSchema)
.withConf(new org.Apache.hadoop.conf.Configuration())
.withCompressionCodec(CompressionCodecName.SNAPPY)
.withWriteMode(Mode.OVERWRITE)//probably not good for prod. (overwrites files).
.build();
for (Map<String, Object> row : message.getTransformedMessage()) {
StopWatch stopWatch = StopWatch.createStarted();
final GenericRecord record = new GenericData.Record(avroSchema);
row.forEach((k, v) -> {
record.put(k, v);
});
writer.write(record);
}
//todo: Write to S3. We should probably write via the AWS objects. This does not show that.
//https://stackoverflow.com/questions/47355038/how-to-generate-parquet-file-using-pure-Java-including-date-decimal-types-an
writer.close();
System.out.println("Total Time: " + sw);
} catch (Exception e) {
//do somethign here. retryable? non-retryable? Wrap this excetion in one of these?
transformedParquetMessage.getOriginalMessage().getMetaData().addException(e);
}
これは問題なくファイルに書き込みますが、AmazonS3 apiにストリーミングするにはどうすればよいですか? Hadoop-aws jarを使用してWeb上でいくつかのコードを見つけましたが、そのためにはいくつかのWindows exeファイルが必要であり、もちろんそれを避けたいと考えています。現在使用しているのは次のものだけです。
<dependency>
<groupId>org.Apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.Apache.parquet</groupId>
<artifactId>parquet-avro</artifactId>
<version>1.8.1</version>
</dependency>
<dependency>
<groupId>org.Apache.hadoop</groupId>
<artifactId>hadoop-core</artifactId>
<version>1.2.1</version>
</dependency>
だから問題は、AvroParquetWriterで出力ストリームをインターセプトしてS3にストリーミングできるようにする方法があるのですか?私がやりたい主な理由これは再試行用です。 S3は自動的に最大3回再試行します。これは私たちを大いに助けてくれるでしょう。
これはhadoop-aws jarに依存しているため、使用したくない場合は、私がお手伝いできるかどうか確信が持てません。ただし、私はMacで実行していて、Windows exeファイルがないので、それらがどこから来ているのかわかりません。 AvroParquetWriterはすでにHadoopに依存しているため、この追加の依存関係が受け入れられない場合でも、他の人には大した問題ではない可能性があります。
AvroParquetWriterを使用して、URIパラメーターで作成されたHadoopパスを渡し、適切な構成を設定することにより、S3に直接ストリーミングできます。
val uri = new URI("s3a://<bucket>/<key>")
val path = new Path(uri)
val config = new Configuration()
config.set("fs.s3a.access.key", key)
config.set("fs.s3a.secret.key", secret)
config.set("fs.s3a.session.token", sessionToken)
config.set("fs.s3a.aws.credentials.provider", credentialsProvider)
val writer = AvroParquetWriter.builder[GenericRecord](path).withConf(config).withSchema(schema).build()
次の依存関係を使用しました(sbt形式):
"org.Apache.avro" % "avro" % "1.8.1"
"org.Apache.hadoop" % "hadoop-common" % "2.9.0"
"org.Apache.hadoop" % "hadoop-aws" % "2.9.0"
"org.Apache.parquet" % "parquet-avro" % "1.8.1"
うまくいけば、私は質問を誤解していませんが、ここであなたがしていることはavroを寄木細工に変換することであり、その寄木細工をs3にアップロードしたいと思います
ParquetWriterを閉じた後、次のようなメソッドを呼び出す必要があります(これにより、avroからparquetへのストリームの書き込みがインターセプトされず、書き込みが行われなくなったParquetファイルがストリーミングされるだけです)。
AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("ACCESS_KEY", "SECRET_KEY"))).build();
S3Path outputPath = new S3Path();
outputPath.setBucket("YOUR_BUCKET");
outputPath.setKey("YOUR_FOLDER_PATH");
try {
InputStream parquetStream = new FileInputStream(new File(parquetFile));
s3Client.putObject(outputPath.getBucket(), outputPath.getKey(), parquetStream, null);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
aWS SDKの使用
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-Java-sdk</artifactId>
<version>1.11.749</version>
</dependency>
もちろん、メソッドは別のutilsクラスに常駐し、このメソッドのコンストラクターはAmazonS3 s3Clientを認証情報で初期化する必要があるため、実行する必要があるのは、オブジェクトを配置するためにそのs3Clientメンバーを呼び出してアクセスすることだけです。
お役に立てれば