Dataproc 中的 NoSuchMethodError StorageObject.getTimeCreated 运行 作业
NoSuchMethodError StorageObject.getTimeCreated running job in Dataproc
我正在尝试 运行 一个在本地工作的 Spark 作业。它使用 Google 存储。我收到此错误:
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.jar
和 google-api-services-storage-v1-rev83-1.22.0.jar
都没有成功,即使该方法已定义。看起来它没有使用正确版本的 google-api-services-storage,但我不知道除了上传和指定 jar 之外我还能做什么。
有什么我遗漏的吗?
看来问题出在 Dataproc 当前 compiles against an older google-api-services-storage-v1
版本中内置的 GCS 连接器。 com.google.api.services.storage.model.StorageObject.getTimeCreated()
方法仅在更高版本中添加,因此当旧版本在类路径中获胜时,您会遇到错误。在验证完全向后兼容性后,我们可能会在不久的将来版本中更新版本。
与此同时,您可以尝试使用自己的 fatjar 中的 shade 插件重新打包 com.google.api.services.storage.*
包,就像 GCS 连接器 repackages com.google.common.* 一样,以避免与用户带来的类路径冲突他们自己的 Guava 版本,或者您可以尝试自己重新编译 GCS 连接器并使用 init 操作将其交换到您的 Dataproc 集群中(您基本上可以 copy/paste 这里的所有内容,除了您需要提供 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);
...
我 运行 使用 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 构建为 fat 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>
我正在尝试 运行 一个在本地工作的 Spark 作业。它使用 Google 存储。我收到此错误:
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.jar
和 google-api-services-storage-v1-rev83-1.22.0.jar
都没有成功,即使该方法已定义。看起来它没有使用正确版本的 google-api-services-storage,但我不知道除了上传和指定 jar 之外我还能做什么。
有什么我遗漏的吗?
看来问题出在 Dataproc 当前 compiles against an older google-api-services-storage-v1
版本中内置的 GCS 连接器。 com.google.api.services.storage.model.StorageObject.getTimeCreated()
方法仅在更高版本中添加,因此当旧版本在类路径中获胜时,您会遇到错误。在验证完全向后兼容性后,我们可能会在不久的将来版本中更新版本。
与此同时,您可以尝试使用自己的 fatjar 中的 shade 插件重新打包 com.google.api.services.storage.*
包,就像 GCS 连接器 repackages com.google.common.* 一样,以避免与用户带来的类路径冲突他们自己的 Guava 版本,或者您可以尝试自己重新编译 GCS 连接器并使用 init 操作将其交换到您的 Dataproc 集群中(您基本上可以 copy/paste 这里的所有内容,除了您需要提供 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);
...
我 运行 使用 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 构建为 fat 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>