【问题标题】:Google Appengine & cloud storage : The AppIdentity service threw an unexpected errorGoogle Appengine 和云存储:AppIdentity 服务引发了意外错误
【发布时间】:2014-11-23 23:43:55
【问题描述】:

我正在尝试按照 sample from google 和 GcsExampleServlet.java 来设置 Google Cloud Storage 文件上传。我已经完成了所有步骤,但是当我将项目部署到 aggengine 并尝试在 GCS 中上传简单文本时,它会失败并显示以下日志:

com.google.appengine.tools.cloudstorage.NonRetriableException: com.google.appengine.tools.cloudstorage.NonRetriableException: com.google.appengine.api.appidentity.AppIdentityServiceFailureException: 
The AppIdentity service threw an unexpected error. Details: 
at com.google.appengine.tools.cloudstorage.RetryHelper.doRetry(RetryHelper.java:120)
at com.google.appengine.tools.cloudstorage.RetryHelper.runWithRetries(RetryHelper.java:166)
at com.google.appengine.tools.cloudstorage.RetryHelper.runWithRetries(RetryHelper.java:156)
at com.google.appengine.tools.cloudstorage.GcsServiceImpl.createOrReplace(GcsServiceImpl.java:70)
at com.appart.storage.server.GcsExampleServlet.doPost(GcsExampleServlet.java:88)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
(...)

不过,代码中并没有什么复杂的地方……在 web.xml 中,我已经配置了 servlet:

<servlet>
  <servlet-name>GcsExample</servlet-name>
    <servlet-class>
      com.example.server.GcsExampleServlet
    </servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>GcsExample</servlet-name>
  <url-pattern>/gcs/*</url-pattern>
</servlet-mapping>

这里是 servlet GcsExampleServlet.java(与谷歌示例完全相同):

@SuppressWarnings("serial")
public class GcsExampleServlet extends HttpServlet {

  private final GcsService gcsService = GcsServiceFactory.createGcsService(new RetryParams.Builder()
      .initialRetryDelayMillis(10)
      .retryMaxAttempts(10)
      .totalRetryPeriodMillis(15000)
      .build());     
  //...
  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException 
  {
    GcsOutputChannel outputChannel =
    gcsService.createOrReplace(getFileName(req), GcsFileOptions.getDefaultInstance());
    copy(req.getInputStream(), Channels.newOutputStream(outputChannel));
  }

  private void copy(InputStream input, OutputStream output) throws IOException {
    try {
      byte[] buffer = new byte[BUFFER_SIZE];
      int bytesRead = input.read(buffer);
      while (bytesRead != -1) {
        output.write(buffer, 0, bytesRead);
        bytesRead = input.read(buffer);
      }
    } finally {
      input.close();
      output.close();
    }
  }
}

这是我的 upload.html 文件:

<form action="/upload.html" enctype="text/plain" method="get" name="putFile" id="putFile">
   <div>
        Bucket: <input type="text" name="bucket" />
        File Name: <input type="text" name="fileName" />
        <br /> File Contents: <br />
        <textarea name="content" id="content" rows="3" cols="60"></textarea>
        <br />
        <input type="submit" onclick='uploadFile(this)' value="Upload Content" />
   </div>
</form>
<script>

  function uploadFile() {
    var bucket = document.forms["putFile"]["bucket"].value;
    var filename = document.forms["putFile"]["fileName"].value;
    if (bucket == null || bucket == "" || filename == null || filename == "") {
      alert("Both Bucket and FileName are required");
      return false;
    } else {
      var postData = document.forms["putFile"]["content"].value;
      document.getElementById("content").value = null;

      var request = new XMLHttpRequest();
      request.open("POST", "/gcs/" + bucket + "/" + filename, false);
      request.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
      request.send(postData);
    }
  }
</script>

我已启用计费,创建了一个存储桶,但 AppIdentity 错误仍然出现。我没有 Oauth,启用了云存储 API,用于上传的 appengine 帐户对存储桶具有写入权限。我什至尝试了一个

gsutil acl ch -u warm-particle-718@appspot.gserviceaccount.com:WRITE gs://ctrlxbucket

确保用户对我的存储桶具有写入权限。

请帮我弄清楚这个错误是什么意思,我从几天就一直呆在这里:(

非常感谢

PS:如果您只有一些 GCS 的工作示例(不是 google 的),我也会很高兴,因为围绕该主题的内容不多。

【问题讨论】:

  • 我最近创建的任何与 GCS 对话的 AppEngine 项目都有类似的问题。在 python AppEngine 代码中,我得到了与获取 GCS 访问的令牌代码相关的 InternalError。问题似乎是在任何新的 AppEngine 应用程序中都缺少凭据,例如如果您在开发控制台中查看 Api & auth -> Credentials,它可能没有服务帐户的“Compute Engine 和 AppEngine”客户端 ID。我有一个去年创建的旧版应用程序,但运行良好。
  • @Abhijit Kalamkar +1。我也一样。我的旧项目运行良好。但是 2 天前我用相同的代码创建了新项目,并且发生了这个错误。我还注意到 Compute Engine 凭据在新项目中消失了,但我想这不是因为 CtrlX 在此comment 中提到了 593689673236-compute@developer.gserviceaccount.com 帐户。我想解决方案是在一些 AppEngine 配置中。
  • @Juniper 解决了这个问题,在cloud.google.com/appengine/docs/python/googlecloudstorageclient/… 上看到了这个注释 注意:在一些不寻常的情况下,您可能无法使用“添加成员”表单添加您的服务帐户。如果发生这种情况,您必须将应用的服务帐号添加到存储桶 ACL。有关更多信息,请参阅授予您的存储桶或对象的权限。
  • @AbhijitKalamkar 听起来很有趣!我正在尝试您的解决方案,但是在文档中,当 gsutil 检索存储桶 ACL 时,它似乎是一个 xml。但我检索了一个 JSON。你有相同的 JSON ACL 文件吗?
  • @AbhijitKalamkar 实际上,它有效(使用 JSON 而不是文档中所说的 XML)!我必须添加 { "email": "warm-particle-718@appspot.gserviceaccount.com", "entity": "user-warm-particle-718@appspot.gserviceaccount.com", "role": "WRITER" } 到 myACL.txt 和 myDefAcl.txt 您能否创建一个答案而不是评论,以便我接受它? (尝试提供文档中提供的用于生成 ACL 的集合)再次感谢

标签: java google-app-engine google-cloud-storage


【解决方案1】:

尝试使用 XXX@developer.gserviceaccount.com 代替 warm-particle-718@appspot.gserviceaccount.com(将 XXX 替换为您的应用程序的项目 ID - 已采用 来自管理控制台的“管理/应用程序设置”中的“Google APIs 控制台项目编号”)。

【讨论】:

  • 此帐号 (593689673236-compute@developer.gserviceaccount.com) 已在权限中,并且工具提示说它用于在云平台外运行的代码。它试图重新添加它,但它仍然不起作用:(
  • 您从哪里运行此代码? VM 引擎或常规应用程序引擎前端或后端?如果后者尝试,593689673236@developer.gserviceaccount.com。你从哪里得到“-compute”部分?
  • 直接在 appengine 上运行所有代码,无需 VM,无需 localhost。 “前端”或“后端”是什么意思?在权限中,我添加了 593689673236@developer.gserviceaccount.com 但此电子邮件需要验证,我无权访问该邮箱。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-14
  • 2022-08-21
  • 2013-01-04
相关资源
最近更新 更多