【问题标题】:403 error when attempting to access Google Cloud Datastore through Dataflow尝试通过 Dataflow 访问 Google Cloud Datastore 时出现 403 错误
【发布时间】:2015-10-11 19:38:27
【问题描述】:

我有一个 Google App Engine 应用程序,其中数据存储在 Google Cloud Datastore 中。我想使用 Dataflow 将部分数据放入 BigQuery,但我想我首先从 Datastore 获取一些信息并将其写入 Google Cloud Storage。我的代码如下所示:

public class DatastorePipeline {
    private static final Logger LOG = LoggerFactory.getLogger(DatastorePipeline.class);

static class GetEmailFn extends DoFn<Entity, String> {

    @Override
    public void processElement(ProcessContext c) throws Exception {
        Map<String, Value> properties = DatastoreHelper.getPropertyMap(c.element());
        Value value = properties.get("email_address");
        if(value != null) {
            c.output(DatastoreHelper.getString(value));
        }
    }
}

    public static void main(String[] args) {
        Pipeline p = Pipeline.create(PipelineOptionsFactory.fromArgs(args).withValidation().create());

        Query.Builder q = Query.newBuilder();
        q.addKindBuilder().setName("User");
        Query query = q.build();

        DatastoreIO.Source source = DatastoreIO.source()
        .withDataset("my-project-id")
        .withQuery(query);

        p.apply("ReadUsersFromDatastore", Read.from(source))
        .apply(ParDo.named("GetEmailAddress").of(new GetEmailFn()))
        .apply(TextIO.Write.to("gs://dataflow-output-bucket/emails.txt"));

        p.run();
    }
}

但是,当我尝试运行此程序时,在进行数据存储区查询时出现 403 错误:

Request failed with code 403, will NOT retry: https://www.googleapis.com/datastore/v1beta2/datasets/my-project-id/runQuery

我使用 Google Cloud Dataflow 插件从 Eclipse 运行它。运行没有数据存储读取的数据流作业可以正常工作。我做了一个

gcloud auth login

在运行作业之前,如教程中所述。我做错了什么?

编辑:这是完整的堆栈跟踪。

2015 年 10 月 11 日下午 12:03:13 (b6119cca307b4d9a):com.google.api.services.datastore.client.DatastoreException:未经授权。在 com.google.api.services.datastore.client.RemoteRpc.makeException(RemoteRpc.java:115) 在 com.google.api.services.datastore.client.RemoteRpc.call(RemoteRpc.java:81) 在 com.google .api.services.datastore.client.BaseDatastoreFactory$RemoteRpc.call(BaseDatastoreFactory.java:41) 在 com.google.api.services.datastore.client.Datastore.runQuery(Datastore.java:109) 在 com.google.api .services.datastore.client.QuerySplitterImpl.getScatterKeys(QuerySplitterImpl.java:189) 在 com.google.api.services.datastore.client.QuerySplitterImpl.getSplits(QuerySplitterImpl.java:75) 在 com.google.cloud.dataflow.sdk .io.DatastoreIO$Source.getSplitQueries(DatastoreIO.java:427) 在 com.google.cloud.dataflow.sdk.io.DatastoreIO$Source.splitIntoBundles(DatastoreIO.java:306) 在 com.google.cloud.dataflow.sdk .runners.dataflow.BasicSerializableSourceFormat.performSplit(BasicSerializableSourceFormat.java:318) 在 com.google.cloud.dataflow.sdk.runners.dataflow.BasicSerializableSourceFormat.performSourceOperation(BasicSerializa bleSourceFormat.java:167) 在 com.google.cloud.dataflow.sdk.runners.worker.SourceOperationExecutor.execute(SourceOperationExecutor.java:80) 在 com.google.cloud.dataflow.sdk.runners.worker.DataflowWorker.executeWork( DataflowWorker.java:257) 在 com.google.cloud.dataflow.sdk.runners.worker.DataflowWorker.doWork(DataflowWorker.java:193) 在 com.google.cloud.dataflow.sdk.runners.worker.DataflowWorker.getAndPerformWork( DataflowWorker.java:146) 在 com.google.cloud.dataflow.sdk.runners.worker.DataflowWorkerHarness$WorkerThread.doWork(DataflowWorkerHarness.java:164) 在 com.google.cloud.dataflow.sdk.runners.worker.DataflowWorkerHarness$ WorkerThread.call(DataflowWorkerHarness.java:145) at com.google.cloud.dataflow.sdk.runners.worker.DataflowWorkerHarness$WorkerThread.call(DataflowWorkerHarness.java:132) at java.util.concurrent.FutureTask.run(FutureTask. java:266) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(T java.lang.Thread.run(Thread.java:745) 处的 readPoolExecutor.java:617) 原因:com.google.api.client.http.HttpResponseException: 403 Forbidden Unauthorized。在 com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1061) 在 com.google.api.services.datastore.client.RemoteRpc.call(RemoteRpc.java:78) ... 19 更多

回答:原来问题是我的项目根据我公司的域限制访问,这导致服务帐户无法连接。感谢 Dan 帮助我完成它!

【问题讨论】:

  • 很抱歉给您带来了麻烦。您可以编辑问题以包含错误的完整堆栈跟踪吗?
  • 看起来您正在使用DataflowPipelineRunner(或Blocking 变体)运行。DirectPipelineRunner 是否也会出现同样的错误?
  • 另外,这个错误每次都会发生,而不是偶尔发生,对吗?
  • 每次都会发生此错误,并且仅在 DataflowPipeLineRunner/Blocking 运行器上发生。它不会发生在 DirectPipelineRunner 上。

标签: java google-app-engine google-cloud-platform google-cloud-datastore google-cloud-dataflow


【解决方案1】:

您的数据存储区的权限似乎配置不正确。

这里有两条通用的建议:

  1. 查看Google Cloud Dataflow Security and Permissions 文档很有用。
  2. 数据存储区是在您运行作业时在同一个项目中创建的吗?

但是,在您的情况下,您遇到了以下错误:

  1. 关联的 AppEngine 项目是否对特定域的所有用户锁定?如果是这样,则当前 Cloud Datastore 测试版中存在一个问题,该问题会阻止 Dataflow 服务帐户(电子邮件以 @cloudservices.gserviceaccount.com 结尾)访问数据。

    如果您使用 OAuth API,我们可以应用一个临时解决方法,但费用较低。解决方法将不再强制用户来自您的应用程序的域。如果这对您来说很重要,您可以在代码中执行域强制。 (常规用户 API 不受影响。)

    要请求我们应用临时解决方法,您可以发送电子邮件至 dataflow-feedback@google.com 向我们发送电子邮件,提及此问题并附上您的数字项目 ID。

【讨论】:

  • 是的,数据存储区是在运行作业的同一项目中创建的。我查看了该文档,但没有发现我需要在任何地方为我的数据存储区设置权限。
  • 另外,我不知道这是否重要,但我没有该项目的所有者权限。我只有编辑权限。
  • 由于您不是所有者,我怀疑您遇到了我们以前没有处理过的权限问题。能否请您发送电子邮件至 dataflow-feedback@google.com?如果可能,请包括一个失败的 jobid(看起来像 2015-10-14_09_02_25-12818314609033999211)和您的数字项目编号。
  • 顺便问一下,赫伯特,如果这解决了你的问题,你能接受答案吗?
猜你喜欢
  • 1970-01-01
  • 2016-04-19
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 2017-04-25
  • 1970-01-01
  • 2022-12-19
  • 1970-01-01
相关资源
最近更新 更多