迁移到适用于 App Engine 的 Cloud Endpoints Frameworks 2.0 版

本页面介绍如何将现有 Cloud Endpoints 1.0 版应用迁移到 Java 版适用于 App Engine 的 Endpoints Frameworks

优势

新版框架具有诸多优势,具体如下所示:

  • 缩短了请求延迟时间。
  • 可更好地与 App Engine 功能(例如自定义网域)集成。
  • 提供对 Guice 配置的官方支持。
  • 提供多种新的 API 管理功能供您选择。

Endpoints Frameworks 2.0 版不会影响 API 的接口。迁移后,现有客户端仍可继续运行,无需更改任何客户端代码。

目前不包含的功能和工具

目前不支持以下功能。如果您需要使用其中任何功能,请提交功能请求

  • JSON-RPC 协议,这是旧版 iOS 客户端所需的功能。要为您的 Endpoints Frameworks 2.0 API 创建 iOS 客户端,我们建议您使用适用于 REST API 的 Google API Objective-C 客户端库
  • 自动 ETag
  • 自动 kind 字段
  • IDE 集成
  • fields 部分响应
  • 自动创建 PATCH API 方法

此外,Android Studio 对 Endpoints 1.0 版的支持目前不适用于 2.0 版。

迁移到 Endpoints Frameworks 2.0 版

Framepoints 2.0 版已移至 Maven 工件中的 com.google.endpoints 组。所需的基本 JAR 位于 endpoints-framework 工件中。如果您希望使用 Guice 配置,请添加 endpoints-framework-guice 工件。

