如何在 Flask 应用中使用 App Engine Memcache(模块 12)

1. 概览

无服务器迁移站系列 Codelab(自定进度的实操教程)和相关视频旨在指导 Google Cloud 无服务器开发者完成一次或多次迁移(主要是从旧服务迁移),从而实现应用的现代化改造。这样做可以提高应用的可移植性,为您提供更多选择和灵活性,让您能够集成并访问更广泛的 Cloud 产品,并更轻松地升级到较新版本。虽然本系列最初主要面向的是最早接触 Cloud 的用户(主要是 App Engine(标准环境)开发者),但涵盖的范围非常广泛,涵盖了 Cloud FunctionsCloud Run 等其他无服务器平台,或其他无服务器平台(如适用)。

此 Codelab 会教您如何在模块 1 Codelab 中的示例应用中添加和使用 App Engine Memcache。我们将在本单元 12 的教程中添加 Memcache 用法,然后在第 13 单元中迁移到 Cloud Memorystore

在接下来的实验中

  • 使用 App Engine Memcache API/库
  • 向基本的 Python 2 Flask App Engine NDB 应用添加缓存

所需条件

调查问卷

您将如何使用本教程?

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

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

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

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

<ph type="x-smartling-placeholder"></ph> 新手 中级 熟练

2. 背景

如需从 App Engine Memcache 迁移,请将其添加到通过模块 1 Codelab 生成的现有 Flask 和 App Engine NDB 应用中。示例应用向用户显示最近 10 次访问。如果同一用户刷新其浏览器,则不断创建新的访问实体并从 Datastore 提取最近的访问不是最佳选择,因此我们要缓存这些最近的访问。

如果同一访问者访问该网页,则从缓存中返回这些访问。如果新用户访问了网站,或者已经过了一小时,缓存会被清空并替换为最近的条目(更不用说又记录了新的访问)。实现此 App Engine Memcache 集成后,我们可以在下一个(模块 13)Codelab 中将其迁移到 Cloud Memorystore

本教程包含以下步骤:

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

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. (重新)部署基准应用

现在需要执行的其余准备工作步骤:

  1. 重新熟悉 gcloud 命令行工具
  2. 使用 gcloud app deploy 重新部署示例应用
  3. 确认应用在 App Engine 上运行没有任何问题

成功执行这些步骤并看到您的 Web 应用正常运行(输出类似于下文)后,您就可以在应用中使用缓存了。

a7a9d2b80d706a2b.png

4. 更新配置

无需对标准 App Engine 配置文件(app.yamlrequirements.txtappengine_config.py)进行任何更改。

5. 修改应用文件

由于我们只添加了 App Engine API,因此不涉及外部软件包,这意味着不需要更新配置文件(app.yamlrequirements.txtappengine_config.py)。只有一个应用文件 main.py,因此本部分中的所有更改都只会影响该文件。

导入

最重要的步骤是导入 Memcache 库 google.appengine.api.memcache。由于我们要将最近的访问缓存一小时,因此我们还要添加一个表示一小时中的秒数的常量。您的代码之前及此变更如下所示:

之前

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 支持添加缓存

最显著的更改是在应用中增加缓存的使用。更具体地说,我们应缓存最近的访问,检查是否有可用的缓存访问,并根据我们的计划尽可能地使用缓存的结果。为实现我们的目标,该应用将采取以下步骤:

  1. 设置当前访问,并将其命名为 visitor
  2. 尝试从缓存中提取最新的 visits
  3. 如果缓存为空或最近访问者 (visits[0]['visitor']) 与当前 visitor 不同:存储此最近的访问,提取最近的访问,并将其缓存一小时。
  4. 通过网页模板向用户显示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)

以下是所做更改的示意图:

b1242503602f7bf0.png

以上就是在模块 1 示例应用中添加 App Engine memcache 使用行为的所有必要更改。让我们构建和部署此应用,看看它能否正常运行!

6. 摘要/清理

在此 Codelab 的最后,本部分将部署应用,验证应用是否按预期以及任何反映的输出中正常运行。应用验证后,执行所有清理步骤并考虑后续步骤。

部署并验证应用

使用 gcloud app deploy 重新部署您的应用,并确认应用能正常运行。您的代码现在应与 FINISH(模块 12 文件夹)中的内容相匹配。输出应该与您之前部署的模块 1 应用相同:

a7a9d2b80d706a2b.png

