1. 概览
无服务器迁移站系列 Codelab(自定进度的动手教程)和相关视频旨在帮助 Google Cloud 无服务器开发者通过一次或多次迁移(主要是从旧版服务迁移)来指导他们的应用现代化。这样做可让您的应用更易于移植,并为您提供更多选择和灵活性,使您能够与更多 Cloud 产品集成并访问这些产品,还能更轻松地升级到新的语言版本。虽然最初侧重于最早的 Cloud 用户(主要是 App Engine [标准环境] 开发者),但本系列文章的范围足够广,可涵盖其他无服务器平台(例如 Cloud Functions 和 Cloud Run),或者其他平台(如果适用)。
本 Codelab 将介绍如何将 App Engine Memcache 纳入 模块 1 Codelab 中的示例应用并加以使用。我们在本模块 12 教程中添加了 Memcache 的使用,然后在模块 13 中迁移到 Cloud Memorystore。
在接下来的实验中
- 使用 App Engine Memcache API/库
- 向基本的 Python 2 Flask App Engine NDB 应用添加缓存
所需条件
- 具有有效的 GCP 结算账号的 Google Cloud Platform 项目
- 基本 Python 技能
- 常用 Linux 命令的实践知识
- 具备开发和部署 App Engine 应用的基础知识
- 有效的模块 1 App Engine 应用(完成其 Codelab [推荐] 或从代码库复制应用)
调查问卷
您将如何使用本教程?
您如何评价使用 Python 的体验?
您如何评价自己在使用 Google Cloud 服务方面的经验水平?
2. 背景
为了从 App Engine Memcache 进行迁移,请将它的使用情况添加到模块 1 Codelab 中生成的现有 Flask 和 App Engine NDB 应用。示例应用会向用户显示最近的 10 次访问。如果同一用户刷新浏览器,持续创建新的 Visit 实体并从 Datastore 中提取最近的访问记录并非最佳做法,因此我们将缓存这些最近的访问记录。
如果同一位访问者再次访问该网页,则系统会从缓存中返回这些访问。如果新用户访问该网站或一小时后,系统会清空缓存并将其替换为最新条目(更不用说注册新的访问)。在实现此 App Engine Memcache 集成后,我们可以在下一个 Codelab(模块 13)中将其迁移到 Cloud Memorystore。
本教程包含以下步骤:
- 设置/准备工作
- 更新配置
- 修改应用代码
3. 设置/准备工作
在开始学习本教程的主要部分之前,让我们设置项目、获取代码,然后部署基准应用,以便我们知道我们从工作代码开始。
1. 设置项目
如果您已完成模块 1 Codelab,我们建议您重复使用同一项目(和代码)。或者,您可以创建一个全新的项目或重复使用另一个现有项目。确保该项目具有有效的结算账号,并且已启用 App Engine。
2. 获取基准示例应用
此 Codelab 的先决条件之一是拥有一个工作正常的模块 1 示例应用。如果您没有,请先完成其中一个教程(上面的链接),然后再继续学习。或者,如果您已经熟悉其内容,可以直接从下面的模块 1 代码开始。
无论您是使用自己的代码还是我们的代码,我们都能在模块 1 中。本 Codelab 将引导您完成每个步骤,最后获得类似于模块 11 代码库文件夹 (FINISH) 中的代码。
模块 1 启动文件(您或我们的文件)的目录应如下所示:
$ ls README.md main.py templates app.yaml requirements.txt
3. (重新)部署基准应用
您现在需要执行的剩余预处理步骤:
- 重新熟悉
gcloud命令行工具 - 使用
gcloud app deploy重新部署示例应用 - 确认应用在 App Engine 上运行没有任何问题
成功执行完这些步骤并看到您的 Web 应用正常运行(输出类似于下方所示)后,您就可以为应用添加缓存使用功能了。

