适用于旧版捆绑服务的 Remote API

Java SDK 包含一个名为 Remote API 的库,它允许您通过任何 Java 应用透明地访问 App Engine 服务。例如,您可以从本地机器上运行的应用中,使用 Remote API 访问生产数据存储区。您还可以使用 Remote API 从一个 App Engine 应用访问另一个 App Engine 应用的数据存储区。

在服务器上配置 Remote API

Remote API 的服务器组件是一个 Java Servlet,是适用于 Java 的 App Engine 运行时的一部分。此 Servlet 从 Remote API 客户端接收请求,并将请求分派至相应的后端服务,然后将该服务调用的结果返回客户端。要安装 Remote API servlet,请将以下项添加至 web.xml

<servlet>
  <display-name>Remote API Servlet</display-name>
  <servlet-name>RemoteApiServlet</servlet-name>
  <servlet-class>com.google.apphosting.utils.remoteapi.RemoteApiServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>RemoteApiServlet</servlet-name>
  <url-pattern>/remote_api</url-pattern>
</servlet-mapping>

如果用户没有经过身份验证或经过身份验证的用户不是应用的管理员,则 Servlet 会返回错误,因此您不需要额外进行安全配置。对应用部署这些设置后,已安装 Remote API 客户端的任何应用都可以使用该客户端的服务。 其中包括使用 Python Remote API 的 Python 客户端。

在独立客户端上配置 Remote API

要为内部使用的 Java 应用程序配置 Remote API 的客户端组件,请将 ${SDK_ROOT}/lib/impl/appengine-api.jar${SDK_ROOT}/lib/appengine-remote-api.jar 添加至类路径。然后在代码中配置并安装 Remote API:

import com.google.appengine.tools.remoteapi.RemoteApiInstaller;
import com.google.appengine.tools.remoteapi.RemoteApiOptions;

// ...
RemoteApiOptions options = new RemoteApiOptions()
    .server("[APP_ID].[REGION_ID].r.appspot.com", 443)
    .useApplicationDefaultCredential();

RemoteApiInstaller installer = new RemoteApiInstaller();
installer.install(options);
// ... all API calls executed remotely
installer.uninstall();

Remote API 客户端将依赖使用 OAuth 2.0 的应用默认凭据。

要获取凭据,请运行以下命令:

gcloud auth application-default login

您可以轻松连接到在开发服务器中本地运行的 App Engine 应用:

RemoteApiOptions options = new RemoteApiOptions()
    .server("localhost", 8888) // server name must equal "localhost"
    .useDevelopmentServerCredential();

下面是一个完整的 Java 应用,它可在运行时向数据存储区插入一个实体:

public class RemoteApiExample {

  public static void main(String[] args) throws IOException {
    String serverString = args[0];
    RemoteApiOptions options;
    if (serverString.equals("localhost")) {
      options = new RemoteApiOptions().server(serverString,
        8080).useDevelopmentServerCredential();
    } else {
      options = new RemoteApiOptions().server(serverString,
        443).useApplicationDefaultCredential();
    }
    RemoteApiInstaller installer = new RemoteApiInstaller();
    installer.install(options);
    try {
      DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
      System.out.println("Key of new entity is " + ds.put(new Entity("Hello Remote API!")));
    } finally {
      installer.uninstall();
    }
  }
}

在 App Engine 客户端上配置 Remote API

您还可以使用 Remote API 从一个 App Engine 应用访问另一个 App Engine 应用的服务。您需要将 ${SDK_ROOT}/lib/appengine-remote-api.jar 添加到 WEB-INF/lib 目录,然后在 App Engine 客户端应用中配置并安装 Remote API,正如您在独立 Java 客户端中执行的操作一样。

请注意,RemoteApiInstaller 仅在执行安装的线程上安装 Remote API,因此切勿跨线程共享此类的实例。

将 Remote API 与 Maven 结合使用

要在 Maven 项目中使用 Remote API 功能,请将以下依赖项添加到项目的 pom.xml 文件中:

<dependency>
  <groupId>com.google.appengine</groupId>
  <artifactId>appengine-remote-api</artifactId>
  <version>1.9.64</version>
</dependency>
<dependency>
  <groupId>com.google.appengine</groupId>
  <artifactId>appengine-api-1.0-sdk</artifactId>
  <version>1.9.64</version>
</dependency>

限制和最佳做法

remote_api 模块竭尽全力来确保尽可能表现得像本地 App Engine 数据存储区。在某些情况下,这意味着处理效率可能会相对低下。使用 remote_api 时,需牢记以下几点:

每一个数据存储区请求都需要一个往返

因为您通过 HTTP 访问数据存储区,所以开销和延迟会略多于本地访问数据存储区。为了加快速度和降低负载,请尝试通过批处理获取内容和写入内容,并从查询提取批量实体来限制往返次数。这不仅适用于 remote_api,也适用于数据存储区的常规使用,因为批处理操作仅被视为单个数据存储区操作。

对 remote_api 使用配额的请求

由于 remote_api 通过 HTTP 运行,您进行的每个数据存储区调用都会产生对以下配额的使用:HTTP 请求、输入和输出字节,以及常规的数据存储区配额。如果您使用 remote_api 来进行批量更新,请牢记这一点。

1 MB API 限制

在本地运行时,对于 API 请求和响应的 1MB 限制仍然适用。如果您的实体特别大,则可能需要限制一次提取或放置的数量,以免超过此限制。但这与最小化往返次数存在冲突,因此最好的建议是尽可能使用最大的批而不超过请求或响应大小限制。但对于大多数实体来说,这不太可能成为问题。

避免迭代查询

当您进行迭代查询时,SDK 以 20 为一个批次,从数据存储区中提取实体,每当用完现有批次时就提取一个新的批次。由于每一批次都必须在单独请求中由 remote_api 提取,因此这种做法的效率没那么高。反之,remote_api 对每一批次执行一个全新的查询,使用偏移功能来进一步接近结果。

如果您知道所需实体的数目,则可以通过请求所需的数量来在一个请求中完成全部提取。

如果您不知道需要多少实体,则可以使用游标高效地迭代大型结果集。这还可以避开对常规数据存储区查询施加的 1000 实体的限制。

事务效率较低

为通过 remote_api 实施事务,它累积有关在事务内提取的实体的信息,以及在事务内放置或删除的实体的副本。事务被提交时会向 App Engine 服务器发送所有这些信息。在 App Engine 服务器中,事务必须再次提取事务中所使用的所有实体,验证这些实体未被修改,然后放置和删除事务所做的所有更改并将其提交。如果有冲突,服务器将回滚事务并通知客户端,然后客户端必须再次重复这一过程。

此方法可行,并能准确提供由事务在本地数据存储区上提供的功能,但是效率相当低下。在必要时,请务必使用事务,但出于效率的考虑,建议尽量限制所执行事务的数量和复杂性。