摘要
在此 Codelab 中,您将学习如何将 Python Flask Web 应用部署到 App Engine 柔性环境。该示例应用允许用户上传人物头像的照片,并了解相应人员满意的可能性。该应用将 Google Cloud API 用于 Vision、Storage 和 Datastore。
关于 App Engine
Google App Engine 应用易于创建、易于维护,并可根据流量和数据存储需求的变化轻松扩缩。使用 App Engine 时,无需维护任何服务器。您只需上传自己的应用,即可开始使用。
App Engine 应用会根据传入的流量自动扩缩。负载平衡、微服务、授权、SQL 和 NoSQL 数据库、流量拆分、日志记录、搜索、版本控制、发布和回滚以及安全扫描都是原生支持的,并且高度可自定义。
App Engine 的柔性环境支持以下所有编程语言:C#、Go、Java、Node.js、PHP、Python 和 Ruby。App Engine 柔性环境在 Google Compute Engine 虚拟机上运行的 Docker 容器中运行您的应用。App Engine 的标准环境是适用于 Python 等特定语言的替代选项。App Engine 标准环境在限制性更强的沙盒环境中运行您的应用。如需了解详情,请参阅选择 App Engine 环境。
学习内容
- 如何将简单的 Web 应用部署到 App Engine 柔性环境
- 如何访问适用于 Vision、Storage 和 Datastore 的 Google Cloud 客户端库
- 如何使用 Google Cloud Console 和 Google Cloud SDK 管理各种云资源
- 如何使用 Cloud Shell
所需条件
- 熟悉 Python
- 熟悉标准的 Linux 文本编辑器,例如 Vim、Emacs 或 Nano
创建项目
如果您还没有 Google 帐号(Gmail 或 Google Apps),则必须创建一个。登录 Google Cloud Platform Console (console.cloud.google.com) 并创建一个新项目:
请记住项目 ID,它在所有 Google Cloud 项目中都是唯一的名称(上述名称已被占用,您无法使用,抱歉!)。它稍后将在此 Codelab 中被称为 PROJECT_ID。
结算
接下来,您需要在 Cloud Console 中启用结算功能,才能使用 Google Cloud 资源。
在此 Codelab 中运行仅花费几美元,但是如果您决定使用更多资源或继续让它们运行,费用可能更高。
Google Cloud Platform 的新用户有资格获享 $300 免费试用。
虽然 Google Cloud 可以从笔记本电脑远程操作,但在此 Codelab 中,我们将使用 Google Cloud Shell,这是一个在云端运行的命令行环境。基于 Debian 的这款虚拟机加载了您需要的所有开发工具(gcloud、python、virtualenv、pip 等),它提供了一个持久的 5GB 主目录,并且在 Google Cloud 上运行,大大增强了网络性能和身份验证。这意味着在本 Codelab 中,您只需要一个浏览器(没错,它适用于 Chromebook)。
要激活 Google Cloud Shell,只需在开发者控制台中点击右上方的按钮(配置和连接到环境应该只需要片刻时间):
在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID:
gcloud auth list Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project [core] Project = <PROJECT_ID>
如果出于某种原因未设置项目,只需发出以下命令即可:
gcloud config set project <PROJECT_ID>
在查找您的 PROJECT_ID 吗?请查看您在设置步骤中使用的项目 ID,或在控制台信息中心内查找项目 ID:
在 Cloud Shell 的命令行中,运行以下命令以克隆 GitHub 代码库:
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
将目录更改为 python-docs-samples/codelabs/flex_and_vision:
cd python-docs-samples/codelabs/flex_and_vision
您必须使用以下命令来启用这些 API,然后我们才能开始使用 Vision API、Storage API 和 Datastore API:
gcloud services enable vision.googleapis.com
gcloud services enable storage-component.googleapis.com
gcloud services enable datastore.googleapis.com
要向 Vision API、Storage API 和 Datastore API 发出请求,您需要服务帐号凭据。您可以使用 gcloud 工具从项目中生成服务帐号凭据。
为您的 PROJECT_ID 设置环境变量,将 [YOUR_PROJECT_ID] 替换为您自己的项目 ID:
export PROJECT_ID=[YOUR_PROJECT_ID]
在本地测试时,需要创建用于访问 Google Cloud API 的服务帐号:
gcloud iam service-accounts create codelab \ --display-name "My Codelab Service Account"
为新创建的服务帐号授予适当的权限:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member serviceAccount:codelab@${PROJECT_ID}.iam.gserviceaccount.com \ --role roles/owner
创建服务帐号后,请创建服务帐号密钥:
gcloud iam service-accounts keys create ~/key.json \ --iam-account codelab@${PROJECT_ID}.iam.gserviceaccount.com
此命令会生成一个服务帐号密钥,该文件存储在主目录中名为 key.json 的 JSON 文件中。
使用生成的密钥的绝对路径,在 Cloud Shell 中为服务帐号密钥设置环境变量:
export GOOGLE_APPLICATION_CREDENTIALS="/home/${USER}/key.json"
您可以详细了解如何对 Vision API 进行身份验证。
启动虚拟环境并安装依赖项
使用 virtualenv 创建名为 env 的独立 Python 3 环境:
virtualenv -p python3 env
输入新创建的名为 env 的 virtualenv:
source env/bin/activate
使用 pip 从 requirements.txt 文件中为项目安装依赖项:
pip install -r requirements.txt
requirements.txt 文件是项目所需的软件包依赖项列表。以上命令会将所有这些列出的软件包依赖项下载到 virtualenv。
创建 App Engine 应用
接下来,使用以下命令创建 App Engine 实例:
gcloud app create
创建存储分区
首先,将环境变量 CLOUD_STORAGE_BUCKET 设置为等于您的 PROJECT_ID 的名称。(为方便起见,通常建议将您的存储分区命名为 PROJECT_ID。)
export CLOUD_STORAGE_BUCKET=${PROJECT_ID}
我们的应用使用了 Cloud Storage 存储分区,您需要使用名为 gsutil 的工具通过 Cloud Shell 创建该存储分区。运行以下命令,这将创建一个与 PROJECT_ID 同名的存储分区。
gsutil mb gs://${PROJECT_ID}
运行应用
python main.py
应用启动后,点击 Cloud Shell 工具栏中的“网络预览”图标 ,然后选择“在端口 8080 上预览”。
您的浏览器会打开一个标签页,并连接到您刚启动的服务器。您应会看到类似下图的界面:
请尝试上传包含人物面孔的照片。点击选择文件按钮,从计算机中选择图片,然后点击提交。
上传照片后,您应该会看到如下内容:
示例代码布局
该示例采用以下布局:
templates/
homepage.html /* HTML template that uses Jinja2 */
app.yaml /* App Engine application configuration file */
main.py /* Python Flask web application */
requirements.txt /* List of dependencies for the project */
main.py
此 Python 文件是一个 Flask Web 应用。该应用允许用户提交照片(最好是面孔),这些照片存储在 Cloud Storage 中,并使用 Cloud Vision API 的人脸检测功能进行分析。每张照片的关键信息都存储在 Datastore(Google Cloud Platform 的 NoSQL 数据库)中,用户每次访问网站时都会访问数据库中。
此应用使用适用于 Cloud Storage、Datastore 和 Vision 的 Google Cloud Platform 客户端库。借助这些客户端库,您可以轻松地使用自己喜欢的编程语言访问 Cloud API。
我们来看一下代码的一些关键代码段。
顶部的 imports 部分用于导入代码所需的各种软件包。以下是我们导入适用于 Datastore、Storage 和 Vision 的 Google Cloud 客户端库的方式:
from google.cloud import datastore
from google.cloud import storage
from google.cloud import vision
以下代码展示了当用户访问网站的根网址时会发生什么情况。我们创建一个 Datastore 客户端对象,用于访问 Datastore 客户端库。然后,我们在 Datastore 上查询 Faces 种类的实体。最后,我们呈现 HTML 模板,将我们从 Datastore 中提取的 image_entities 作为变量传入。
@app.route('/')
def homepage():
# Create a Cloud Datastore client.
datastore_client = datastore.Client()
# Use the Cloud Datastore client to fetch information from Datastore about
# each photo.
query = datastore_client.query(kind='Faces')
image_entities = list(query.fetch())
# Return a Jinja2 HTML template and pass in image_entities as a parameter.
return render_template('homepage.html', image_entities=image_entities)
我们来看看实体如何保存到 Datastore。Datastore 是 Google Cloud 的 NoSQL 数据库解决方案。数据存储在名为“实体”的对象中。系统会为每个实体分配一个唯一的标识键,此键可以使用种类和键名字符串创建。种类是一种组织存储分区,用于决定实体所属的类型。例如,我们可能希望为照片、人物和动物设置种类。
每个实体都可以包含多个开发者定义的属性,这些属性可以具有多种类型的值,包括整数、浮点数、字符串、日期或二进制数据。
# Create a Cloud Datastore client.
datastore_client = datastore.Client()
# Fetch the current date / time.
current_datetime = datetime.now()
# The kind for the new entity.
kind = 'Faces'
# The name/ID for the new entity.
name = blob.name
# Create the Cloud Datastore key for the new entity.
key = datastore_client.key(kind, name)
# Construct the new entity using the key. Set dictionary values for entity
# keys blob_name, storage_public_url, timestamp, and joy.
entity = datastore.Entity(key)
entity['blob_name'] = blob.name
entity['image_public_url'] = blob.public_url
entity['timestamp'] = current_datetime
entity['joy'] = face_joy
# Save the new entity to Datastore.
datastore_client.put(entity)
您可以通过与 Datastore 类似的方式以编程方式访问 Storage 和 Vision 客户端库。您可以使用 vim、emacs 或 nano 自行打开 main.py 文件,以浏览所有示例代码。
如需详细了解 Flask,请访问 http://flask.pocoo.org/。
如需详细了解客户端库,请访问 https://googlecloudplatform.github.io/google-cloud-python/。
home.html
Flask Web 框架利用 Jinja2 作为模板引擎。这样,我们就可以在网页呈现后将变量和表达式从 main.py 传入 homepage.html 中,并用相应的值替换它们。
如需详细了解 Jinja2,请访问 http://jinja.pocoo.org/docs/2.9/template/。
此 Jinja2 HTML 模板显示一个表单,供用户将照片提交到数据库。它还会显示之前提交的每个图片及其文件名、上传日期/时间,以及 Vision API 检测到的人脸的可能性。
homepage.html
<h1>Google Cloud Platform - Face Detection Sample</h1>
<p>This Python Flask application demonstrates App Engine Flexible, Google Cloud
Storage, Datastore, and the Cloud Vision API.</p>
<br>
<html>
<body>
<form action="upload_photo" method="POST" enctype="multipart/form-data">
Upload File: <input type="file" name="file"><br>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
App Engine 柔性环境使用名为 app.yaml 的文件来描述应用的部署配置。如果该文件不存在,App Engine 将尝试猜测部署配置。不过,最好提供此文件。
接下来,您可以使用自己选择的 vim、nano 或 emacs 编辑器修改 app.yaml。我们将使用 nano 编辑器:
nano app.yaml
app.yaml
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app
runtime_config:
python_version: 3
env_variables:
CLOUD_STORAGE_BUCKET: <your-cloud-storage-bucket>
这是部署 Python 3 App Engine 柔性环境应用所需的基本配置。如需详细了解如何配置 App Engine,请点击此处。
打开 app.yaml 后,将 < your-cloud-storage-bucket > 替换为您的 Cloud Storage 存储分区的名称。(如果您忘记了 Cloud Storage 存储分区的名称,请复制 Qwiklabs 中的 GCP 项目 ID,ID 相同)。env_variables 部分用于设置部署应用后在 main.py 中使用的环境变量。
您现在可以使用 Ctrl + x 关闭保存功能并在 nano 中关闭该文件,系统会提示您:
输入字母 y,然后再次按 ENTER 键以确认以下提示的文件名:
使用 gcloud 在 App Engine 上部署应用:
gcloud app deploy
部署应用后,您可以在网络浏览器中打开网址 https://< PROJECT_ID >.appspot.com 来访问该应用。
摘要
在此步骤中,您将设置一个 Python Web 应用并将其部署到 App Engine 柔性环境。
您已了解如何编写和部署您的第一个 App Engine 柔性环境 Web 应用!
清理
为避免系统因本快速入门中使用的资源向您的 Google Cloud Platform 帐号收取费用,请执行以下操作:
- 访问 Cloud Platform Console。
- 选择要关停的项目,然后点击顶部的“删除”,此操作会将该项目安排删除。
了解详情
- Google Cloud Platform 上的 Python:https://cloud.google.com/python/
- Python 版 App Engine 柔性环境文档:https://cloud.google.com/appengine/docs/flexible/python/
- Python 客户端库:Datastore、Storage 和 Vision
- 更多 Python 代码示例:https://cloud.google.com/python/samples
许可
此作品已获得 Creative Commons Attribution 2.0 通用许可授权。