我们所做的只是为同一用户提升了用户体验。刷新时,您应直接从缓存中获取结果,这既不会创建新访问,也不会进行 Datastore 提取。

恭喜您完成了第 12 单元的 Codelab,了解如何在我们的示例应用中添加 App Engine memcache 服务。现在,您可以在额外步骤中选择将此 Python 2 应用移植到 Python 3。

清理

常规

如果您目前已完成,我们建议您停用 App Engine 应用,以免产生费用。不过,如果您希望测试或实验更多内容,App Engine 平台有免费配额,因此只要您不超过该使用量水平,您就不必支付费用。这只是计算费用,但相关 App Engine 服务可能也会产生费用,因此请查看其价格页面了解详情。如果此迁移涉及其他 Cloud 服务,这些服务单独计费。无论是哪种情况(如适用),请参阅“此 Codelab 的具体说明”部分。

为了全面披露,部署到像 App Engine 这样的 Google Cloud 无服务器计算平台会产生少量构建和存储费用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*格式,例如“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 支持一对不同的底层存储机制(缓存引擎),即 RedisMemcached
  • 与 App Engine Memcache 相比,Cloud Memorystore (for 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: 部分。此外,threadsafeapi_version 都已弃用

之后

根据上述必要更改,这是 Python 3 的替代 app.yaml

runtime: python39
app_engine_apis: true

唯一需要说明的行是 app_engine_apis: true旧版 App Engine 服务于 2021 年面向第二代运行时推出时,部分运行时(包括 Python 3)需要额外的引导才能访问这些 API(例如 ndbtaskqueuememcache)。配置中的这一行即用于实现此目的。

更新 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 代运行时中已不再提供。
  • 第 2 代运行时不再需要复制非内置库(有时称为“vendoring”或“自捆绑”)。相反,它们应列在 requirements.txt 中,构建系统在部署时会自动代您进行安装。

由于对第三方软件包管理进行了上述更改,因此既不需要 appengine_config.py 文件和 lib 文件夹,也不需要删除它们。在第 2 代运行时中,App Engine 会自动安装 requirements.txt 中列出的第三方软件包。总结:

  1. 不得自行捆绑或复制第三方库;在requirements.txt中列出
  2. 没有 pip installlib 文件夹中,即无 lib 文件夹期限
  3. app.yaml 中未列出内置的第三方库(因此没有 libraries 部分);在requirements.txt中列出
  4. 没有可从您的应用引用的第三方库意味着没有 appengine_config.py 文件

requirements.txt 中列出所有需要的第三方库是开发者的唯一要求。

更新应用以使用 App Engine SDK

如上所述,Python 3 应用需要一些修改才能访问 App Engine 捆绑服务:

  1. 捆绑 App Engine SDK(在 requirements.txt 中)
  2. 激活 App Engine SDK(在 app.yaml 中)
  3. 封装 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 并使用它封装 Flask 应用对象(SDK 封装容器),从而生成以下内容:

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 下运行,因此无需更改兼容性。

部署应用

完成上述更改后,您可以部署更新后的示例应用。(如果部署应用的 Python 3 版本以覆盖同一 GCP 项目中的原始 Python 2 版本,则不会产生任何问题。)应用行为应保持不变。如果您需要将更新后的应用与我们的应用进行比较,请参阅迁移代码库中的模块 12b 文件夹。如需详细了解最新运行时(例如 Python 3)对 App Engine 捆绑服务的支持,请参阅功能发布公告模块 17 Codelab

恭喜您完成了第 12 单元中的奖励步骤!另请参阅关于为 Python 3 运行时准备配置文件的文档。请查看上文中的“摘要/清理”部分,了解后续步骤和清理。

8. 其他资源

下面列出的其他资源可帮助开发者进一步探索此迁移模块或相关迁移模块及相关产品。这包括提供有关此内容的反馈、代码链接以及各种可能对您有用的文档的地方。

Codelab 问题/反馈

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

迁移时可参考的资源

下表列出了模块 2(START)和模块 12 (FINISH) 对应的代码库文件夹的链接。您还可以从所有 App Engine Codelab 迁移的代码库访问这些库,您可以克隆或下载 ZIP 文件。

Codelab

Python 2

Python 3

模块 1

代码

code(本教程中未提供)

第 12 单元(此 Codelab)

代码

代码

在线参考

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

App Engine

Cloud Memorystore 和 Cloud Datastore

其他 Cloud 信息

视频

许可

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