1. 概览
无服务器迁移站系列 Codelab(自定进度的动手教程)和相关视频旨在帮助 Google Cloud 无服务器开发者通过一次或多次迁移(主要是从旧版服务迁移)来指导他们的应用现代化。这样做可让您的应用更易于移植,并为您提供更多选择和灵活性,使您能够与更多 Cloud 产品集成并访问这些产品,还能更轻松地升级到新的语言版本。虽然最初侧重于最早的 Cloud 用户(主要是 App Engine [标准环境] 开发者),但本系列文章的范围足够广,可涵盖其他无服务器平台(例如 Cloud Functions 和 Cloud Run),或者其他平台(如果适用)。
有时,您可能没有“整个应用”需要 App Engine 或 Cloud Run 的资源。如果您的代码仅包含微服务或简单函数,那么 Cloud Functions 可能更适合您。本 Codelab 将介绍如何迁移简单的 App Engine 应用(或将较大的应用拆分为多个微服务),并将其部署到 Cloud Functions(另一个专门为此类使用情形创建的无服务器平台)。
在接下来的实验中
- 使用 Cloud Shell
- 启用 Google Cloud Translation API
- 对 API 请求进行身份验证
- 将小型 App Engine 应用转换为在 Cloud Functions 上运行
- 将代码部署到 Cloud Functions
所需条件
- 具有有效的 GCP 结算账号的 Google Cloud Platform 项目
- 基本 Python 技能
- 常用 Linux 命令的实践知识
- 具备开发和部署 App Engine 应用的基础知识
- 有效的模块 2 Cloud NDB Python 3 App Engine 应用
- 推荐:完成模块 2 Codelab,以及将应用从 Python 2 移植到 3 的奖励步骤
调查问卷
您将如何使用本教程?
您如何评价使用 Python 的体验?
您如何评价自己在使用 Google Cloud 服务方面的经验水平?
2. 背景
PaaS 系统(例如 Google App Engine 和 Cloud Functions)为用户提供了许多便利。这些无服务器平台使您的技术团队能够专注于创建业务解决方案,而不是花费时间来调查要使用的平台并确定所需的硬件量。应用可根据需要自动扩缩,使用按用量计费的结算方式有助于缩减至零,并支持多种当今常见的开发语言。
不过,虽然 App Engine 非常适合用于全栈 Web 应用开发或移动应用的复杂后端,但开发者通常主要只是想将某些功能在线实现,例如更新新闻信息流或拉取主队季后赛的最新得分。虽然这两种场景都有相应的编码逻辑,但似乎都不是需要 App Engine 强大功能的成熟“应用”。这时,Cloud Functions 就派上用场了。
Cloud Functions 适用于部署以下少量代码:
- 不是整个应用的一部分
- 在整个开发技术栈中不需要
- 位于专注于某项功能的单个移动应用后端或应用中
您还可以使用 Cloud Functions 将大型单体式应用拆分为多个微服务,每个微服务都使用共享的通用数据库,例如 Cloud Firestore 或 Cloud SQL。如果您希望将函数或微服务容器化,并在 Cloud Run 上以无服务器方式执行,也可以这样做。
我们的示例 App Engine 应用几乎在所有迁移教程中都有介绍,它是一个具有基本功能的简短应用,在 Cloud Functions 中也能正常运行。在本教程中,您将学习如何修改该应用,使其在 Cloud Functions 上运行。从 App Engine 的角度来看,由于函数比整个应用简单,因此您的入门体验应该更轻松(也更快),并且总体上“开销”更少。此迁移具有以下步骤:
- 设置/准备工作
- 移除配置文件
- 修改应用文件
3. 设置/准备工作
此 Codelab 从 Module 2 Cloud NDB App Engine 示例应用的 Python 3 版本开始,因为 Cloud Functions 不支持 Python 2。首先,让我们设置项目、获取代码,然后部署基准应用,以确认我们从工作代码开始。
1. 设置项目
如果您已完成模块 2 Codelab(并将其移植到 Python 3),我们建议您重复使用同一项目(和代码)。或者,您可以创建一个全新的项目或重复使用另一个现有项目。确保项目具有有效的结算账号,并且已启用 App Engine 服务。
2. 获取基准示例应用
此 Codelab 的先决条件之一是拥有一个工作正常的模块 2 示例应用。如果您没有,请先完成上面链接的任一教程,然后再继续学习。或者,如果您已经熟悉其内容,可以直接从下面的模块 2 开始。
无论您是使用自己的代码还是我们的代码,我们都能在模块 2 Python 3 代码中。本模块 11 Codelab 将引导您完成每个步骤,最终获得类似于模块 11 代码库文件夹 (FINISH) 中的代码。
Python 3 模块 2 启动文件(您或我们的文件)的目录应如下所示:
$ ls README.md main.py templates app.yaml requirements.txt
3. (重新)部署基准应用
您现在需要执行的剩余预处理步骤:
- 重新熟悉
gcloud命令行工具 - 使用
gcloud app deploy重新部署示例应用 - 确认应用在 App Engine 上运行没有任何问题
成功执行完这些步骤后,您就可以将其转换为 Cloud Functions 函数。
4. 移除配置文件
app.yaml 文件是 App Engine 制品,不适用于 Cloud Functions,因此请立即将其删除。如果您未执行或忘记执行此操作,也不会有任何影响,因为 Cloud Functions 不会使用它。这是唯一的配置更改,因为 requirements.txt 与模块 2 中的保持完全一致。
如果您还要将 Python 2 App Engine 应用移植到 Python 3,请删除 appengine_config.py 和 lib 文件夹(如果有)。它们是 Python 3 运行时中未使用的 App Engine 制品。
5. 修改应用文件
只有一个应用文件 main.py,因此迁移到 Cloud Functions 的所有必要更改都在此文件中进行。
导入
由于我们只使用函数,因此无需 Web 应用框架。不过,为方便起见,当调用基于 Python 的 Cloud Functions 时,系统会自动传递一个请求对象,供您的代码根据需要使用。(Cloud Functions 团队选择将其作为 Flask Request 对象传递给您的函数。)
由于 Web 框架不属于 Cloud Functions 的范畴,因此除非您的应用使用其他 Flask 功能,否则不会从 Flask 导入任何内容。这确实是我们的情况,因为在转换为函数后,模板渲染仍在进行,这意味着仍然需要调用 flask.render_template(),因此需要从 Flask 导入它。由于没有 Web 框架,因此无需实例化 Flask 应用,请删除 app = Flask(__name__)。应用更改前后,您的代码如下所示:
之前:
from flask import Flask, render_template, request
from google.cloud import ndb
app = Flask(__name__)
ds_client = ndb.Client()
升级后:
from flask import render_template
from google.cloud import ndb
ds_client = ndb.Client()
如果您依赖于应用对象 (app) 或任何其他 Web 框架基础架构,则需要解决所有这些依赖项,找到合适的解决方法,或者完全移除其使用或找到代理。只有这样,您才能将代码转换为 Cloud Functions 函数。否则,您最好继续使用 App Engine,或者为 Cloud Run 容器化您的应用
更新了主处理函数签名
函数签名中需要进行的更改如下:
- 将应用转换为 Cloud Function 后,不再使用 Flask,因此请移除路由装饰器。
- Cloud Functions 会自动传入 Flask
Request对象作为参数,因此请为其创建一个变量。在我们的示例应用中,我们将其称为request。 - 已部署的 Cloud Functions 函数必须命名。我们的主要处理程序在 App Engine 中被恰当地命名为
root(),以描述其用途(根应用处理程序)。作为 Cloud Functions,使用该名称不太合理。相反,我们将部署名为visitme的 Cloud Functions 函数,因此也使用该名称作为 Python 函数的名称。同样,在模块 4 和 5 中,我们也将 Cloud Run 服务命名为visitme。
下面是应用这些更新前后的效果:
之前:
@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)
升级后:
def visitme(request):
'main application (GET) handler'
store_visit(request.remote_addr, request.user_agent)
visits = fetch_visits(10)
return render_template('index.html', visits=visits)
以上就是所有必要的更新。请注意,所做的更改仅影响应用的“基础架构”代码。无需更改核心应用代码,并且应用的功能未发生任何变化。下图直观地展示了为说明这一点而做出的更改:

本地开发和测试
App Engine 有 dev_appserver.py 本地开发服务器,而 Cloud Functions 有 Functions 框架。借助此框架,您可以在本地进行开发和测试。您的代码可以部署到 Cloud Functions,但也可以部署到其他计算平台,例如 Compute Engine、Cloud Run,甚至支持 Knative 的本地或混合云系统。如需了解 Functions 框架的其他链接,请参阅下文。
6. 构建和部署
部署到 Cloud Functions 与部署到 App Engine 略有不同。由于 requirements.txt 之外没有使用任何配置文件,因此必须在命令行中指定有关代码的更多信息。使用以下命令部署在 Python 3.10 下运行的新 HTTP 触发型 Cloud Functions 函数:
$ gcloud functions deploy visitme --runtime python310 --trigger-http --allow-unauthenticated
您应会看到如下所示的输出:
Deploying function (may take a while - up to 2 minutes)...⠛ For Cloud Build Logs, visit: https://console.cloud.google.com/cloud-build/builds;region=REGION/f5f6fc81-1bb3-4cdb-8bfe?project=PROJECT_ID Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 buildId: f5f6fc81-1bb3-4cdb-8bfe buildName: projects/PROJECT_ID/locations/REGION/builds/f5f6fc81-1bb3-4cdb-8bfe dockerRegistry: CONTAINER_REGISTRY entryPoint: visitme httpsTrigger: securityLevel: SECURE_OPTIONAL url: https://REGION-PROJECT_ID.cloudfunctions.net/visitme ingressSettings: ALLOW_ALL labels: deployment-tool: cli-gcloud name: projects/PROJECT_ID/locations/REGION/functions/visitme runtime: python310 serviceAccountEmail: PROJECT_ID@appspot.gserviceaccount.com sourceUploadUrl: https://storage.googleapis.com/uploads-853031211983.REGION.cloudfunctions.appspot.com/8c923758-cee8-47ce-8e97-5720a5301c34.zip status: ACTIVE timeout: 60s updateTime: '2022-05-16T18:28:06.153Z' versionId: '8'
函数部署完成后,使用部署输出中的网址访问您的应用。该网址的格式为:REGION-PROJECT_ID.cloudfunctions.net/visitme。输出应与您之前将其部署到 App Engine 时相同:

与本系列中的大多数其他 Codelab 和视频一样,基准应用功能不会发生变化。目的是应用一种现代化技术,让应用能够像以前一样正常运行,但由更新的基础设施提供支持,例如从旧版 App Engine 服务迁移到其替代产品 Cloud 独立产品,或者(如本教程中的示例)将应用迁移到另一个 Google Cloud 无服务器平台。
7. 总结/清理
恭喜您将这个小型 App Engine 应用转换为 Cloud Functions 函数!另一个合适的应用场景:将大型单体式 App Engine 应用拆分为一系列微服务,每个微服务都作为 Cloud Functions 函数。这是一种更现代的开发技术,可实现更“即插即用”的组件(类似于“JAM 堆栈”风格)。它支持混搭和代码重用,这是两个目标,但另一个好处是,这些微服务会随着时间的推移不断得到调试,这意味着代码稳定,总体维护成本较低。
清理
完成本 Codelab 后,您可以停用模块 2 App Engine 应用(暂时或永久),以避免产生费用。App Engine 平台提供免费配额,只要您的用量未超出相应的使用层级,就不会产生费用。Datastore 也是如此;如需了解详情,请参阅 Cloud Datastore 价格页面。
部署到 App Engine 和 Cloud Functions 等平台会产生少量 build 和存储费用。在某些区域,Cloud Build 和 Cloud Storage 都有各自的免费配额。构建会消耗部分配额。请注意您的存储空间用量,以尽可能减少潜在费用,尤其是在您所在的地区没有此类免费层级的情况下。
遗憾的是,Cloud Functions 没有“停用”功能。备份您的代码,然后删除该函数。您日后可以随时使用相同的名称重新部署。不过,如果您不打算继续学习任何其他迁移 Codelab,并且想要彻底删除所有内容,请关闭您的 Cloud 项目。
后续步骤
除了本教程之外,您还可以查看其他迁移模块,包括为 Cloud Run 容器化 App Engine 应用。请参阅指向模块 4 和模块 5 Codelab 的链接:
- 模块 4:使用 Docker 迁移到 Cloud Run
- 使用 Docker 将应用容器化,以便在 Cloud Run 上运行
- 通过此迁移,您可以继续使用 Python 2。
- 模块 5:使用 Cloud Buildpack 迁移到 Cloud Run
- 使用 Cloud Buildpacks 将应用容器化,以便在 Cloud Run 上运行
- 您无需了解 Docker、容器或
Dockerfile。 - 要求您的应用已迁移到 Python 3(buildpack 不支持 Python 2)
其他许多模块都侧重于向开发者展示如何从 App Engine 捆绑服务迁移到 Cloud 独立替代服务:
- 模块 2:从 App Engine
ndb迁移到 Cloud NDB - 模块 7-9:从 App Engine 任务队列推送任务迁移到 Cloud Tasks
- 模块 12-13:从 App Engine Memcache 迁移到 Cloud Memorystore
- 模块 15-16:从 App Engine Blobstore 迁移到 Cloud Storage
- 模块 18-19:从 App Engine 任务队列(拉取任务)迁移到 Cloud Pub/Sub
如果容器化已成为应用开发工作流的一部分,尤其是当该工作流包含 CI/CD(持续集成/持续交付或部署)流水线时,请考虑迁移到 Cloud Run 而不是 Cloud Functions。请参阅模块 4,了解如何使用 Docker 将应用容器化;或参阅模块 5,了解如何在不使用容器、Docker 知识或 Dockerfile 的情况下将应用容器化。无论您是考虑使用 Cloud Functions 还是 Cloud Run,切换到其他无服务器平台都是可选的,我们建议您在做出任何更改之前,先考虑最适合您的应用和使用情形的选项。
无论您接下来考虑哪个迁移模块,都可以在 开源代码库中访问所有无服务器迁移站内容(Codelab、视频、源代码 [如有])。该代码库的 README 还提供了有关应考虑哪些迁移以及任何相关的迁移模块“顺序”的指南。
8. 其他资源
App Engine 迁移模块 Codelab 问题/反馈
如果您发现本 Codelab 存在任何问题,请先搜索您的问题,然后再提交。用于搜索和创建新问题的链接:
迁移时可参考的资源
下表中提供了指向模块 8(开始)和模块 9(完成)的 Repo 文件夹的链接。您还可以从所有 App Engine Codelab 迁移的代码库中访问这些示例,您可以克隆该代码库或下载 ZIP 文件。
Codelab | Python 3 |
在线资源
以下是一些可能与本教程相关的在线资源:
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 Functions
- gcloud functions deploy 命令
- 价格信息
- Cloud Functions 下一代公告
- 第一代函数与第二代函数之间的区别
- Functions 框架(本地开发)操作指南、使用文档和代码库
- 商品页面
- 文档
其他云信息
- 在 Google Cloud Platform 上使用 Python 应用
- Google Cloud Python 客户端库
- Google Cloud“始终免费”层级
- Google Cloud SDK(
gcloud命令行工具) - 所有 Google Cloud 文档
视频
许可
此作品已获得 Creative Commons Attribution 2.0 通用许可授权。