[英]Error using SpannerIO in apache beam
這個問題是一個跟進到這一個 。 我正在嘗試使用apache beam從google spanner表中讀取數據(然后進行一些數據處理)。 我使用java SDK編寫了以下最小示例:
package com.google.cloud.dataflow.examples;
import java.io.IOException;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.PipelineResult;
import org.apache.beam.sdk.io.gcp.spanner.SpannerIO;
import org.apache.beam.sdk.options.PipelineOptions;
import org.apache.beam.sdk.options.PipelineOptionsFactory;
import org.apache.beam.sdk.values.PCollection;
import com.google.cloud.spanner.Struct;
public class backup {
public static void main(String[] args) throws IOException {
PipelineOptions options = PipelineOptionsFactory.create();
Pipeline p = Pipeline.create(options);
PCollection<Struct> rows = p.apply(
SpannerIO.read()
.withInstanceId("my_instance")
.withDatabaseId("my_db")
.withQuery("SELECT t.table_name FROM information_schema.tables AS t")
);
PipelineResult result = p.run();
try {
result.waitUntilFinish();
} catch (Exception exc) {
result.cancel();
}
}
}
當我嘗試使用DirectRunner執行代碼時,我收到以下錯誤消息:
org.apache.beam.runners.direct.repackaged.com.google.common.util.concurrent.UncheckedExecutionException:
org.apache.beam.sdk.util.UserCodeException:java.lang.NoClassDefFoundError:無法初始化類com.google.cloud.spanner.spi.v1.SpannerErrorInterceptor
[...]引起:org.apache.beam.sdk.util.UserCodeException:java.lang.NoClassDefFoundError:無法初始化類com.google.cloud.spanner.spi.v1.SpannerErrorInterceptor
[...]引起:java.lang.NoClassDefFoundError:無法初始化類com.google.cloud.spanner.spi.v1.SpannerErrorInterceptor
或者,使用DataflowRunner:
org.apache.beam.runners.direct.repackaged.com.google.common.util.concurrent.UncheckedExecutionException:org.apache.beam.sdk.util.UserCodeException:java.lang.NoSuchFieldError:internal_static_google_rpc_LocalizedMessage_fieldAccessorTable
[...]引起:org.apache.beam.sdk.util.UserCodeException:java.lang.NoSuchFieldError:internal_static_google_rpc_LocalizedMessage_fieldAccessorTable
[...]引起:java.lang.NoSuchFieldError:internal_static_google_rpc_LocalizedMessage_fieldAccessorTable
在這兩種情況下,錯誤信息都相當神秘,我找不到任何明確的想法,因為谷歌搜索的錯誤是什么原因。 我也找不到使用SpannerIO模塊的任何示例腳本。
這個錯誤是由於我的代碼中的明顯錯誤,還是由於Google雲工具安裝不當造成的?
此問題很可能是由此處描述的依賴性兼容性問題引起的: BEAM-2837 。 以下是JIRA問題中的一條評論中描述的快速解決方法:
<dependency>
<groupId>com.google.api.grpc</groupId>
<artifactId>grpc-google-common-protos</artifactId>
<version>0.1.9</version>
</dependency>
<dependency>
<groupId>org.apache.beam</groupId>
<artifactId>beam-sdks-java-io-google-cloud-platform</artifactId>
<version>${beam.version}</version>
<exclusions>
<exclusion>
<groupId>com.google.api.grpc</groupId>
<artifactId>grpc-google-common-protos</artifactId>
</exclusion>
</exclusions>
</dependency>
明確定義所需的com.google.api.grpc
依賴關系並從org.apache.beam
排除該版本。
您需要指定ProjectID:
SpannerIO.read()
.withProjectId("my_project")
.withInstanceId("my_instance")
.withDatabaseId("my_db")
您需要為Spanner項目設置憑據。 由於SpannerIO的API不允許您設置任何自定義憑據,因此必須使用環境變量GOOGLE_APPLICATION_CREDENTIALS設置全局應用程序憑據。
您還可以使用JDBC讀取(並寫入)Cloud Spanner。 閱讀是這樣完成的:
PCollection<KV<String, Long>> words = p2.apply(JdbcIO.<KV<String, Long>> read()
.withDataSourceConfiguration(JdbcIO.DataSourceConfiguration.create("nl.topicus.jdbc.CloudSpannerDriver",
"jdbc:cloudspanner://localhost;Project=my-project-id;Instance=instance-id;Database=database;PvtKeyPath=C:\\Users\\MyUserName\\Documents\\CloudSpannerKeys\\cloudspanner-key.json"))
.withQuery("SELECT t.table_name FROM information_schema.tables AS t").withCoder(KvCoder.of(StringUtf8Coder.of(), BigEndianLongCoder.of()))
.withRowMapper(new JdbcIO.RowMapper<KV<String, Long>>()
{
private static final long serialVersionUID = 1L;
@Override
public KV<String, Long> mapRow(ResultSet resultSet) throws Exception
{
return KV.of(resultSet.getString(1), resultSet.getLong(2));
}
}));
此方法還允許您通過設置PvtKeyPath來使用自定義憑據。 您也可以使用JDBC寫入Google Cloud Spanner。 看看這里的例子: http : //www.googlecloudspanner.com/2017/10/google-cloud-spanner-with-apache-beam.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.