以下说明举例介绍了如何使用发现文档从 Endpoints Frameworks 1.0 版迁移到 Endpoints Frameworks 2.0 版:

  • 下载并初始化 Cloud SDK
  • 运行以下命令:
    1. 确保 Cloud SDK 有权访问您在 Google Cloud 上的数据和服务:
      gcloud auth login
    2. 使用应用默认凭据:
      gcloud auth application-default login
    3. 安装 Cloud SDK app-engine-java 组件:
      gcloud components install app-engine-java
    4. 更新为 Cloud SDK 和所有组件的最新版本:
      gcloud components update
  • 使用 Maven 或 Gradle 迁移:

    Maven

    1. 移除旧版依赖项,即 appengine-endpoints 工件:
      <dependency>
            <groupId>com.google.appengine</groupId>
            <artifactId>appengine-endpoints</artifactId>
            <version>1.9.53</version>
      </dependency>
    2. 添加新版 Endpoints Frameworks 依赖项:
      <dependency>
          <groupId>com.google.endpoints</groupId>
          <artifactId>endpoints-framework</artifactId>
          <version>2.2.1</version>
      </dependency>
    3. 添加新版 Endpoints Frameworks 插件,并为生成的发现文档定义主机名:
      <plugin>
          <groupId>com.google.cloud.tools</groupId>
          <artifactId>endpoints-framework-maven-plugin</artifactId>
          <version>1.0.2</version>
          <configuration>
              <!-- plugin configuration -->
              <hostname>YOUR-PROJECT-ID.appspot.com</hostname>
          </configuration>
      </plugin>
    4. 添加新版 App Engine Maven 插件:
      <plugin>
          <groupId>com.google.cloud.tools</groupId>
          <artifactId>appengine-maven-plugin</artifactId>
          <version>1.3.2</version>
          <configuration>
              <!-- deploy configuration -->
          </configuration>
      </plugin>
    5. 更新项目 web.xml 文件中的 API 入口点:
      • 将出现的所有 SystemServiceServlet 重命名为 EndpointsServlet
      • 将出现的所有 /_ah/spi/ 路径替换为新的必需路径 /_ah/api/

      以下显示迁移前后的 web.xml 内容:

      迁移前

      Endpoints Frameworks 1.0 版 web.xml
      <servlet>
          <servlet-name>SystemServiceServlet</servlet-name>
          <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
          <init-param>
              <param-name>services</param-name>
              <param-value>com.example.helloendpoints.Greetings</param-value>
          </init-param>
          <init-param>
              <param-name>restricted</param-name>
              <param-value>false</param-value>
          </init-param>
      </servlet>
      <servlet-mapping>
          <servlet-name>SystemServiceServlet</servlet-name>
          <url-pattern>/_ah/spi/*</url-pattern>
      </servlet-mapping>

      迁移后

      Endpoints Frameworks 2.0 版 web.xml
      <servlet>
          <servlet-name>EndpointsServlet</servlet-name>
          <servlet-class>com.google.api.server.spi.EndpointsServlet</servlet-class>
          <init-param>
              <param-name>services</param-name>
              <param-value>com.example.helloendpoints.Greetings</param-value>
          </init-param>
          <init-param>
              <param-name>restricted</param-name>
              <param-value>false</param-value>
          </init-param>
      </servlet>
      <servlet-mapping>
          <servlet-name>EndpointsServlet</servlet-name>
          <url-pattern>/_ah/api/*</url-pattern>
      </servlet-mapping>

    6. 修改依赖项后,清理项目:
      mvn clean
    7. 您可以生成发现文档:
      mvn endpoints-framework:discoveryDocs
      详细了解 Maven Endpoints Frameworks 插件目标
    8. 您可以部署项目:
      mvn appengine:deploy

      详细了解 Maven App Engine 插件目标

    Gradle

    1. 移除旧版依赖项,即 appengine-endpoints 工件:
      compile group: 'com.google.appengine', name: 'appengine-endpoints', version: '+'
    2. 添加新版 Endpoints Frameworks 依赖项:
      compile group: 'com.google.endpoints', name: 'endpoints-framework', version: '2.0.8'
    3. 添加新版 App Engine 和 Endpoints Frameworks 插件:
      buildscript {    // Configuration for building
        repositories {
          mavenCentral()
          jcenter()    // Bintray's repository - a fast Maven Central mirror & more
        }
        dependencies {
          // App Engine Gradle plugin
          classpath 'com.google.cloud.tools:appengine-gradle-plugin:1.3.3'
      
          // Endpoints Frameworks Gradle plugin
          classpath 'com.google.cloud.tools:endpoints-framework-gradle-plugin:1.0.2'
        }
      }
    4. 应用新版 App Engine 和 Endpoints Frameworks 插件:
      apply plugin: 'com.google.cloud.tools.appengine'
      apply plugin: 'com.google.cloud.tools.endpoints-framework-server'
    5. 为生成的发现文档定义主机名端点:
      endpointsServer {
        // Endpoints Framework Plugin server-side configuration
        hostname = "YOUR-PROJECT-ID.appspot.com"
      }
    6. 更新项目 web.xml 文件中的 API 入口点:
      • 将出现的所有 SystemServiceServlet 重命名为 EndpointsServlet
      • 将出现的所有 /_ah/spi/ 路径替换为新的必需路径 /_ah/api/

      以下显示迁移前后的 web.xml 内容:

      迁移前

      Endpoints Frameworks 1.0 版 web.xml
      <servlet>
          <servlet-name>SystemServiceServlet</servlet-name>
          <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
          <init-param>
              <param-name>services</param-name>
              <param-value>com.example.helloendpoints.Greetings</param-value>
          </init-param>
          <init-param>
              <param-name>restricted</param-name>
              <param-value>false</param-value>
          </init-param>
      </servlet>
      <servlet-mapping>
          <servlet-name>SystemServiceServlet</servlet-name>
          <url-pattern>/_ah/spi/*</url-pattern>
      </servlet-mapping>

      迁移后

      Endpoints Frameworks 2.0 版 web.xml
      <servlet>
          <servlet-name>EndpointsServlet</servlet-name>
          <servlet-class>com.google.api.server.spi.EndpointsServlet</servlet-class>
          <init-param>
              <param-name>services</param-name>
              <param-value>com.example.helloendpoints.Greetings</param-value>
          </init-param>
          <init-param>
              <param-name>restricted</param-name>
              <param-value>false</param-value>
          </init-param>
      </servlet>
      <servlet-mapping>
          <servlet-name>EndpointsServlet</servlet-name>
          <url-pattern>/_ah/api/*</url-pattern>
      </servlet-mapping>

    7. 修改依赖项后,使用以下命令清理项目:
      gradle clean
    8. 您可以使用以下命令生成发现文档:
      gradle endpointsDiscoveryDocs
      详细了解 Gradle Endpoints Frameworks 插件任务
    9. 您可以使用以下命令部署项目:
      gradle appengineDeploy

      详细了解 Gradle App Engine 插件任务

    使用 Guice 配置 Java 版 Endpoints Frameworks

    若要使用 Guice,请执行以下操作:

    1. 添加新版 Endpoints Frameworks Guice 依赖项:

      Maven

      <dependency>
          <groupId>com.google.endpoints</groupId>
          <artifactId>endpoints-framework-guice</artifactId>
          <version>2.2.1</version>
      </dependency>

      Gradle

      compile 'com.google.endpoints:endpoints-framework-guice:2.0.9'
    2. 声明一个继承 EndpointsModule 的新模块并对其进行配置,如下所示:
      public class EchoEndpointModule extends EndpointsModule {
        @Override
        public void configureServlets() {
          super.configureServlets();
      
          bind(ServiceManagementConfigFilter.class).in(Singleton.class);
          filter("/_ah/api/*").through(ServiceManagementConfigFilter.class);
      
          Map<String, String> apiController = new HashMap<String, String>();
          apiController.put("endpoints.projectId", "YOUR-PROJECT-ID");
          apiController.put("endpoints.serviceName", "YOUR-PROJECT-ID.appspot.com");
      
          bind(GoogleAppEngineControlFilter.class).in(Singleton.class);
          filter("/_ah/api/*").through(GoogleAppEngineControlFilter.class, apiController);
      
          bind(Echo.class).toInstance(new Echo());
          configureEndpoints("/_ah/api/*", ImmutableList.of(Echo.class));
        }
      }

    验证新的部署

    您可以验证新框架是否正在处理流量:

    1. 向新部署发送一些请求。
    2. 在 Cloud Console 中,转到 Stackdriver Logging > 日志(日志查看器)页面。

      转到“日志查看器”页面

    3. 如果请求显示的路径以 /_ah/api 开头,表示 Endpoints Frameworks 2.0 版现在正在处理您的 API 请求。日志不应显示任何路径以 /_ah/spi 开头的请求。这样的请求表明 Endpoints Frameworks 1.0 版代理仍在处理请求。

    添加 Endpoints API 管理

    使用 Endpoints Frameworks 2.0 版,您还可以开启 API 管理功能,其中包括:

    • API 密钥管理
    • API 共享
    • 用户身份验证
    • API 指标
    • API 日志

    要开始使用这些功能,请参阅添加 API 管理

    问题排查

    本部分介绍迁移到 Endpoints Frameworks 2.0 时一些常见的异常行为以及建议的解决方案。

    API 返回 404 错误,但 API Explorer 仍会正确列出 API

    迁移到 Endpoints Frameworks 2.0 版时,您需要移除旧版 Endpoints Frameworks 1.0 版配置。如果应用配置中仍然存在旧配置,则 Endpoints 服务会继续将应用视为 1.0 版应用。您可能会在 App Engine 日志中看到发送到 /_ah/spi 的请求,导致向客户端发送 HTTP 404 错误。

    1. 如果您的 web.xml 文件中存在以下几行内容,请将其删除:

      <servlet>
          <servlet-name>SystemServiceServlet</servlet-name>
          <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
          <init-param>
              <param-name>services</param-name>
              <param-value>...</param-value>
          </init-param>
      </servlet>
      <servlet-mapping>
          <servlet-name>SystemServiceServlet</servlet-name>
          <url-pattern>/_ah/spi/*</url-pattern>
      </servlet-mapping>
      
    2. 请确保您的 web.xml 文件包含以下内容:

      <servlet-mapping>
          <servlet-name>EndpointsServlet</servlet-name>
          <url-pattern>/_ah/api/*</url-pattern>
      </servlet-mapping>
      

    API 抛出反射错误

    您只能将 endpoints-framework 工件打包到您的应用中,而不是旧的 appengine-endpoints JAR。如果您部署同时包含这两个 JAR 的应用,则可能会遇到反射错误或运行时类型错误,例如 NoClassDefFoundErrorNoSuchMethodErrorClassCastException。请从构建文件中移除以下行(如果存在):

    Maven

    <dependency>
          <groupId>com.google.appengine</groupId>
          <artifactId>appengine-endpoints</artifactId>
          <version>1.9.53</version>
    </dependency>

    Gradle

    compile group: 'com.google.appengine', name: 'appengine-endpoints', version: '+'

    此外,如果其他任何依赖项依赖旧版 Guava,系统也可能指示缺少 TypeToken 方法。您必须确保使用 Guava v19 或使用 endpoints-framework-all 工件(此工件会隐藏依赖项)。

    客户端库源代码无法编译

    如果您看到 method does not override or implement a method from a supertypecannot find symbol method setBatchPath(String) 这样的错误,那么您的客户端应用可能依赖于旧版本的 Google Java 客户端库。您必须确保 google-api-client 工件为 1.23.0 或更高版本。

    Maven

    <dependency>
        <groupId>com.google.api-client</groupId>
        <artifactId>google-api-client</artifactId>
        <version>1.23.0</version>
    </dependency>

    Gradle

    compile group: 'com.google.api-client', name: 'google-api-client', version: '1.23.0'

    IJPA/JDO Datanucleus 增强功能问题

    Maven

    基于 Cloud SDK 的新版 App Engine Maven 插件不支持任何类型的 Datanucleus 增强功能。如果您的项目使用旧版插件中支持的 Datanucleus JDO 或 JPA 增强功能,则必须在迁移时单独配置第三方 Datanucleus Maven 插件。如需了解详情,请参阅以下内容:

    Gradle

    如果您的项目使用 gradle-appengine-plugin JPA/JDO Datanucleus 增强功能,则必须在切换到新的基于 Cloud SDK 的 Gradle 插件后手动配置 Datanucleus 增强功能。请参阅 Stackoverflow 中的示例