NoSuchMethodError StorageObject.getTimeCreated在Dataproc

时间:2016-09-14 14:30:20

标签: google-cloud-storage google-cloud-dataproc

我试图运行一个在本地工作的Spark工作。它使用谷歌存储。我收到此错误:

Exception in thread "main" java.lang.NoSuchMethodError: com.google.api.services.storage.model.StorageObject.getTimeCreated()Lcom/google/api/client/util/DateTime;
    at com.google.cloud.storage.BlobInfo.fromPb(BlobInfo.java:798)
    at com.google.cloud.storage.Blob.fromPb(Blob.java:641)
    at com.google.cloud.storage.StorageImpl.create(StorageImpl.java:139)
    at com.google.cloud.storage.StorageImpl.create(StorageImpl.java:132)
...

Dataproc作业正在使用gcloud-java-storage-0.2.8.jar,我已经尝试了google-api-services-storage-v1-rev62-1.21.0.jargoogle-api-services-storage-v1-rev83-1.22.0.jar但没有成功,即使定义了该方法。看起来它没有使用正确版本的google-api-services-storage,但我不知道除了上传和指定jar之外我还能做些什么。

我有什么遗失的吗?

2 个答案:

答案 0 :(得分:3)

看起来问题是Dataproc中内置的GCS连接器目前是compiles against an older google-api-services-storage-v1版本。 com.google.api.services.storage.model.StorageObject.getTimeCreated()方法仅在更高版本中添加,因此当旧版本在类路径上获胜时,您会遇到错误。在验证完全向后兼容性后,我们可能会在不久的将来发布该版本。

与此同时,您可以尝试使用自己的fatjar中的shade插件重新打包com.google.api.services.storage.*包,就像GCS连接器repackages com.google.common.*一样,以避免与用户自带类路径冲突Guava版本,或者您可以尝试自己重新编译GCS连接器并使用init操作将其交换到Dataproc集群(除了需要提供GCS存储桶的第一行之外,您基本上可以逐字复制/粘贴所有内容):

export GCS_BUCKET=[SOME BUCKET YOU OWN HERE WITHOUT gs:// PREFIX]


# Clone the code, update the dependency, build it
git clone https://github.com/GoogleCloudPlatform/bigdata-interop.git
cd bigdata-interop
sed -i "s/v1-rev35/v1-rev83/" pom.xml
mvn -P hadoop2 package


# Upload the new GCS connector to GCS
gsutil cp gcs/target/gcs-connector-1.5.3-hadoop2-SNAPSHOT-shaded.jar gs://${GCS_BUCKET}/gcs-connector-1.5.3-hadoop2-SNAPSHOT-shaded.jar


# Create a quick init action
cat << EOF > install_new_gcs.sh

#!/bin/bash
rm /usr/lib/hadoop/lib/gcs-connector-*.jar
gsutil cp gs://${GCS_BUCKET}/gcs-connector-1.5.3-hadoop2-SNAPSHOT-shaded.jar \
    /usr/lib/hadoop/lib/
chmod 644 /usr/lib/hadoop/lib/gcs-connector-*.jar

EOF
gsutil cp install_new_gcs.sh gs://${GCS_BUCKET}/install_new_gcs.sh


# Create your dataproc cluster
gcloud dataproc clusters create ${USER}-new-connector \
    --initialization-actions gs://${GCS_BUCKET}/install_new_gcs.sh

顺便说一句,由于这里的根本原因是自动安装的Hadoop GCS连接器与您自己的GCS库之间发生冲突,您可能需要考虑在代码中使用Hadoop FileSystem接口;在Dataproc中,这将被配置为在您传递Path的任何位置时,您可以使用gs://bucket/foo/bar形式的路径,并且它会自动加载GCS连接器库以便正常工作。您的代码看起来像这样:

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.conf.Configuration;

...
Path foo = new Path("gs://my-bucket/my-data.txt");
InputStream is = foo.getFileSystem(new Configuration()).open(foo);
...

答案 1 :(得分:0)

我遇到了与Dataproc的1.0图像版本相同的问题。我通过在我的集群初始化操作中添加以下内容来解决它:

#!/bin/bash

rm /usr/lib/hadoop/lib/bigquery-connector-0.10.1-hadoop2.jar
rm /usr/lib/hadoop/lib/gcs-connector-1.6.0-hadoop2.jar

rm /usr/lib/hadoop/lib/guava-11.0.2.jar
gsutil cp gs://my-bucket/jars/guava-18.0.jar /usr/lib/hadoop/lib/

此外,我将我的Spark应用程序jar构建为胖罐,具有以下maven配置:

    <dependency>
        <groupId>com.google.apis</groupId>
        <artifactId>google-api-services-storage</artifactId>
        <version>v1-rev97-1.22.0</version>
    </dependency>
    <dependency>
        <groupId>com.google.cloud.bigdataoss</groupId>
        <artifactId>gcs-connector</artifactId>
        <version>1.6.0-hadoop2</version>
    </dependency>