4. 更新配置
无需对标准 App Engine 配置文件(app.yaml、requirements.txt、appengine_config.py)进行任何更改。
5. 修改应用文件
由于我们只添加了 App Engine API,因此不涉及任何外部软件包,这意味着无需更新任何配置文件(app.yaml、requirements.txt、appengine_config.py)。只有一个应用文件 main.py,因此本部分中的所有更改都只会影响该文件。
导入
最重要的一步是导入 Memcache 库 google.appengine.api.memcache。由于我们要将最近 1 小时的访问记录缓存起来,因此我们还要添加一个常量来表示 1 小时内的秒数。以下是您的代码在进行此项更改前后的样子:
之前:
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 memcache
from google.appengine.ext import ndb
app = Flask(__name__)
HOUR = 3600
添加了对 Memcache 的缓存支持
最显著的变化是在应用中添加了缓存的使用。更具体地说,我们应该缓存最近的访问,检查是否有缓存的访问,并尽可能根据我们的计划使用缓存的结果。应用将采取以下步骤来实现我们的目标:
- 设置当前访问会话并将其命名为
visitor - 尝试从缓存中提取最新的
visits - 如果缓存为空或最新访问者 (
visits[0]['visitor']) 与当前visitor不同:存储此最新访问,提取最近的访问,并缓存这些访问一个小时。 - 通过 Web 模板向用户显示
visits
下面是应用这些更新前后的效果:
之前:
@app.route('/')
def root():
'main application (GET) handler'
store_visit(request.remote_addr, request.user_agent)
visits = fetch_visits(10)
return render_template('index.html', visits=visits)
升级后:
@app.route('/')
def root():
'main application (GET) handler'
# check for (hour-)cached visits
ip_addr, usr_agt = request.remote_addr, request.user_agent
visitor = '{}: {}'.format(ip_addr, usr_agt)
visits = memcache.get('visits')
# register visit & run DB query if cache empty or new visitor
if not visits or visits[0]['visitor'] != visitor:
store_visit(ip_addr, usr_agt)
visits = list(fetch_visits(10))
memcache.set('visits', visits, HOUR) # set() not add()
return render_template('index.html', visits=visits)
下图直观地展示了所做的更改:

至此,我们已完成向模块 1 示例应用添加 App Engine memcache 使用所需的所有更改。接下来,我们来构建并部署此应用,看看它是否能正常运行!
6. 总结/清理
本部分将通过部署应用来结束此 Codelab,并验证应用是否按预期运行以及是否在任何反映的输出中正常运行。应用验证完成后,执行任何清理步骤,并考虑后续步骤。
部署并验证应用
使用 gcloud app deploy 重新部署应用,并确认应用可正常运行。您的代码现在应与 模块 12 文件夹中的 FINISH 内容相匹配。输出应与您之前部署的模块 1 应用完全相同:

我们只是加快了同一用户的用户体验。刷新时,您应直接从缓存中获取结果,这样既不会创建新的会话,也不会进行 Datastore 提取。
恭喜您完成了模块 12 的 Codelab,该 Codelab 介绍了如何向我们的示例应用添加对 App Engine memcache 服务的使用。现在,您可以选择在奖励步骤中将此 Python 2 应用移植到 Python 3。
清理
常规
如果您暂时不想继续操作,建议您停用 App Engine 应用,以免产生结算费用。不过,如果您想进一步测试或实验,App Engine 平台有免费配额,因此只要您不超过该使用层级,就不会产生费用。这是计算费用,但相关 App Engine 服务也可能会产生费用,因此请查看其价格页面了解详情。如果此迁移涉及其他 Cloud 服务,则这些服务会单独计费。在任何一种情况下,如果适用,请参阅下文中的“本 Codelab 特有的问题”部分。
为了完全公开透明,我们在此说明,部署到 Google Cloud 无服务器计算平台(例如 App Engine)会产生少量 build 和存储费用。Cloud Build 和 Cloud Storage 都有各自的免费配额。存储该图片会占用部分配额。不过,您可能居住在没有此类免费层的地区,因此请注意存储空间用量,以尽可能减少潜在费用。您应查看的特定 Cloud Storage“文件夹”包括:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- 上述存储链接取决于您的
PROJECT_ID和 *LOC*ation,例如,如果您的应用托管在美国,则为“us”。
另一方面,如果您不打算继续学习此应用或其他相关迁移 Codelab,并且想要彻底删除所有内容,请关闭您的项目。
此 Codelab 特有的
以下列出的服务是此 Codelab 特有的。如需了解详情,请参阅各个产品的文档:
- App Engine Memcache 服务有两种不同的版本,每种版本都有自己的价格结构,因此您必须跟踪与结算相关的用量。
- App Engine Datastore 服务由 Cloud Datastore(Datastore 模式的 Cloud Firestore)提供,后者也提供免费层级;如需了解详情,请参阅其价格页面。
后续步骤
下一个要考虑的逻辑迁移在模块 13 中介绍,该模块向开发者展示了如何从 App Engine memcache 服务迁移到 Cloud Memorystore。这些迁移都是可选的,适用于希望采取各种步骤来更新其应用的用户。Cloud Memorystore 服务是对 App Engine 的 memcache 的重大升级,原因如下:
- Cloud Memorystore 不是无服务器的。这意味着您必须为缓存分配服务器。Cloud Memorystore 也没有免费层级。这两个因素都会对费用产生重大影响。
- Cloud Memorystore 支持两种不同的底层存储机制(缓存引擎):Redis 和 Memcached。
- 与 App Engine Memcache 相比,Cloud Memorystore(适用于 Redis)的功能集更加丰富和深入。
- 如需使用 Cloud Memorystore,您必须设置 Cloud Memorystore 服务器,将其添加到 Google Cloud VPC 网络,然后让 App Engine 应用使用该网络与 Memorystore 服务器通信。
如果您认为自己不需要 Cloud Memorystore 提供的所有功能,或者担心它会对费用产生影响,则可以继续使用 App Engine Memcache。
除了模块 13 之外,还有许多其他可能的迁移,例如 Cloud NDB 和 Cloud Datastore,或 Cloud Tasks。此外,还可以跨产品迁移到 Cloud Run 和 Cloud Functions。您可以在迁移代码库中找到所有这些代码。
另一个可能的后续步骤是移植到 Python 3,下一部分将介绍此可选步骤。
7. 奖励:迁移到 Python 3
概览
本部分包含可选的奖励内容,用于将我们刚刚完成的模块 12 应用迁移到 Python 3。我们先介绍配置,然后再介绍应用。
简化 app.yaml
Python 3 运行时的一大优势是,app.yaml 可以大幅简化。
之前:
以下是第 12 模块结束时 app.yaml 中的内容:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
由于 Python 3 运行时要求 Web 框架自行进行路由,因此 app.yaml 中的所有路由处理程序都必须更改为 auto。如果没有提供任何静态文件,用户可以直接移除整个 handlers: 部分。此外,threadsafe 和 api_version 都已弃用。
升级后:
在进行上述必需的更改后,以下是 Python 3 的替代 app.yaml:
runtime: python39
app_engine_apis: true
唯一需要解释的行是 app_engine_apis: true。2021 年旧版 App Engine 服务可用于第二代运行时时,部分运行时(包括 Python 3)需要额外的引导加载程序才能访问 ndb、taskqueue 和 memcache 等 API。配置中的这一行可实现此目的。
更新 requirements.txt
在 requirements.txt 中,需要对原始 API 进行另一次引导启动:必须包含对新 App Engine SDK 的访问权限。
之前:
以下是第 12 模块结束时 app.yaml 中的内容:
flask
升级后:
只需添加 App Engine Python SDK,您就应该会看到以下内容:
flask
appengine-python-standard
删除 appengine_config.py 和 lib
新一代 App Engine 运行时改进了第三方软件包的使用方式:
- 内置库是指经过 Google 审核并可在 App Engine 服务器上使用的库,这可能是因为它们包含开发者不允许部署到云端的 C/C++ 代码,这些库在第 2 代运行时中不再可用。
- 在第二代运行时中,不再需要复制非内置库(有时称为“供应商”或“自打包”)。相反,它们应列在
requirements.txt中,以便构建系统在部署时自动为您安装它们。
由于对第三方软件包管理进行了这些更改,因此不再需要 appengine_config.py 文件和 lib 文件夹,请将其删除。在第二代运行时中,App Engine 会自动安装 requirements.txt 中列出的第三方软件包。总结:
- 没有自捆绑或复制的第三方库;请在
requirements.txt中列出它们 - 没有
pip install到lib文件夹中,即无lib文件夹期限 app.yaml中未列出内置第三方库(因此没有libraries部分);在requirements.txt中列出这些库- 如果您的应用无需引用任何第三方库,则无需
appengine_config.py文件
在 requirements.txt 中列出所有所需的第三方库是开发者的唯一要求。
更新应用以使用 App Engine SDK
如上所述,Python 3 应用需要进行一些修改才能访问 App Engine 捆绑服务:
- 捆绑 App Engine SDK(在
requirements.txt中) - 激活 App Engine SDK(在
app.yaml中) - 封装 WSGI 对象(在
main.py中)
前两个配对已在上面完成,因此最后一个要求是更新 main.py。
之前:
以下是模块 12 结束时的 Python 2 main.py:
from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb
app = Flask(__name__)
HOUR = 3600
升级后:
对于 Python 3 移植,请导入 SDK 并使用它(SDK 封装容器)封装 Flask 应用对象,如下所示:
from flask import Flask, render_template, request
from google.appengine.api import memcache, wrap_wsgi_app
from google.appengine.ext import ndb
app = Flask(__name__)
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
HOUR = 3600
开发者在从 2.x 向 3.x 移植 Python 应用时,需要进行这些更改才能访问捆绑服务。如果您未使用 Flask,文档中还提供了 Django 和 Pyramid 示例。如果您的 Python 2 代码不是 Web 应用,那么在移植到 Python 3 时,只需包含 SDK 软件包即可。我们的应用代码最初是为在 Python 2 和 3 下运行而精心设计的,因此无需进行额外的兼容性更改。
部署应用
完成上述更改后,您可以部署更新后的示例应用。(在同一 GCP 项目中,将应用的 Python 3 版本部署到原始 Python 2 版本上不会出现问题。)应用行为应保持不变。如果您需要将更新后的应用与我们的应用进行比较,请参阅迁移代码库中的模块 12b 文件夹。如需详细了解最新运行时(例如 Python 3)中对 App Engine 捆绑服务的支持,请参阅功能发布公告以及模块 17 Codelab。
恭喜您完成了第 12 模块中的奖励步骤!另请参阅有关为 Python 3 运行时准备配置文件的文档。请参阅上文中的“总结/清理”部分,了解后续步骤和清理操作。
8. 其他资源
下面列出了其他资源,可供开发者进一步探索本迁移模块或相关迁移模块以及相关产品。这包括提供有关此内容的反馈的途径、指向代码的链接,以及您可能会觉得有用的各种文档。
Codelab 问题/反馈
如果您发现本 Codelab 存在任何问题,请先搜索您的问题,然后再提交。用于搜索和创建新问题的链接:
迁移时可参考的资源
下表中提供了指向模块 2(开始)和模块 12(结束)的代码库文件夹的链接。您还可以从所有 App Engine Codelab 迁移的代码库中访问这些示例,您可以克隆该代码库或下载 ZIP 文件。
Codelab | Python 2 | Python 3 |
代码(本教程中未介绍) | ||
第 12 模块(本 Codelab) |
在线参考
以下是一些可能与本教程相关的在线资源:
App Engine
- App Engine 文档
- Python 2 App Engine(标准环境)运行时
- Python 3 App Engine(标准环境)运行时
- Python 2 和 3 App Engine(标准环境)运行时之间的差异
- Python 2 到 3 App Engine(标准环境)迁移指南
- App Engine 价格和配额信息
- 第二代 App Engine 平台发布 (2018)
- 比较第一代和第二代平台
- 对旧版运行时的长期支持
- 文档迁移示例代码库
- 社区提供的迁移示例代码库
Cloud Memorystore 和 Cloud Datastore
- Cloud Memorystore 产品页面
- Cloud Memorystore for Redis 文档
- Cloud Memorystore for Memcached 文档
- Cloud Memorystore(适用于 Redis)价格信息
- Cloud Datastore 文档
- Cloud Datastore 价格信息
其他云信息
- 在 Google Cloud Platform 上使用 Python 应用
- Google Cloud Python 客户端库
- Google Cloud“始终免费”层级
- Google Cloud SDK(
gcloud命令行工具) - 所有 Google Cloud 文档
视频
许可
此作品已获得 Creative Commons Attribution 2.0 通用许可授权。