本教程介绍了如何使用 Google Cloud 无服务器技术创建 Web 性能监控应用。
性能对于任何 Web 应用的成功都起着非常重要的作用。如果您的网站性能不佳,则注册人数会比较少,用户留存率会比较低,这可能会影响您的业务目标。在设计、构建和测试 Web 应用时,性能应该是衡量成功的一个关键标准。
不过,随着应用的发展,网页性能也可能会随时间发生变化。开发者可能会添加或更新映像和脚本,或者底层应用服务基础架构本身可能会发生变化。因此,定期监控网页性能非常重要。通常,您需要存储性能指标以便进行历史记录分析。此外,您通常还需要设置一些提醒消息,以便系统在网页性能低于某些定义的阈值时收到提醒。
目标
- 创建一个使用无头 Chrome 来收集网页性能指标的 Cloud Functions 函数。
- 将指标存储在 Cloud Storage 中。
- 创建另一个由 Cloud Storage 创建事件触发的 Cloud Functions 函数,以分析网页指标。
- 将分析结果存储在 Firestore 中。
- 创建另一个由 Firestore 创建事件触发的 Cloud Functions 函数,以便在网页性能不佳时向 Pub/Sub 发布提醒消息。
- 创建 Cloud Scheduler 作业以定期触发第一个 Cloud Functions 函数。
- 验证成功和失败情况下的输出。
费用
本教程使用 Google Cloud 的以下收费组件:
- Cloud Functions
- Cloud Scheduler
- Cloud Storage
- Firestore
- Pub/Sub
- Container Registry
- Cloud Build
您可使用价格计算器根据您的预计使用情况来估算费用。
准备工作
- 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
-
在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目。
-
启用 Cloud Functions, Cloud Scheduler, Pub/Sub, and Cloud Build API。
-
在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目。
-
启用 Cloud Functions, Cloud Scheduler, Pub/Sub, and Cloud Build API。
架构
Web 性能监控操作通常是无状态的,而且持续时间很短。它们通常也是由事件驱动的 - 要么按时间表执行,要么作为其他某个过程(例如自动化测试流水线)的一部分触发。这些特性使得无服务器架构成为实现网络分析应用的理想选择。
在本教程中,您将使用 Google Cloud 无服务器栈的各种组件,包括 Cloud Functions、Firestore、Cloud Scheduler、Pub/Sub。您不必管理这些服务的基础架构,并且只需为所用的资源付费。应用的核心是使用 Cloud Functions 实现的,Cloud Functions 提供了一个可扩缩的事件驱动型无服务器执行环境。借助 Cloud Functions,您可以使用松散耦合的独立逻辑块创建和连接应用。
下图展示了您在本教程中创建的无服务器解决方案的架构。
准备环境
在创建无服务器环境之前,您需要从 GitHub 获取代码、设置变量,以及准备稍后进行分析和存储所需的资源。
获取代码并设置环境变量
在 Google Cloud Console 中,打开 Cloud Shell。
克隆包含本教程中使用的 Cloud Functions 函数代码的代码库:
git clone https://github.com/GoogleCloudPlatform/solutions-serverless-web-monitoring.git
切换到 functions 目录:
cd solutions-serverless-web-monitoring/functions
将当前项目 ID 和项目编号设置为 shell 变量:
export PROJECT=$DEVSHELL_PROJECT_ID export PROJECT_NUM=$(gcloud projects list \ --filter="$PROJECT" \ --format="value(PROJECT_NUMBER)")
设置 Cloud Functions 的默认部署区域。以下示例将区域设置为
us-east1
,但您可以将此区域更改为可以使用 Cloud Functions 的任何区域。export REGION=us-east1 gcloud config set functions/region $REGION
创建 Cloud Storage 存储分区
在本部分中,您将创建一个 Cloud Storage 存储分区以存储收集的网页性能数据。您可以选择任何位置或存储类别,但最好是在将要使用相应存储分区的 Cloud Functions 函数所在的位置创建存储分区。
在 Cloud Shell 中,导出将要存储指标的 Cloud Storage 存储分区的名称的 shell 变量。存储分区名称必须是全局唯一的,因此以下命令将您的 Google Cloud 项目编号用作存储分区名称的后缀。
export METRICS_BUCKET=page-metrics-$PROJECT_NUM
使用
gsutil
工具创建存储分区:gsutil mb -l $REGION gs://$METRICS_BUCKET
使用存储分区名称更新
env-vars.yaml
文件。此文件包含您稍后将传递给 Cloud Functions 函数的环境变量。sed -i "s/\[YOUR_METRICS_BUCKET\]/$METRICS_BUCKET/" env-vars.yaml
创建 Firestore 集合
在稍后的部分中,您将分析网页性能指标。在本部分中,您将创建一个 Firestore 集合来存储每项分析的结果。
在 Google Cloud Console 中,前往 Firestore 页面。
如果您之前从未创建过 Firestore 数据库,请执行以下步骤:
- 点击选择原生模式以激活 Firestore。
- 选择靠近您的 Cloud Functions 函数运行区域的区域位置。
- 点击创建数据库。
完成配置需要一些时间。
点击开始收集,然后将集合 ID 设置为
page-metrics
。点击保存。
创建 Pub/Sub 主题和订阅
如果分析表明网页性能不佳,您通常需要通知相关系统和各方。在本部分中,您将创建 Pub/Sub 主题,其中将包含描述任何不佳性能的消息。
在 Cloud Shell 中,创建名为
performance-alerts
的 Pub/Sub 主题:gcloud pubsub topics create performance-alerts
创建对该主题的订阅。您可以使用该订阅来验证提醒消息是否会发布到该主题。
gcloud pubsub subscriptions create performance-alerts-sub \ --topic performance-alerts
收集网页性能指标
很多网站都会使用 JavaScript 来动态呈现网页内容。这会使性能分析变得更复杂,因为客户端需要模拟浏览器才能完全加载网页。适用于 Cloud Functions 的 Node.js 运行时环境支持无头 Chrome,无头 Chrome 可以在无服务器环境中提供完整网络浏览器的功能。
Puppeteer 是由 Chrome DevTools 团队构建的 Node.js 库,用于提供高级 API 来控制无头 Chrome。默认情况下,Puppeleer 会安装最新版本的浏览器和库。因此,您可以将 Puppeteer 作为依赖项添加到 Cloud Functions 函数中,以便在该函数中使用无头 Chrome。
衡量和分析网页性能是一项复杂的大型工作。为简单起见,在本教程中,您将使用 Puppeteer 收集一些顶级网页性能指标。不过,您也可以使用 Puppeteer 和 Chrome DevTools Protocol (CDP) 收集更详细的信息,例如时间轴跟踪记录。您还可以通过模拟网络拥塞和执行 CPU 节流来更好地展现最终用户体验。如需查看有关如何分析网页性能的详细介绍,请参阅 Chrome Web 开发者网站。
请注意,影响网页加载时间的因素有很多,包括客户端的性能特征。请务必使用 Cloud Functions 函数的 CPU 和 RAM 配置来建立基准。
tracer/index.js
文件中的以下代码段展示了如何使用 Puppeteer 加载网页:
在 Cloud Shell 中,部署
trace
Cloud Functions 函数:gcloud functions deploy trace \ --trigger-http \ --runtime nodejs10 \ --memory 1GB \ --source tracer \ --env-vars-file env-vars.yaml \ --quiet
部署 Cloud Functions 函数可能需要几分钟的时间。
部署参数指定函数应具有 HTTP 触发器、应使用 Node.js 10 运行时环境、应具有 1 GB 内存。为了运行无头 Chrome,至少必须具有此内存量。环境变量是通过
env-vars.yaml
文件提供给函数的。
默认情况下,HTTP 触发的 Cloud Functions 函数允许未经身份验证的调用。因此,您必须保护跟踪记录函数。
移除
allUsers
的cloudfunctions.invoker
IAM 角色:gcloud beta functions remove-iam-policy-binding trace \ --member allUsers \ --role roles/cloudfunctions.invoker
分析指标
Web 性能监控练习的一个典型目标是根据一些定义的基准来跟踪性能。如果特定指标超出预期阈值,则可能表示最近的软件版本存在问题或者底层基础架构存在问题。
在本部分中,您将使用 Python 创建 Cloud Functions 函数以解析网页指标并将结果保存到 Firestore 集合中。该函数会根据预期阈值评估 FirstMeaningfulPaint
指标;如果超出阈值,则该函数会将分析结果标记为有问题。FirstMeaningfulPaint
是以用户为中心的指标,用于广泛描述网页何时对用户有用。每当新文件写入包含指标的存储分区时,您都可以使用 Cloud Storage 触发器执行分析函数。
analyzer/main.py
文件中的以下代码段展示了函数逻辑:
部署
analyze
Cloud Functions 函数:gcloud functions deploy analyze \ --trigger-resource gs://$METRICS_BUCKET \ --trigger-event google.storage.object.finalize \ --runtime python37 \ --source analyzer \ --env-vars-file env-vars.yaml
该函数由指标存储分区中的
finalize
事件触发,该事件会在存储分区中每次创建对象时发送。该函数使用 Python 3.7 运行时环境。
在出现故障时发出提醒消息
如果指标分析表明网页性能不佳,您通常需要采取措施。
在本部分中,您将创建 Cloud Functions 函数以便在网页性能不佳时向 Pub/Sub 主题发送消息。每次在 Firestore 集合中创建文档时,系统都会触发该函数。相关各方可以订阅 Pub/Sub 主题并采取适当的措施。例如,支持应用可以订阅 Pub/Sub 消息,以及发送电子邮件、触发支持网页调度程序或提交错误。
alerter/main.py
文件中的以下代码段展示了函数逻辑:
请注意,只有在状态字段指示失败时,系统才会发送提醒消息。
部署
alert
Cloud Functions 函数:gcloud functions deploy alert \ --trigger-event providers/cloud.firestore/eventTypes/document.create \ --trigger-resource "projects/$PROJECT/databases/(default)/documents/page-metrics/{any}" \ --runtime python37 \ --source alerter \ --env-vars-file env-vars.yaml \ --entry-point generate_alert
该函数由
page-metrics
Firestore 集合中的document.create
事件触发。{any}
后缀是一个通配符,它表示,在该集合中创建文档的任何时候,系统都应触发该函数。
安排分析
定期监控网页性能是一种不错的做法。例如,您可能希望每小时、每天或每周分析某个特定网页。在本部分中,您将创建 Cloud Scheduler 作业,以便通过触发 trace
函数来定期运行分析流水线。
Cloud Scheduler 作业是使用服务账号执行的,该服务账号已获得调用 trace
函数所需的 cloudfunctions.invoker
IAM 角色。
有时候,网页没有正确响应或请求超时,于是网络分析应用不得不重试。因此,您的应用务必要有重试逻辑。Cloud Functions 支持后台函数重试。
HTTP 触发的 Cloud Functions 函数无法重试,因此您无法使用 Cloud Functions 重试 trace
函数。不过,Cloud Scheduler 支持重试。如需详细了解如何配置重试参数,请参阅 RetryConfig 文档。
验证三个 Cloud Functions 函数是否已正确部署并显示
ACTIVE
状态:gcloud functions list
创建新的服务账号,该账号将用作执行 Cloud Scheduler 作业的身份:
gcloud iam service-accounts create tracer-job-sa
向新服务账号授予
trace
函数的cloudfunctions.invoker
IAM 角色:gcloud beta functions add-iam-policy-binding trace \ --role roles/cloudfunctions.invoker \ --member "serviceAccount:tracer-job-sa@$PROJECT.iam.gserviceaccount.com"
创建 Cloud Scheduler 作业:
gcloud scheduler jobs create http traceWithRetry \ --uri="https://$REGION-$PROJECT.cloudfunctions.net/trace" \ --http-method=POST \ --message-body="{\"url\":\"http://www.example.com\"}" \ --headers="Content-Type=application/json" \ --oidc-service-account-email="tracer-job-sa@$PROJECT.iam.gserviceaccount.com" \ --schedule="0 3 * * *" \ --time-zone="UTC" \ --max-retry-attempts=3 \ --min-backoff=30s
由于该作业将调用 HTTP 触发的
trace
函数,因此该命令将作业类型指定为http
,并提供函数触发器网址作为uri
值。待分析的网页(在本示例中为www.example.com
)是在message-body
标志中提供的。oidc-service-account-email
标志定义用于身份验证的服务账号。该命令使用max-retry-attempts
标志指示重试次数,而通过schedule
标志传递的值则将运行时间设置为每天凌晨 3:00(世界协调时间 (UTC))。
验证结果
在本部分中,您将验证成功和失败情况下的行为是否符合预期。
验证成功时的行为
Cloud Scheduler 作业将在下一个安排的时间(在本示例中为世界协调时间 (UTC) 凌晨 3:00)开始运行。如需立即查看结果,您可以手动触发运行。
- 等待 90 秒,让调度器作业完成初始化。
手动运行 Cloud Scheduler 作业:
gcloud scheduler jobs run traceWithRetry
等待大约 30 秒,让函数流水线执行完毕。
列出指标存储分区的内容以显示网页指标已收集:
gsutil ls -l gs://$METRICS_BUCKET
在 Google Cloud 控制台中,打开 Cloud Logging 查看器页面:
您会看到来自以下三个 Cloud Functions 函数的日志消息:
trace
、analyze
、alert
。系统可能需要一些时间才能显示日志,因此您可能需要刷新日志窗格。记下 Firestore 文档 ID,该 ID 列在文本
Created new Firestore document page-metrics/
后面在 Google Cloud 控制台中,转到 Firestore 页面:
检查包含分析结果的文档。文档值表示
PASS
状态,并包含最新的网页性能指标。在 Cloud Shell 中,通过尝试拉取订阅的消息来验证系统是否没有向 Pub/Sub 主题发送任何提醒消息:
gcloud pubsub subscriptions pull \ projects/$PROJECT/subscriptions/performance-alerts-sub \ --auto-ack
您不会看到有任何项列出。
验证失败时的行为
手动触发跟踪记录函数。此时,以网址形式提供 Google Cloud 教程页面。此页面包含大量动态内容,导致页面加载时间超过预期的最大阈值。
gcloud functions call trace \ --data='{"url":"https://cloud.google.com/docs/tutorials"}'
由于您具有项目的
Owner
或Editor
IAM 角色,因此有足够的权限来调用该函数。等待大约 30 秒,让函数流水线执行完毕。
列出指标存储分区的内容以验证是否已收集其他指标:
gsutil ls -l gs://$METRICS_BUCKET
现在,您会在每个存储分区中看到两项内容。
在 Google Cloud 控制台中,转到 Cloud Logging 查看器页面并过滤出 Cloud Functions 函数日志:
您会看到来自
analyze
函数的错误,它指示该网页的加载时间超出了允许的最长加载时间。同样,您可能需要刷新日志窗格以查看最新的消息。记下 Firestore 文档 ID。
在 Google Cloud 控制台中,转到 Firestore 页面:
找到描述失败分析的文档。
状态字段会被标记为
FAIL
。在 Cloud Shell 中,通过拉取订阅的消息来验证系统是否向 Pub/Sub 主题发送了提醒消息。
gcloud pubsub subscriptions pull \ projects/$PROJECT/subscriptions/performance-alerts-sub \ --auto-ack
这一次,您会看到消息的内容。
清除数据
删除项目
- 在 Google Cloud 控制台中,进入管理资源页面。
- 在项目列表中,选择要删除的项目,然后点击删除。
- 在对话框中输入项目 ID,然后点击关闭以删除项目。
后续步骤
- 详细了解 Google Cloud 无服务器技术。
- 浏览其他 Cloud Functions 教程。
- 观看 Google I/O '18 大会的视频,其中介绍了 Puppeteer 和无头 Chrome 的其他用途。
- 探索有关 Google Cloud 的参考架构、图表和最佳做法。查看我们的 Cloud Architecture Center。