扩展对 App Engine 捆绑服务的支持:第 1 部分(模块 17)

1. 概览

无服务器迁移站系列 Codelab(自定进度的动手教程)和相关视频旨在帮助 Google Cloud 无服务器开发者通过一次或多次迁移(主要是从旧版服务迁移)来指导他们的应用现代化。这样做可让您的应用更易于移植,并为您提供更多选择和灵活性,使您能够与更多 Cloud 产品集成并访问这些产品,还能更轻松地升级到新的语言版本。虽然最初侧重于最早的 Cloud 用户(主要是 App Engine [标准环境] 开发者),但本系列文章的范围足够广,可涵盖其他无服务器平台(例如 Cloud FunctionsCloud Run),或者其他平台(如果适用)。

以前,开发者必须先从 App Engine 的旧版“捆绑服务”(例如 Datastore 和 Memcache)迁移,然后才能升级语言版本,这两个过程都可能非常具有挑战性。通过在第二代 App Engine 服务中提供许多关键的捆绑服务,开发者现在可以将应用移植到最新运行时,同时继续使用(大多数)捆绑服务。此 Codelab 将引导您完成以下操作:将示例应用从 Python 2 升级到 Python 3,同时继续使用 Datastore 捆绑服务(通过 App Engine NDB 库)。使用大多数捆绑服务只需要对代码进行小幅更新(本教程将对此进行介绍),但也有一些服务需要进行更广泛的更改;“第 2 部分”(后续模块和 Codelab)将对此进行介绍。

在接下来的实验中

  • 将示例 App Engine 应用从 Python 2 移植到 3
  • 更新应用配置以包含 App Engine SDK
  • 向应用添加 SDK 代码,以支持第二代运行时(例如 Python 3)中的捆绑服务

所需条件

调查问卷

您将如何使用本教程?

仅阅读教程内容 阅读并完成练习

您如何评价使用 Python 的体验?

新手水平 中等水平 熟练水平

您如何评价自己在使用 Google Cloud 服务方面的经验水平?

新手水平 中等水平 熟练水平

2. 背景

原始 App Engine 服务于 2008 年推出,并附带一组旧版 API(现在称为捆绑服务),以便开发者轻松构建和部署全球应用。这些服务包括 Datastore、Memcache 和任务队列。虽然使用专有 API 将应用绑定到 App Engine 很方便,但用户开始担心应用的便携性,希望应用更具便携性。此外,许多捆绑服务逐渐成熟,成为独立的 Cloud 产品,因此 App Engine 团队于 2018 年推出了下一代平台,但未包含这些服务。

如今,Python 2 开发者渴望升级到 Python 3。使用捆绑服务的 2.x 应用必须先从这些服务迁移,然后才能将应用移植到 3.x,这相当于连续两次强制迁移,而且可能非常具有挑战性。为了帮助完成此过渡,App Engine 团队于 2021 年秋季推出了“虫洞”功能,让在下一代运行时中运行的应用能够访问许多此类捆绑服务。虽然此版本不包含原始运行时环境中的所有服务,但 Datastore、任务队列和 Memcache 等主要服务已包含在内。

此 Codelab 演示了在保留对捆绑服务的使用的情况下,将应用升级到 Python 3 所需进行的更改。我们的目标是让您的应用在最新运行时上运行,这样您就可以按照自己的时间表将捆绑的服务迁移到 Cloud 独立等效服务或第三方替代方案,而不是让其成为 3.x 升级的障碍。虽然现在不再需要迁移到非捆绑服务,但这样做可让您在应用托管位置方面获得更高的可移植性和灵活性,包括迁移到可能更适合您的工作负载的平台,或者只是升级到更现代的语言版本(如上所述)的同时继续使用 App Engine。

模块 1 Python 2 示例应用通过 App Engine NDB 利用 Datastore 捆绑服务。该应用已将框架从 webapp2 迁移到 Flask(已在模块 1 Codelab 中完成),但其 Datastore 用法保持不变。

本教程包含以下步骤:

  1. 设置/准备工作
  2. 更新配置
  3. 修改应用代码

3. 设置/准备工作

本节介绍如何执行以下操作:

  1. 设置 Cloud 项目
  2. 获取基准示例应用
  3. (重新)部署并验证基准应用

这些步骤可确保您从正常运行的代码开始。

1. 设置项目

如果您已完成模块 1 Codelab,我们建议您重复使用同一项目(和代码)。或者,您可以创建一个全新的 Cloud 项目或重复使用另一个现有项目。确保该项目具有有效的结算账号,并且已启用 App Engine 服务。

2. 获取基准示例应用

此 Codelab 的前提条件之一是拥有一个有效的工作模块 1 App Engine 应用:完成模块 1 Codelab(推荐)或从代码库中复制模块 1 应用。无论您是使用自己的代码还是我们的代码,我们都能在模块 1 中“开始”。本 Codelab 将引导您完成每个步骤,最终获得类似于模块 7 代码库文件夹“FINISH”中的代码。

