簡體   English   中英

如何在Apache Beam項目中直接使用google-cloud-storage

[英]How to use google-cloud-storage directly in a Apache Beam project

我們正在開發Apache Beam項目(版本2.4.0),我們還希望通過google-cloud-storage API直接使用存儲桶。 但是,將一些波束依賴性與雲存儲相結合,會導致難以解決的依賴性問題。

我們看到Beam 2.4.0依賴於雲存儲1.22.0,所以這就是我們在下面使用它的原因。 我們遇到了與1.27.0相同的問題。 以下pom.xml指定了我們在項目中使用的四個梁依賴關系,其中最后兩個導致問題。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bol</groupId>
    <artifactId>beam-plus-storage</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <beam.version>2.4.0</beam.version>
    </properties>

    <dependencies>
        <!-- These first two dependencies do not clash -->
        <dependency>
            <groupId>org.apache.beam</groupId>
            <artifactId>beam-runners-direct-java</artifactId>
            <version>${beam.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.beam</groupId>
            <artifactId>beam-sdks-java-extensions-join-library</artifactId>
            <version>${beam.version}</version>
        </dependency>
        <!-- This one leads to java.lang.ClassNotFoundException: com.google.api.gax.rpc.HeaderProvider -->
        <dependency>
            <groupId>org.apache.beam</groupId>
            <artifactId>beam-sdks-java-io-google-cloud-platform</artifactId>
            <version>${beam.version}</version>
        </dependency>
        <!-- This one leads to java.lang.NoSuchMethodError: com.google.api.services.storage.Storage$Objects$List.setUserProject(...) -->
        <dependency>
            <groupId>org.apache.beam</groupId>
            <artifactId>beam-runners-google-cloud-dataflow-java</artifactId>
            <version>${beam.version}</version>
        </dependency>

        <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>google-cloud-storage</artifactId>
            <version>1.22.0</version>
        </dependency>

    </dependencies>
</project>

以下是存儲API的最小工作/損壞用法,列出了公共存儲桶中的文件。

import com.google.api.gax.paging.Page;
import com.google.cloud.storage.Blob;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;

public class CloudStorageReader {

    public static void main(String[] args) {
        Storage storage = StorageOptions.getDefaultInstance().getService();
        Page<Blob> list = storage.list("gcp-public-data-landsat", Storage.BlobListOption.currentDirectory(), Storage.BlobListOption.prefix("LC08/PRE/044/034/LC80440342016259LGN00/"));
        for (Blob blob : list.getValues()) {
            System.out.println(blob);
        }
    }
}

刪除最后兩個依賴項時,列出存儲桶的內容可以正常工作。 使用java-io beam依賴項時,找不到HeaderProvider類。 由於數據流依賴性,找不到setUserProject方法。 請參閱pom中的注釋以獲取完整的錯誤消息。

我們花了很多時間來嘗試修復HeaderProvider錯誤,這是導入所有四個波束依賴關系時出現的錯誤。 我們為沖突依賴項添加了顯式導入,並在梁導入中添加了排除。 每次我們添加顯式依賴項時,都會彈出另一個相關問題。 我們嘗試了maven陰影,由於我們項目的包裝,這不是那么實用,所以從來沒有讓它起作用。

最后,我們為雲存儲交互創建了一個單獨的子模塊+ jar,為我們的打包/運行帶來了更多的復雜性。

最后一點,我們在嘗試使用BigQuery API時遇到了同樣的問題,但通過重用包私有光束代碼解決了這個問題。

如果某人確實有(相對簡單的)方法讓這些庫協同工作,或者確認這確實是一個具有挑戰性的依賴性問題,可能需要在Apache Beam中解決,那將是非常棒的。

您可以利用Beam包含的FileSystems API列出存儲桶中的存儲桶,讀/寫文件和刪除對象,而不是包含單獨的雲存儲依賴項。 下面是一個示例,其中列出了存儲桶下的所有文件,然后將其中一個文件讀入字符串。

// Set the default pipeline options so the various filesystems are
// loaded into the registry. This shouldn't be necessary if used
// within a pipeline.
FileSystems.setDefaultPipelineOptions(PipelineOptionsFactory.create());

// List Bucket
MatchResult listResult = FileSystems.match("gs://filesystems-demo/**/*");
listResult
    .metadata()
    .forEach(
        metadata -> {
          ResourceId resourceId = metadata.resourceId();
          System.out.println(resourceId.toString());
        });


// Read file
ResourceId existingFileResourceId = FileSystems
    .matchSingleFileSpec("gs://filesystems-demo/test-file1.csv")
    .resourceId();

try (ByteArrayOutputStream out = new ByteArrayOutputStream();
    ReadableByteChannel readerChannel = FileSystems.open(existingFileResourceId);
    WritableByteChannel writerChannel = Channels.newChannel(out)) {
  ByteStreams.copy(readerChannel, writerChannel);

  System.out.println("File contents: \n" + out.toString());
}


// Write file
String contentToWrite = "Laces out Dan!";

ResourceId newFileResourceId = FileSystems
    .matchNewResource("gs://filesystems-demo/new-file.txt", false);

try (ByteArrayInputStream in = new ByteArrayInputStream(contentToWrite.getBytes());
    ReadableByteChannel readerChannel = Channels.newChannel(in);
    WritableByteChannel writerChannel = FileSystems.create(newFileResourceId, MimeTypes.TEXT)) {

  ByteStreams.copy(readerChannel, writerChannel);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM