尝试通过数据流访问Google Cloud Datastore时出现403错误

时间:2015-10-11 19:38:28

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

我有一个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的com.google.api.services.datastore.client.Datastore.runQuery(Datastore.java:109) com.google.cloud.dataflow.sdk上com.google.api.services.datastore.client.QuerySplitterImpl.getSplits(QuerySplitterImpl.java:75)的.services.datastore.client.QuerySplitterImpl.getScatterKeys(QuerySplitterImpl.java:189) com.google.cloud.dataflow.sdk上的com.google.cloud.dataflow.sdk.io.DatastoreIO $ Source.splitIntoBundles(DatastoreIO.java:306)上的.io.DatastoreIO $ Source.getSplitQueries(DatastoreIO.java:427) .runners.dataflow.BasicSerializableSourceFormat.performSplit(BasicSerializableSourceFormat.java:318)at 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)at com.google.cloud.dataflow.sdk.runners.worker.DataflowWorker.executeWork( DataflowWorker.java:257)com.google.cloud.dataflow.sdk.runners.worker.DataflowWorker.doWork(DataflowWorker.java:193)at 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)at com.google.cloud.dataflow.sdk.runners.worker.DataflowWorkerHarness $ WorkerThread.call(DataflowWorkerHarness.java:145)位于java.util.concurrent.FutureTask.run(FutureTask。)的com.google.cloud.dataflow.sdk.runners.worker.DataflowWorkerHarness $ WorkerThread.call(DataflowWorkerHarness.java:132)。 java:266)java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor $ Worker.run(T hreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)引起: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更多< / p>

回答:原来问题是我的项目限制了基于我公司域名的访问权限,这阻止了服务帐户的连接。感谢Dan帮助我完成它!

1 个答案:

答案 0 :(得分:2)

看起来您的数据存储区的权限配置不正确。

以下是两条通用建议:

  1. 查看Google Cloud Dataflow Security and Permissions文档非常有用。
  2. 数据存储是否在您运行作业的同一项目中创建?
  3. 但是,在您的情况下,您遇到了以下错误:

    1. 关联的AppEngine项目是否已锁定到特定域的所有用户?如果是这样,当前的云数据存储测试版中存在一个问题,即阻止Dataflow服务帐户(例如,@cloudservices.gserviceaccount.com的电子邮件)访问数据。

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

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