无论您使用哪个模块 1 应用,该文件夹都应如下所示,可能还包含 lib 文件夹:

$ ls
README.md               appengine_config.py     requirements.txt
app.yaml                main.py                 templates

3. (重新)部署基准应用

执行以下步骤以(重新)部署模块 1 应用:

  1. 删除 lib 文件夹(如果有),然后运行 pip install -t lib -r requirements.txt 以重新填充 lib。如果您同时安装了 Python 2 和 3,可能需要改用 pip2 命令。
  2. 确保您已安装初始化 gcloud 命令行工具,并已查看其用法。
  3. 如果您不想在每次发出 gcloud 命令时都输入 PROJECT_ID,请使用 gcloud config set project PROJECT_ID 设置您的云项目。
  4. 使用 gcloud app deploy 部署示例应用
  5. 确认模块 1 应用运行正常,可显示最近的访问记录(如下图所示)

a7a9d2b80d706a2b.png

4. 更新配置

成功执行完这些步骤并看到 Web 应用正常运行后,您就可以开始将此应用移植到 Python 3,首先从配置开始。

将 SDK 添加到 requirements.txt

App Engine Python 3 运行时显著降低了使用第三方库的开销。只需在 requirements.txt 中列出这些标头即可。如需在 Python 3 中使用捆绑服务,请向其中添加 App Engine SDK 软件包 appengine-python-standard。SDK 软件包与模块 1 中的 Flask 类似:

flask
appengine-python-standard

更新 app.yaml

请按照以下步骤将配置更改应用到 app.yaml 文件:

  1. runtime 指令替换为受支持的 Python 3 版本;例如,为 Python 3.10 指定 python310
  2. 删除 threadsafeapi_version 指令,因为 Python 3 中不使用这两者。
  3. 完全删除 handlers 部分,因为此应用只有脚本处理程序。如果您的应用具有静态文件处理程序,请在 handlers 中保持这些处理程序不变。
  4. Python 3 运行时不支持内置第三方库,而 Python 2 运行时支持。如果您的应用在 app.yaml 中包含 libraries 部分,请删除整个部分。(只需在 requirements.txt 中列出必需的软件包,就像列出非内置库一样。)我们的示例应用没有 libraries 部分,因此请继续执行下一步。
  5. 创建设置为 trueapp_engine_apis 指令,以便使用该指令 - 这与将 App Engine SDK 软件包添加到上面的 requirements.txt 相对应。

需要对 app.yaml 做出的更改摘要:

之前

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

升级后

runtime: python310
app_engine_apis: true

其他配置文件

由于所有第三方软件包只需要列在 requirements.txt 中,除非您在 appengine_config.py 中有特殊内容,否则不需要 appengine_config.py,因此请将其删除。同样,由于所有第三方库都会在构建流程中自动安装,因此无需复制或 vendoring 它们,这意味着不再需要 pip install 命令或 lib 文件夹,因此请将其删除。总结:

  • 删除 appengine_config.py 个文件
  • 删除 lib 个文件夹

至此,所有必要的配置更改都已完成。

5. 修改应用代码

如需在 Python 3 运行时环境中访问大多数可用的捆绑服务,您需要编写一小段代码,将 Web 服务器网关接口 (WSGI) 应用对象封装在 main.py 中。封装函数为 google.appengine.api.wrap_wsgi_app(),您可以通过导入该函数并使用它封装您的 WSGI 对象来使用它。进行以下更改,以反映 main.py 中 Flask 的必需更新:

之前

from flask import Flask, render_template, request
from google.appengine.ext import ndb

app = Flask(__name__)

升级后

from flask import Flask, render_template, request
from google.appengine.api import wrap_wsgi_app
from google.appengine.ext import ndb

app = Flask(__name__)
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)

如需查看其他 Python 框架的 WSGI 封装示例,请参阅文档

虽然此示例可让您的应用访问 Python 3 中的大多数捆绑服务,但 Blobstore 和 Mail 等其他服务需要额外的代码。我们将在另一个迁移模块中介绍这些示例。

至此,我们已完成所有必要的更改,以便在模块 1 示例应用中添加对 App Engine 捆绑服务的使用。该应用已与 Python 2 和 3 兼容,因此除了您已在配置中完成的更改之外,无需进行其他更改即可将其移植到 Python 3。最后一步:将修改后的应用部署到新一代 App Engine Python 3 运行时,并确认更新成功。

6. 总结/清理

本部分将通过部署应用来结束此 Codelab,并验证应用是否按预期运行以及是否在任何反映的输出中正常运行。应用验证完成后,请执行任何清理操作,并考虑后续步骤。

部署并验证应用

