本文档介绍如何实现将微服务与 Pub/Sub 和 GKE 集成中所述的参考架构。此架构旨在使用容器和异步消息传递功能来处理长时间运行的进程。
本文档使用一个示例照片分享应用来生成照片缩略图。您可以使用 Google Kubernetes Engine (GKE) 来部署应用,并使用 Pub/Sub 来异步调用长时间运行的进程。您还可以使用适用于 Cloud Storage 的 Pub/Sub 通知功能来添加一些辅助作业,而无需修改应用的代码。
应用由 Cloud Build 容器化并存储在 Artifact Registry 中。它使用 Cloud Vision 来检测不当图片。
架构
下图展示了实现参考架构的示例相册应用的设计。
图 1. 基于使用容器和异步消息传递的图片处理架构。
上图展示了如何生成缩略图:
- 客户端将图片上传到应用。
- 应用将图片存储在 Cloud Storage 中。
- 系统为缩略图生成请求。
- 缩略图生成器生成缩略图。
- 成功响应被发送到相册应用。
- 成功的响应被发送给客户端,您可以在 Cloud Storage 中找到该缩略图。
下图展示了应用如何以异步方式将缩略图生成功能作为一项单独的服务来实现。
图 2. 缩略图提取进程的架构。
您可以使用 Pub/Sub 向缩略图生成服务发送服务请求。这一新架构以异步方式调用服务,使应用将响应发送回客户端后才在后台创建缩略图。该设计还让您可以对缩略图生成服务进行扩缩,以便多个作业能够并行运行。
目标
- 在 GKE 上部署示例相册应用。
- 从应用发出异步服务调用。
- 在将新文件上传到 Cloud Storage 存储桶时,使用 Cloud Storage 的 Pub/Sub 通知触发应用。
- 使用 Pub/Sub 执行更多任务,而无需修改应用。
费用
在本文档中,您将使用 Google Cloud 的以下收费组件:
- Cloud Storage
- Cloud SQL
- Pub/Sub
- GKE 使用的 Compute Engine 实例
- GKE 的集群管理费用
- Cloud Load Balancing
- Cloud Build
- Artifact Registry
- Vision
您可使用价格计算器根据您的预计使用情况来估算费用。
完成示例应用的构建后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理。
须知事项
- 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
启用 GKE, Cloud SQL, Cloud Build, Artifact Registry, and Cloud Vision API。
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
启用 GKE, Cloud SQL, Cloud Build, Artifact Registry, and Cloud Vision API。
-
在 Google Cloud 控制台中,激活 Cloud Shell。
Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。
设置环境
在本部分中,您将为整个文档中使用的值分配默认设置。如果您关闭 Cloud Shell 会话,则会丢失这些环境设置。
在 Cloud Shell 中,设置默认 Google Cloud 项目:
gcloud config set project PROJECT_ID
将
PROJECT_ID
替换为您的 Google Cloud 项目 ID。设置默认的 Compute Engine 区域:
gcloud config set compute/region REGION export REGION=REGION
将
REGION
替换为您附近的区域。如需了解详情,请参阅区域和地区。设置默认的 Compute Engine 可用区:
gcloud config set compute/zone ZONE export ZONE=ZONE
将
ZONE
替换为您附近的可用区。下载示例应用文件并设置当前目录:
git clone https://github.com/GoogleCloudPlatform/gke-photoalbum-example cd gke-photoalbum-example
创建 Cloud Storage 存储桶并上传默认缩略图
在 Cloud Shell 中,创建 Cloud Storage 存储分区以存储原始图片和缩略图:
export PROJECT_ID=$(gcloud config get-value project) gsutil mb -c regional -l ${REGION} gs://${PROJECT_ID}-photostore
上传默认缩略图文件:
gsutil cp ./application/photoalbum/images/default.png \ gs://${PROJECT_ID}-photostore/thumbnails/default.png
- 按以下格式存储上传的图片:
gs://PROJECT_ID-photostore/FILENAME
,其中FILENAME
表示上传的图片文件的名称。 - 按以下格式存储生成的缩略图:
gs://PROJECT_ID-photostore/thumbnails/FILENAME
。 - 原始图片和相应的缩略图具有相同的
FILENAME
值,但缩略图存储在thumbnails
存储桶中。 创建缩略图时,相册应用中会显示以下
default.png
占位符缩略图。
- 按以下格式存储上传的图片:
将缩略图文件设为公开:
gsutil acl ch -u AllUsers:R \ gs://${PROJECT_ID}-photostore/thumbnails/default.png
创建 Cloud SQL 实例和 MySQL 数据库
在 Cloud Shell 中,创建 Cloud SQL 实例:
gcloud sql instances create photoalbum-db --region=${REGION} \ --database-version=MYSQL_8_0
检索连接名称:
gcloud sql instances describe photoalbum-db \ --format="value(connectionName)"
记下该名称,后面您将用到该名称。
为
root@%
MySQL 用户设置密码:gcloud sql users set-password root --host=% --instance=photoalbum-db \ --password=PASSWORD
将
PASSWORD
替换为root@%
用户的安全密码。连接到 Cloud SQL 实例:
gcloud sql connect photoalbum-db --user=root --quiet
出现提示时,输入您在上一步中设置的密码。
创建一个名为
photo_db
的数据库,其中用户为appuser
,密码为pas4appuser
:create database photo_db; create user 'appuser'@'%' identified by 'pas4appuser'; grant all on photo_db.* to 'appuser'@'%' with grant option; flush privileges;
确认结果并从 MySQL 退出:
show databases; select user from mysql.user; exit
在输出中,确认已创建
photo_db
数据库和appuser
用户:mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | photo_db | | sys | +--------------------+ 5 rows in set (0.16 sec) mysql> \t Outfile disabled. mysql> select user from mysql.user; +-------------------+ | user | +-------------------+ | appuser | | cloudsqlreplica | | cloudsqlsuperuser | | root | | cloudsqlexport | | cloudsqlimport | | cloudsqloneshot | | root | | cloudsqlexport | | cloudsqlimport | | cloudsqloneshot | | root | | cloudsqlapplier | | cloudsqlimport | | mysql.infoschema | | mysql.session | | mysql.sys | | root | +-------------------+ 18 rows in set (0.16 sec) mysql> exit Bye
创建 Pub/Sub 主题和订阅
在 Cloud Shell 中,创建名为
thumbnail-service
的 Pub/Sub 主题:gcloud pubsub topics create thumbnail-service
相册应用通过在
thumbnail-service
主题上发布消息,向缩略图生成服务发送请求。创建名为
thumbnail-workers
的 Pub/Sub 订阅:gcloud pubsub subscriptions create --topic thumbnail-service thumbnail-workers
缩略图生成服务会收到来自
thumbnail-workers
订阅的请求。
创建 GKE 集群
在 Cloud Shell 中,创建一个有权调用 API 的 GKE 集群:
gcloud container clusters create "photoalbum-cluster" \ --scopes "https://www.googleapis.com/auth/cloud-platform" \ --num-nodes "5"
配置访问凭据,以便在后续步骤中使用
kubectl
命令管理集群:gcloud container clusters get-credentials photoalbum-cluster
显示节点列表:
kubectl get nodes
在输出中,确认有 5 个节点的
STATUS
值为Ready
:NAME STATUS ROLES AGE VERSION gke-photoalbum-cluster-default-pool-d637570a-2pfh Ready <none> 2m55s v1.24.10-gke.2300 gke-photoalbum-cluster-default-pool-d637570a-3rm4 Ready <none> 2m55s v1.24.10-gke.2300 gke-photoalbum-cluster-default-pool-d637570a-f7l4 Ready <none> 2m55s v1.24.10-gke.2300 gke-photoalbum-cluster-default-pool-d637570a-qb2z Ready <none> 2m53s v1.24.10-gke.2300 gke-photoalbum-cluster-default-pool-d637570a-rvnp Ready <none> 2m54s v1.24.10-gke.2300
创建 Artifact Registry 代码库
在 Cloud Shell 中,创建一个代码库来存储容器映像:
gcloud artifacts repositories create photoalbum-repo \ --repository-format=docker \ --location=us-central1 \ --description="Docker repository"
为应用构建映像
在文本编辑器中,打开
application/photoalbum/src/auth_decorator.py
文件并更新用户名和密码:USERNAME = 'username' PASSWORD = 'passw0rd'
在 Cloud Shell 中,使用 Cloud Build 服务为相册应用构建映像:
gcloud builds submit ./application/photoalbum -t \ us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/photoalbum-app
使用 Cloud Build 服务为
thumbnail-worker
缩略图生成服务构建映像:gcloud builds submit ./application/thumbnail -t \ us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/thumbnail-worker
部署相册应用
在 Cloud Shell 中,使用您环境中的值更新相册和缩略图生成器的 Kubernetes Deployment 清单:
connection_name=$(gcloud sql instances describe photoalbum-db \ --format "value(connectionName)") digest_photoalbum=$(gcloud container images describe \ us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/photoalbum-app:latest --format \ "value(image_summary.digest)") sed -i.bak -e "s/\[PROJECT_ID\]/${PROJECT_ID}/" \ -e "s/\[CONNECTION_NAME\]/${connection_name}/" \ -e "s/\[DIGEST\]/${digest_photoalbum}/" \ config/photoalbum-deployment.yaml digest_thumbnail=$(gcloud container images describe \ us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/thumbnail-worker:latest --format \ "value(image_summary.digest)") sed -i.bak -e "s/\[PROJECT_ID\]/${PROJECT_ID}/" \ -e "s/\[CONNECTION_NAME\]/${connection_name}/" \ -e "s/\[DIGEST\]/${digest_thumbnail}/" \ config/thumbnail-deployment.yaml
创建部署资源以启动相册应用和缩略图生成服务:
kubectl create -f config/photoalbum-deployment.yaml kubectl create -f config/thumbnail-deployment.yaml
创建服务资源,为应用分配外部 IP 地址:
kubectl create -f config/photoalbum-service.yaml
查看 Pod 的结果:
kubectl get pods
在输出中,确认每个
photoalbum-app
和thumbail-worker
Pod 有 3 个 Pod 且其STATUS
值为Running
:NAME READY STATUS RESTARTS AGE photoalbum-app-555f7cbdb7-cp8nw 2/2 Running 0 2m photoalbum-app-555f7cbdb7-ftlc6 2/2 Running 0 2m photoalbum-app-555f7cbdb7-xsr4b 2/2 Running 0 2m thumbnail-worker-86bd95cd68-728k5 2/2 Running 0 2m thumbnail-worker-86bd95cd68-hqxqr 2/2 Running 0 2m thumbnail-worker-86bd95cd68-xnxhc 2/2 Running 0 2m
thumbnail-worker
Pod 会通过thumbnail-workers
订阅来订阅缩略图生成请求。如需了解详情,请参阅如何在源代码中使用callback
函数。查看服务的结果:
kubectl get services
在输出中,确认
photoalbum-service
服务的EXTERNAL-IP
列中有一个外部 IP 地址。服务可能需要几分钟时间才能全部运行。NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.23.240.1 <none> 443/TCP 20m photoalbum-service LoadBalancer 10.23.253.241 146.148.111.115 80:32657/TCP 2m
记下该外部 IP 地址,后面您将用到该 IP 地址。在此示例中,该 IP 地址为
146.148.111.115
。
测试相册应用
如需在网络浏览器中访问已部署的应用,请转到以下网址,并输入您之前设置的用户名和密码:
http://EXTERNAL_IP
将
EXTERNAL_IP
替换为您在上一步中复制的 IP 地址。如需上传图片文件,请点击上传。
此时,屏幕上将显示缩略图占位符。
在后台,缩略图生成服务会创建已上传图片的缩略图。如需查看生成的缩略图,请点击刷新。Cloud Vision API 会添加它检测到的图片标签。
要查看原始图片,请点击缩略图。
添加不当图片检测功能
下图演示了如何使用 Cloud Storage 的 Pub/Sub 通知来触发用于检测不当内容的服务。当 Cloud Storage 存储分区中存储了包含不当内容的新文件时,此功能会对图片进行模糊处理。
在上图中,该服务使用 Vision API 的安全搜索检测功能检测图片中的不当内容。
由于照片应用会异步触发缩略图生成器和图片检查工具;因此,无法保证它们按特定顺序执行。如果缩略图生成发生在图片模糊处理之前,那么您可能会在短时间内看到不当缩略图。但是,图片检查工具最终会对不当图片和不当缩略图进行模糊处理。
创建 Pub/Sub 主题、订阅和通知
在 Cloud Shell 中,创建名为
safeimage-service
的 Pub/Sub 主题:gcloud pubsub topics create safeimage-service
创建名为
safeimage-workers
的 Pub/Sub 订阅:gcloud pubsub subscriptions create --topic safeimage-service \ safeimage-workers
配置 Pub/Sub 通知,以便在新文件上传到 Cloud Storage 存储分区时向
safeimage-service
主题发送消息:gsutil notification create -t safeimage-service -f json \ gs://${PROJECT_ID}-photostore
构建和部署工作器映像
在 Cloud Shell 中,使用 Cloud Build 为
safeimage-workers
订阅构建容器映像:gcloud builds submit ./application/safeimage \ -t us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/safeimage-worker
使用 Google Cloud 项目 ID、Cloud SQL 连接名称和容器映像摘要更新安全映像服务的 Kubernetes Deployment 清单:
digest_safeimage=$(gcloud container images describe \ us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/safeimage-worker:latest --format \ "value(image_summary.digest)") sed -i.bak -e "s/\[PROJECT_ID\]/${PROJECT_ID}/" \ -e "s/\[CONNECTION_NAME\]/${connection_name}/" \ -e "s/\[DIGEST\]/${digest_safeimage}/" \ config/safeimage-deployment.yaml
创建部署资源
创建名为
safeimage-deployment
的部署资源以部署safeimage-service
主题:kubectl create -f config/safeimage-deployment.yaml
检查结果:
kubectl get pods
在输出中,确认有 3 个
safeimage-worker
Pod 的STATUS
值为Running
。NAME READY STATUS RESTARTS AGE photoalbum-app-555f7cbdb7-cp8nw 2/2 Running 0 30m photoalbum-app-555f7cbdb7-ftlc6 2/2 Running 0 30m photoalbum-app-555f7cbdb7-xsr4b 2/2 Running 8 30m safeimage-worker-7dc8c84f54-6sqzs 1/1 Running 0 2m safeimage-worker-7dc8c84f54-9bskw 1/1 Running 0 2m safeimage-worker-7dc8c84f54-b7gtp 1/1 Running 0 2m thumbnail-worker-86bd95cd68-9wrpv 2/2 Running 0 30m thumbnail-worker-86bd95cd68-kbhsn 2/2 Running 2 30m thumbnail-worker-86bd95cd68-n4rj7 2/2 Running 0 30m
safeimage-worker
Pod 会通过safeimage-workers
订阅来订阅不当图片检测请求。如需了解详情,请参阅如何在源代码中使用callback
函数。
测试不当图片检测功能
在此部分中,您需要上传一张测试图片,以验证安全搜索检测功能是否对不当图片进行了模糊处理。测试图片是一张装扮成僵尸的女孩的照片(经 Pixaby CC0 许可授权使用)。
- 下载测试图片。
- 如需上传图片,请转到
http://EXTERNAL_IP
,然后点击上传。 点击刷新。此时,该应用会显示经过模糊处理的缩略图。
要查看上传的图片是否也经过了模糊处理,请点击缩略图。
清理
如果您不想保留为示例应用创建的 Google Cloud 资源,则可以移除这些资源,以免日后继续为这些资源付费。您可以彻底删除项目,也可以删除集群资源,然后删除集群。
删除项目
- 在 Google Cloud 控制台中,进入管理资源页面。
- 在项目列表中,选择要删除的项目,然后点击删除。
- 在对话框中输入项目 ID,然后点击关闭以删除项目。
逐个删除资源
除了删除项目之外,您也可以逐个删除自己创建的资源。
删除 GKE 中的资源:
kubectl delete -f config/safeimage-deployment.yaml kubectl delete -f config/photoalbum-service.yaml kubectl delete -f config/thumbnail-deployment.yaml kubectl delete -f config/photoalbum-deployment.yaml
删除 GKE 中的集群:
gcloud container clusters delete photoalbum-cluster --quiet
从 Artifact Registry 中删除代码库:
gcloud artifacts repositories delete photoalbum-repo --location us-central1 --quiet
删除 Pub/Sub 中的订阅和主题:
gcloud pubsub subscriptions delete safeimage-workers gcloud pubsub topics delete safeimage-service gcloud pubsub subscriptions delete thumbnail-workers gcloud pubsub topics delete thumbnail-service
删除 Cloud SQL 实例:
gcloud sql instances delete photoalbum-db --quiet
删除 Cloud Storage 存储分区:
gsutil rm -r gs://${PROJECT_ID}-photostore gsutil rm -r gs://${PROJECT_ID}_cloudbuild
删除文件:
cd .. rm -rf gke-photoalbum-example
后续步骤
- 了解 DevOps,并详细了解与此参考架构相关的架构功能。
- 进行 DevOps 快速检查,了解您与业界其他公司相比所处的位置。
- 如需查看更多参考架构、图表和最佳实践,请浏览云架构中心。