Java 8 运行时环境

通过 App Engine,您可以构建使用 Google 的可扩展基础架构和服务的网页应用。 App Engine 使用 Java 8 JVM 运行 Web 应用。在此环境中,App Engine 会调用应用的 servlet 类来处理请求并准备响应。

App Engine 平台中内置了许多 API 服务,可供您的代码进行调用。您的应用还可以配置以指定时间间隔运行的计划任务

为您的应用指定 Java 8 运行时

如需让您的应用使用 Java 8 运行时,请在 appengine-web.xml 文件中添加以下行:

<runtime>java8</runtime>

请注意,之前使用 Java 7 运行时的现有 App Engine 应用只需进行上述更改即可在 Java 8 运行时中运行。

Java 版 App Engine API 由 Cloud SDK 中的 App Engine SDK 附带的 appengine-api-*.jar 表示(其中 * 表示 API 和 App Engine SDK 的版本)。

您可以通过在应用的 WEB-INF/lib/ 目录中添加此 JAR 来选择应用使用的 API 版本,或使用 Maven 来处理依赖项。如果发布了新版本的 Java 运行时环境,而该版本引入了与现有应用不兼容的更改,则该环境将具有新的主要版本号。

使用 Maven 处理依赖项

您可以使用 Maven 来管理所有依赖项。 例如,此 pom.xml 条目包含 Maven Central 提供的最新 App Engine API (Rappengine-api-1.0-sdk):

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

沙盒

App Engine Java 运行时跨多个网络服务器分发应用请求,可防止应用之间相互干扰。 App Engine 应用的响应速度不能太慢。 向应用发出的网络请求必须在请求超时限制内进行处理。在此时限内未做出响应的进程会被终止,以避免网络服务器过载。

请注意,用户只能将文件写入到 /tmp 目录。 /tmp 中的文件将占用分配给您的实例的内存。存储在此位置的文件仅供该实例使用,且仅可在该特定实例的生命周期内使用。

应用获取资源文件的常用方法是,使用应用将您所依赖的文件打包到 WEB-INF 下,然后使用 Class.getResource()ServletContext.getResource() 或类似方法从应用中加载这些文件。默认情况下,WAR 中的所有文件都是“资源文件”。 您可以使用 appengine-web.xml 文件将文件从此集中排除。

类加载器 JAR 排序

有时,为了解决类名称之间的冲突,可能需要重新定义扫描 JAR 文件以查找类的顺序。在这些情况下,可以通过在 appengine-web.xml 文件中添加包含 <priority-specifier> 元素的 <class-loader-config> 元素,将加载优先级授予特定 JAR 文件。例如:

<class-loader-config>
  <priority-specifier filename="mailapi.jar"/>
</class-loader-config>

这会将“mailapi.jar”作为第一个进行类搜索的 JAR 文件,而禁止目录 war/WEB-INF/classes/ 中的那些文件。

如果多个 JAR 文件已按优先顺序排序,则将使用其原始加载顺序(相对于彼此)。换句话说,<priority-specifier> 元素本身的顺序无关紧要。

线程

在 Java 8 运行时中,您可以使用 App Engine 的 ThreadManager API 和 Java 的内置 API(例如 new Thread())创建线程。目前,如果要调用 App Engine API (com.google.appengine.api.*),您必须从请求线程或使用 ThreadManager API 创建的线程中调用这些 API。

应用可以执行以下操作:

如果您通过 currentRequestThreadFactory() 创建 ThreadPoolExecutor,则必须在 Servlet 请求完成之前明确调用 shutdown()。否则,请求将无法完成,并且应用服务器最终会失败。 请注意,某些库可能会为您创建 ThreadPoolExecutor。

应用程序可以对当前线程执行操作,例如 thread.interrupt()

每个请求仅限于 50 个并发 App Engine API 请求线程。

使用线程时,请使用高级并发对象,例如 ExecutorRunnable。这些对象可处理许多细微但非常重要的并发细节,如中断调度和簿记

对于每个实例,App Engine API 最多创建 10 个并发后台线程。 (此限制不适用于与 App Engine API 无关的常规 Java 线程。)

工具

支持的 IDE

对于 App Engine 项目,Cloud Tools for EclipseEclipse IDE 中添加了新的项目向导和调试配置。您可以从 Eclipse 内将 App Engine 项目实时部署到生产环境中。

通过 Cloud Tools for IntelliJ,您可以在 IntelliJ IDEA 内运行和调试 App Engine 应用。您可以在 IDE 内将 App Engine 项目实时部署到生产环境中。

支持的构建工具

为加快开发过程,您可以使用适用于 Apache Maven 或 Gradle 的 App Engine 插件:

本地开发服务器

开发服务器在本地计算机上运行您的应用以进行开发和测试。服务器模拟 Datastore 服务。开发服务器还可以根据应用在测试期间执行的查询生成 Datastore 索引的配置。

并发和延迟

应用的延迟对处理流量所需的实例数量影响最大。如果您快速处理请求,则单个实例可以处理大量请求。

单线程实例可以处理一个并发请求。 因此,延迟时间与每秒可在实例上处理的请求数之间存在着直接关系。例如,10 毫秒的延迟时间等同于每个实例每秒处理 100 个请求。

多线程实例可以处理多个并发请求。因此,所用 CPU 与每秒请求数之间存在直接关系。

Java 应用支持并发请求,因此单个实例可以在等待其他请求完成时处理新的请求。并发处理能力可显著减少应用所需的实例数量,但您需要设计应用以实现多线程。

例如,如果 B4 实例(大约 2.4GHz)为每个请求消耗 10 个兆周期,则每个实例每秒可以处理 240 个请求。如果它为每个请求消耗 100 个兆周期,则每个实例每秒可以处理 24 个请求。这些数字是理想的情况,但就您可以在实例上完成的任务而言,它们相当贴近实际情况。

环境变量

以下环境变量由运行时设置:

环境变量 说明
GAE_APPLICATION App Engine 应用的 ID。此 ID 以“region code~”为前缀,例如“e~”(对于在欧洲部署的应用)。
GAE_DEPLOYMENT_ID 当前部署的 ID。
GAE_ENV App Engine 环境。设置为 standard
GAE_INSTANCE 当前运行您的服务的实例的 ID。
GAE_RUNTIME app.yaml 文件中指定的运行时环境。
GAE_SERVICE app.yaml 文件中指定的服务名称。如果未指定服务名称,则将其设置为 default
GAE_VERSION 服务的当前版本标签。
GOOGLE_CLOUD_PROJECT 与您的应用关联的 Cloud 项目 ID。
PORT 接收 HTTP 请求的端口。

您可以app.yaml 文件中定义其他环境变量,但不能替换上述值。