使用 gcloud app deploy 部署 Python 3 应用,并确认该应用与在 Python 2 中的运行方式相同。功能没有任何变化,因此输出应与模块 1 应用的输出相同:

a7a9d2b80d706a2b.png

结语

恭喜您迈出了第一步,将 Python 2 App Engine 应用移植到 Python 3,同时保留其对捆绑服务的使用。

清理

常规

如果您暂时不想继续操作,建议您停用 App Engine 应用,以免产生结算费用。不过,如果您想进一步测试或实验,App Engine 平台有免费配额,因此只要您不超过该使用层级,就不会产生费用。这是计算费用,但相关 App Engine 服务也可能会产生费用,因此请查看其价格页面了解详情。如果此迁移涉及其他 Cloud 服务,则这些服务会单独计费。在任何一种情况下,如果适用,请参阅下文中的“本 Codelab 特有的问题”部分。

为了完全公开透明,我们在此说明,部署到 Google Cloud 无服务器计算平台(例如 App Engine)会产生少量 build 和存储费用Cloud BuildCloud Storage 都有各自的免费配额。存储该图片会占用部分配额。不过,您可能居住在没有此类免费层的地区,因此请注意存储空间用量,以尽可能减少潜在费用。您应查看的特定 Cloud Storage“文件夹”包括:

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • 上述存储链接取决于您的 PROJECT_ID 和 *LOC*ation,例如,如果您的应用托管在美国,则为“us”。

另一方面,如果您不打算继续学习此应用或其他相关迁移 Codelab,并且想要彻底删除所有内容,请关闭您的项目

此 Codelab 特有的

以下列出的服务是此 Codelab 特有的。如需了解详情,请参阅各个产品的文档:

后续步骤

接下来,您可以从以下几个方面入手:

  1. 更新使用需要更多代码更改的捆绑服务的代码
  2. 从捆绑服务迁移到 Cloud 独立产品
  3. 从 App Engine 迁移到其他 Cloud 无服务器平台

访问其他捆绑服务(例如 BlobstoreMailDeferred)需要进行更多代码更改。以下迁移模块重点介绍了如何从 App Engine 旧版捆绑服务迁出,您可以考虑一下:

  • 模块 2:从 App Engine NDB 迁移到 Cloud NDB
  • 模块 7-9:从 App Engine TaskQueue(推送任务)迁移到 Cloud Tasks
  • 模块 12-13:从 App Engine Memcache 到 Cloud Memorystore
  • 模块 15-16:从 App Engine Blobstore 迁移到 Cloud Storage
  • 模块 18-19:从 App Engine TaskQueue(拉取任务)到 Cloud Pub/Sub

App Engine 不再是 Google Cloud 中唯一的无服务器平台。如果您有一个小型 App Engine 应用或功能有限的应用,并希望将其转换为独立的微服务,或者您希望将单体式应用拆分为多个可重用的组件,那么这些都是考虑迁移到 Cloud Functions 的充分理由。如果容器化已成为应用开发工作流的一部分,尤其是当它包含 CI/CD(持续集成/持续交付或部署)流水线时,请考虑迁移到 Cloud Run。以下模块涵盖了这些使用场景:

  • 从 App Engine 迁移到 Cloud Functions:请参阅模块 11
  • 从 App Engine 迁移到 Cloud Run:请参阅模块 4,了解如何使用 Docker 将应用容器化;或参阅模块 5,了解如何在不使用容器、Docker 知识或 Dockerfile 的情况下完成迁移

您可以选择改用其他无服务器平台,但我们建议您先考虑最适合您的应用和使用情形的选项,然后再进行任何更改。

无论您接下来考虑哪个迁移模块,都可以在 开源代码库中访问所有无服务器迁移站内容(Codelab、视频、源代码 [如有])。该代码库的 README 还提供了有关应考虑哪些迁移以及任何相关的迁移模块“顺序”的指南。

7. 其他资源

下面列出了其他资源,可供开发者进一步探索本迁移模块或相关迁移模块以及相关产品。这包括提供有关此内容的反馈的途径、指向代码的链接,以及您可能会觉得有用的各种文档。

Codelab 问题/反馈

如果您发现本 Codelab 存在任何问题,请先搜索您的问题,然后再提交。用于搜索和创建新问题的链接:

迁移时可参考的资源

下表中提供了指向模块 1(开始)和模块 1b(完成)的 Repo 文件夹的链接。您还可以通过所有 App Engine Codelab 迁移的代码库访问这些代码。

Codelab

Python 2

Python 3

模块 1

代码

不适用

第 17 模块(本 Codelab)

不适用

代码 (mod1b-flask)

在线资源

以下是一些可能与本教程相关的在线资源:

App Engine 捆绑服务

App Engine 常规文档

其他云信息

视频

许可

此作品已获得 Creative Commons Attribution 2.0 通用许可授权。