从我们的全球测试基础设施监控关键用户旅程,并了解网络和前端性能对用户体验的影响。 全面了解你的网站性能、功能和可用性(从开发到生产),并在客户之前发现问题。合成监测(synthetic monitoring)使你能够模拟、跟踪和可视化关键用户旅程的性能。本文将从零基础教会你如何对网站进行检测。合成监测扩展了传统的端到端测试技术,因为它允许你的测试在云上持续运行。 通过综合监测,你可以通过重复使用用于在计算机上验证软件的相同旅程来保障你的应用程序在部署后继续工作。
你可以使用合成监视器来检测由你无法预测且未编写测试的无效状态引起的错误。 合成监测器还可以让你定期模拟用户的操作,从而帮助你捕获流量不大的功能中的错误。
Synthetic monitoring 分类
Synthetics 定期检查你的服务和应用程序的状态。 使用以下类型的监视器监视网络端点和服务的可用性。目前 synthetic monitoring 分为两种:
- Lightweight HTTP/S, TCP, and ICMP monitors
- Browser monitors
注意:
Synthetics 应用程序用于查看直接在 Synthetics 应用程序中创建和管理或使用项目(projects)在外部管理的监视器的结果数据。 这可以包括轻量级监视器和基于浏览器的监视器,也可以包括从 Elastic 的全局托管测试基础设施或私有位置(Private Locations)运行的监视器。
要查看通过 Heartbeat 运行并使用传统 heartbeat.yml 文件配置的轻量级监视器的结果数据,请使用 Uptime 应用程序而不是 Synthetics 应用程序。
轻量级 HTTP/S、TCP 和 ICMP 监视器
你可以使用以下轻量级检查来监视网络端点的状态:
名称 | 描述 |
---|---|
HTTP monitor | 监控你的网站。 HTTP 监视器进行检查以确保特定端点返回正确的状态代码并显示正确的文本。 |
ICMP monitor | 检查主机的可用性。 ICMP 监视器使用 ICMP(v4 和 v6)回显请求来检查你正在 ping 的主机的网络可达性。 这将告诉你主机是否可用并连接到网络,但不会告诉你主机上的服务是否正在运行。 |
TCP monitor | 监控主机上运行的服务。 TCP 监视器检查各个端口以确保服务可访问并正在运行。 |
Browser monitors - 浏览器监视器
真正的浏览器综合监控使你能够测试最终用户在受控环境中按预定义的时间间隔在你的网站上发出的关键操作和请求。 综合监控扩展了传统的端到端测试技术,因为它允许你的测试在云上持续运行。 结果是丰富、一致且可重复的数据,你可以根据这些数据进行趋势分析和警报。
例如,你可以测试流行的用户旅程,例如登录、将商品添加到购物车以及签出需要对用户持续有效的操作。你可以在真正的 Chromium 浏览器上运行自动综合监控项目,并在 Kibana 中与其他监视器并排查看每个合成监控过程。警报可帮助你在用户之前检测到性能下降或操作损坏。 通过尽早接收警报,你可以在问题影响你的利润或客户体验之前解决问题。
我们在下面以 Browser monitor 为例来进行展示。我将使用最新的 Elastic Stack 8.8.2 来进行展示。
开发的方式
要设置合成监视器,你需要配置监视器、运行它并将数据发送回 Elasticsearch。 设置完成后,数据将可在 Kibana 中查看、分析和发出警报。设置合成监视器有两种方法:
- Project monitors
- The Synthetics app
Project monitors - 项目检测器
借助 Elastic Project 监视器,你可以使用 YAML(用于轻量级监视器)和 JavaScript 或 TypeScript(用于浏览器监视器)在外部版本控制项目中编写测试。 然后,你使用 @elastic/synthetics NPM 库的推送命令在 Kibana 中创建监视器。
如果你想同时创建浏览器监视器和轻量级监视器,则此方法非常有效。 它还允许你使用 GitOps 工作流程配置和更新监视器。
Synthetics app
Synthetics 应用程序是 Kibana 中的应用程序。 你可以使用用户界面直接在 Synthetics 应用程序中创建监视器。
如果你想使用浏览器中的 UI 配置和更新监视器,则此方法非常有效。
注意:
Elastic Synthetics 集成是一种创建合成监视器的方法,现已不再推荐。 请勿使用 Elastic Synthetics 集成来设置新监视器。
有关如何从 Elastic Synthetics 集成迁移到项目监视器或 Synthetics 应用程序的详细信息,请参阅从 Elastic Synthetics 集成迁移。
如果你过去使用 Elastic Synthetics 集成创建监视器并且需要参考有关集成的文档,请转到 8.3 文档。
安装
如果你还没有安装好自己的 Elasticsearch 及 Kibana,请参考如下的文章来进行安装:
-
如何在 Linux,MacOS 及 Windows 上进行安装 Elasticsearch
-
Kibana:如何在 Linux,MacOS 及 Windows 上安装 Elastic 栈中的 Kibana
在安装的时候,请选择 Elastic Stack 8.x 的安装指南来进行安装。由于在我们的监控中,我们需要使用到 fleet,内置的 API service 必须启动。在我们的安装中,我们需要对 Elasticsearch 及 Kibana 的安装做如下的调整。Elasticsearch 的配置文件 config/elasticsearch.yml 文件配置:
xpack.security.authc.api_key.enabled: true
配置完后,我们再重新启动 Elasticsearch。针对 Kibana,我们也需要做一个额外的配置。我们需要修改 config/kibana.yml 文件。在这个文件的最后面,添加如下的一行:
xpack.encryptedSavedObjects.encryptionKey: 'fhjskloppd678ehkdfdlliverpoolfcr'
如果你不想使用上面的这个设置,你可以使用如下的方式来获得:
./bin/kibana-encryption-keys generate
从上面的输出中,我们可以看出来,有三个输出的 key。我们可以把这三个同时拷贝,并添加到 config/kibana.yml 文件的后面。当然,我们也可以只拷贝其中的一个也可。我们再重新启动 Kibana。
这样我们对 Elasticsearch 及 Kibana 的配置就完成。 针对 Elastic Stack 8.0 以前的版本安装,请阅读我之前的文章 “Observability:如何在最新的 Elastic Stack 中使用 Fleet 摄入 system 日志及指标”。
除此之外,Kibana 需要 Internet 连接才能从 Elastic Package Registry 下载集成包。 确保 Kibana 服务器可以连接到 https://epr.elastic.co 的端口 443 上 。如果你的环境有网络流量限制,有一些方法可以解决此要求。 有关详细信息,请参阅气隙环境。
目前,Fleet 只能被具有 superuser role 的用户所使用。我将使用如下的架构来进行练习:
如上所示,我在自己的电脑上安装 Elasticsearch,Kibana,Fleet server 及 Elastic agent。我们使用它们来针对网站 Vue.js • TodoMVC 来进行监测。Vue.js • TodoMVC 是一个非常简单的网站。它是一个 todo 功能的网站。它可以用来创建一个 task,删除一个 task。
配置 Fleet
我们需要在本地电脑中安装 Fleet server 及 Elastic Agent。我们可以使用 docker 来进行部署。这也是最为方便的方法。我们可以参考链接 Run Elastic Agent in a container | Fleet and Elastic Agent Guide [8.8] | Elastic 来进行安装。针对 synthetics monitoring,我们需要用到一个特殊版本的镜像 elastic-agent-complete。针对我们的情况,我们是 self-managed 的 Elasticsearch 集群。我们首先打开 Kibana:
我们在上面已经成功地创建了 fleet-server-policy。我们直接拷贝上面的命令:
curl -L -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-8.8.2-darwin-x86_64.tar.gz
tar xzvf elastic-agent-8.8.2-darwin-x86_64.tar.gz
cd elastic-agent-8.8.2-darwin-x86_64
sudo ./elastic-agent install \--fleet-server-es=https://192.168.0.3:9200 \--fleet-server-service-token=AAEAAWVsYXN0aWMvZmxlZXQtc2VydmVyL3Rva2VuLTE2ODg0MzU0MDY5MjA6S19NQ3pTbUpRTzJxWndhcURPRWY5Zw \--fleet-server-policy=fleet-server-policy \--fleet-server-es-ca-trusted-fingerprint=bd0a26dc646ef1cb3cb5e132e77d6113e1b46d56ee390dd3c6f0b2d2b16962c4 \--fleet-server-port=8220
在这里,我们需要注意的是:我们不需要运行上面的命令。我们记下上面的 policy,Elasticsearch 的地址及 service token。我们参考网址 Run Elastic Agent in a container | Fleet and Elastic Agent Guide [8.8] | Elastic 并拷贝里面的命令:
docker run \--env FLEET_SERVER_ENABLE=true \ --env FLEET_SERVER_ELASTICSEARCH_HOST=<elasticsearch-host> \ --env FLEET_SERVER_SERVICE_TOKEN=<service-token> \ --env FLEET_SERVER_POLICY_ID=<fleet-server-policy> \ -p 8220:8220 \ --rm docker.elastic.co/beats/elastic-agent:8.8.2
我们需要使用上面得到的信息来进行修改:
docker run \--volume="$PWD/http_ca.crt:/usr/share/certs/http_ca.crt:ro" \--env FLEET_SERVER_ENABLE=true \--env FLEET_SERVER_ELASTICSEARCH_HOST=https://192.168.0.3:9200 \--env FLEET_SERVER_SERVICE_TOKEN=AAEAAWVsYXN0aWMvZmxlZXQtc2VydmVyL3Rva2VuLTE2ODg0MzU0MDY5MjA6S19NQ3pTbUpRTzJxWndhcURPRWY5Zw \--env FLEET_SERVER_POLICY_ID=fleet-server-policy \-p 8220:8220 \--user=elastic-agent \--env FLEET_SERVER_ELASTICSEARCH_CA=/usr/share/certs/http_ca.crt\--rm docker.elastic.co/beats/elastic-agent-complete:8.8.2
为了能够使得我们的 fleet server 能够正确地连接到 Elasticsearch,我们必须把 Elasticsearch 的证书也拷贝到当前的目录中:
$ pwd
/Users/liuxg/fleet
$ cp ~/elastic/elasticsearch-8.8.2/config/certs/http_ca.crt .
$ ls
http_ca.crt
我们接着运行上面的 docker 命令:
我们回到 Kibana 的界面:
上面显示我们的 Fleet server 已经成功地连接到 Elasticsearch 了。
我们甚至可以使用如下的命令来进行查看端口的使用情况:
sudo lsof -i -P | grep LISTEN | grep 8220
$ sudo lsof -i -P | grep LISTEN | grep 8220
com.docke 64198 liuxg 115u IPv6 0xab7bdc71c082f047 0t0 TCP *:8220 (LISTEN
上面显示我们的 8220 端口已经被使用,并且是以 IPv6 的格式进行创建的。
使用项目监测器创建监视器
项目是在 Elastic Stack 中配置合成监测器的最强大、最复杂的方式。 项目允许你将基础设施定义为代码,通常称为 IaaC 或 Git-ops。 通过项目监测器,你可以在文件系统上组织 YAML 配置和 JavaScript 或 TypeScript 定义的监视器,使用 Git 进行版本控制,并通过 CLI 工具进行部署(通常在 CI/CD 平台上执行)。
前提条件
你必须以至少具有 synthetics write permissions 的用户身份登录 Kibana,并且必须由管理员启用监控管理,如设置角色中所述。
处理项目需要使用 Elastic Synthetics CLI 工具,可以通过 npx @elastic/synthetics 命令调用该工具。 在开始之前,你需要:
1)安装 Nodejs
2)安装下面的 package:
npm install -g @elastic/synthetics
3)确认你的系统设置正确:
npx @elastic/synthetics -h
在开始之前,你还应该决定要在哪里运行监视器。 你可以在以下一项或两项上运行项目监视器:
- Elastic 的全球托管测试基础设施:借助 Elastic 的全球托管测试基础设施,你可以在多个位置创建和运行监视器,而无需管理自己的基础设施。 Elastic 会为您处理软件更新和容量规划。
- 私有位置(Private Locations):私人位置允许您从自己的场所运行监视器。 要使用私人位置,你必须先创建一个私有位置,然后才能继续。 有关分步说明,请参阅监控专用网络上的资源。
注意:如果你正在为配置了流量过滤器的部署设置 Synthetics,则与 Elasticsearch 的连接将受到限制,并且除非获得许可,否则结果将无法写回 Elasticsearch。 有关更多详细信息,请参阅将 Synthetics 与流量过滤器结合使用。
创建位置
打开 Kibana:
在上面我们创建了一个叫做 Beijing 的私有位置。
创建项目
运行以下命令在当前目录中创建一个新项目:
npx @elastic/synthetics init
由于我们不使用 Elastic Cloud,我们选择 false。在我们输入 Kibana instance 的地址的时候,一定要注意的是:如果我们使用 http://localhost:5601,这个可能会有问题。在我的电脑上,localhost 可能被解析为 IPv6 的格式,但是我的 Kibana 是绑定于 IPv4 的系统。这个依赖于你自己的系统配置。在上面,我们也可以多添加一个参数来作为项目的名称:
npx @elastic/synthetics init projects-test
我们拷贝上面提示中的链接来创建 API:
把上面的 API key 拷贝出来,并粘贴到上面的命令中:
我们使用空格键选中 Beijing 这个私有位置:
使用空格键每三分钟检测一次:
使用 synthetics-demo 作为 project id:
选择 Kibana space 为 default:
这样,我们就完成了一个最为基本的项目创建。我们首先看一下当前的文件架构:
$ ls -al
total 288
drwxr-xr-x 12 liuxg staff 384 Jul 4 11:04 .
drwxr-xr-x 22 liuxg staff 704 Jul 4 10:10 ..
drwxr-xr-x 3 liuxg staff 96 Jul 4 10:49 .github
-rw-r--r-- 1 liuxg staff 27 Jul 4 10:49 .gitignore
drwxr-xr-x 2 liuxg staff 64 Jul 4 11:04 .synthetics
-rw-r--r-- 1 liuxg staff 1323 Jul 4 10:49 README.md
drwxr-xr-x 5 liuxg staff 160 Jul 4 10:49 journeys
drwxr-xr-x 3 liuxg staff 96 Jul 4 11:19 lightweight
drwxr-xr-x 136 liuxg staff 4352 Jul 4 10:49 node_modules
-rw-r--r-- 1 liuxg staff 130010 Jul 4 10:49 package-lock.json
-rw-r--r-- 1 liuxg staff 329 Jul 4 10:49 package.json
-rw-r--r-- 1 liuxg staff 745 Jul 4 10:49 synthetics.config.ts
我们注意到有两个目录 lightweight 及 journeys。这两个目录中分别含有测试的案例。这也印证了之前所说的,project monitors 非常适合既含有 lightweight 也有浏览器的监测。
让我们查看项目中的关键文件和目录:
- journeys 是你添加定义浏览器监视器的 .ts 和 .js 文件的地方。 当你创建新项目时,此目录将包含定义示例监视器的文件。
- lightweight 是你添加定义轻量级监视器的 .yaml 文件的位置。 当你创建新项目时,此目录将包含一个定义示例监视器的文件。
- synthesis.config.ts 包含项目的设置。 当你创建新项目时,它将包含一些您可以稍后自定义的基本配置选项。
- package.json 包含项目的 NPM 设置。 在 NPM 文档中了解更多信息。
- .github 包含与 GitHub Actions 一起使用的示例工作流程文件。
其中的一个文件叫做 synthetics.config.ts。它描述了 synthetics monitoring 的配置情况:
cat synthetics.config.ts
$ cat synthetics.config.ts
import type { SyntheticsConfig } from '@elastic/synthetics';export default env => {const config: SyntheticsConfig = {params: {url: 'https://elastic.github.io/synthetics-demo/',},playwrightOptions: {ignoreHTTPSErrors: false,},/*** Configure global monitor settings*/monitor: {schedule: 3,locations: [],privateLocations: ['Beijing'],},/*** Project monitors settings*/project: {id: 'synthetics-demo',url: 'http://127.0.0.1:5601',space: 'default',},};if (env !== 'development') {/*** Override configuration specific to environment* Ex: config.params.url = ""*/}return config;
};
这里的信息和我们上面输入的信息是一致的。我们甚至可以手动来配置这个文件。
示例 HTTP 监视器
在 lightweight 目录中,你将找到示例 lightweight 监视器。 以下是定义轻量级监视器的 YAML 文件示例:
heartbeat.yml
heartbeat.monitors:
- type: httpname: Todos Lightweightid: todos-lightweightenabled: trueurls: "https://elastic.github.io/synthetics-demo/"schedule: '@every 3m'timeout: 16salert.status.enabled: true
它被用来检测该网站的连接状态。更多关于如何配置 lightweight 的选项,请参阅链接 Configure lightweight monitors。
示例 journeys
在 journeys 目录中,你将找到示例 browser 监视器。 以下是定义 browser 监视器的 TypeScript 文件示例:
// example.journey.ts
import { journey, step, monitor, expect } from '@elastic/synthetics';
journey('My Example Journey', ({ page, params }) => {// Only relevant for the push command to create// monitors in Kibanamonitor.use({id: 'example-monitor',schedule: 10,});step('launch application', async () => {await page.goto(params.url);});step('assert title', async () => {const header = await page.locator('h1');expect(await header.textContent()).toBe('todos');});
});
上面的代码是每隔 10 分钟运行一次。进入到主页后,确定 h1 header 的内容是 “todos”。否则这项测试是错误的。
在项目目录中,你可以使用 npx @elastic/synthetics 命令执行两件事:
- 在本地测试基于浏览器的监视器。 要运行 .ts 和 .js 文件中定义的所有旅程:
npx @elastic/synthetics journeys
$ npx @elastic/synthetics journeysJourney: addition and completion of single task✓ Step: 'launch app' succeeded (1311 ms)✓ Step: 'add task Don't put salt in your eyes' succeeded (93 ms)✓ Step: 'check that task list has exactly 1 elements' succeeded (22 ms)✓ Step: 'check for task 'Don't put salt in your eyes' in list' succeeded (34 ms)✓ Step: 'destroy task 'Don't put salt in your eyes'' succeeded (74 ms)✓ Step: 'check that task list has exactly 0 elements' succeeded (33 ms)Journey: adding and removing multiple tasks✓ Step: 'launch app' succeeded (1272 ms)✓ Step: 'add task Task 1' succeeded (54 ms)✓ Step: 'add task Task 2' succeeded (35 ms)✓ Step: 'add task Task 3' succeeded (39 ms)✓ Step: 'check that task list has exactly 3 elements' succeeded (24 ms)✓ Step: 'destroy task 'Task 2'' succeeded (74 ms)✓ Step: 'check that task list has exactly 2 elements' succeeded (27 ms)✓ Step: 'add task Task 4' succeeded (34 ms)✓ Step: 'check that task list has exactly 3 elements' succeeded (23 ms)Journey: My Example Journey✓ Step: 'launch application' succeeded (1198 ms)✓ Step: 'assert title' succeeded (33 ms)17 passed (8660 ms)
- 将所有监视器配置推送到 Elastic 部署。 从项目内部运行以下命令:
npx @elastic/synthetics push --auth $SYNTHETICS_API_KEY --url <kibana-url>
每个旅程的 Synthetics 应用程序中都会出现一个监视器或 lightweight 监视器,你将管理本地环境中的所有监视器。 有关使用 push 命令的更多详细信息,请参阅@elastic/syntheticspush。
注意:如果你添加了私人位置,则可以推送到该私人位置。
要列出可用的私有位置,请使用要从中获取可用位置的部署的 Kibana URL 运行 elastic-synthetics locations 命令。
$ elastic-synthetics locations Available locations: * japan* india* singapore* australia_east* united_kingdom* germany* canada_east* brazil* us_east* us_westSet default location for monitors via- Synthetics config file 'monitors.locations' | 'monitors.privateLocations' field- Monitor API 'monitor.use({ locations: ["japan"], privateLocations: ["custom-location"] }')
$ elastic-synthetics locations --url http://127.0.0.1:5601 --auth TXBIS0hva0JrNXV4SWljNkNBeTc6b016Qms2aHFUNnkwNVlRcVV1ZnNtZw== Available locations: * Beijing(private)Set default location for monitors via- Synthetics config file 'monitors.locations' | 'monitors.privateLocations' field- Monitor API 'monitor.use({ locations: ["japan"], privateLocations: ["custom-location"] }')
我们这个时候如果直接使用下面的命令来进行 push 的话:
npm run push
我们将看到如下的结果:
$ npm run push> synthetics@1.0.0 push> npx @elastic/synthetics push✖ Error✖ monitor creation failed - 401:Unauthorized[security_exceptionRoot causes:security_exception: unable to authenticate with provided credentials and anonymous access is not allowed for this request]: unable to authenticate with provided credentials and anonymous access is not allowed for this request
我们需要在上面生成 API 的界面拷贝第二项:
export SYNTHETICS_API_KEY=TXBIS0hva0JrNXV4SWljNkNBeTc6b016Qms2aHFUNnkwNVlRcVV1ZnNtZw==
运行上面的命令后,我们再次执行:
npm run push
$ npm run push> synthetics@1.0.0 push
> npx @elastic/synthetics push⚠ Lightweight monitor schedules will be adjusted to their nearest frequency supported by our synthetics infrastructure.
> Pushing monitors for project: synthetics-demo
> Monitor Diff: Added(4) Updated(0) Removed(0) Unchanged(0)
> bundling 4 monitors
> creating or updating 4 monitors (7338ms)
✓ Pushed: http://127.0.0.1:5601/app/synthetics/monitors
查看结果
在上面,我们已经上传了 journeys 及 lightweight 测试案例。我们现在启动 Kibana 来查看结果:
从上面的结果中,我们可以看出来网站是 Up 的而不是 Down 的。每隔 3 分钟,会查一次结果。这个和我们在 lightweight 里的配置的 heartbeart.yml 配置相关:
lightweight/heartbeat.yml
heartbeat.monitors:
- type: httpname: Todos Lightweightid: todos-lightweightenabled: trueurls: "https://elastic.github.io/synthetics-demo/"schedule: '@every 3m'timeout: 16salert.status.enabled: true
点击上面的超链接,我们可以看到:
我们接下来进入到 Synthetics 应用程序来进行查看:
我们可以看到有 5 个 monitors。这个和我们之前在 journeys 目录下的 advanced-example.journey.ts 及 example.journey.ts 相对应:
$ pwd
/Users/liuxg/demos/synthetics/journeys
$ ls
advanced-example-helpers.ts advanced-example.journey.ts example.journey.ts
在 advanced-example.journey.ts 文件里,它定义了 2 个测试案例:
import { journey } from '@elastic/synthetics';
import {loadAppStep,addTaskStep,assertTaskListCountStep,checkForTaskStep,destroyTaskStep,
} from './advanced-example-helpers';// This file shows the use of re-usable functions, imported from
// `advanced-example-helpers.ts` to make writing tests that perform
// different combinations of similar functions simpler and with less
// duplication.journey('addition and completion of single task', ({ page, params }) => {const testText = "Don't put salt in your eyes";loadAppStep(page, params.url);addTaskStep(page, testText);assertTaskListCountStep(page, 1);checkForTaskStep(page, testText);destroyTaskStep(page, testText);assertTaskListCountStep(page, 0);
});journey('adding and removing multiple tasks', ({ page, params }) => {const testTasks = ['Task 1', 'Task 2', 'Task 3'];loadAppStep(page, params.url);testTasks.forEach(t => {addTaskStep(page, t);});assertTaskListCountStep(page, 3);// remove the middle task and check that it workeddestroyTaskStep(page, testTasks[1]);assertTaskListCountStep(page, 2);// add a new task and check it existsaddTaskStep(page, 'Task 4');assertTaskListCountStep(page, 3);
});
在 example.journey.ts 中,它也添加了一个测试的案例:
import { journey, step, monitor, expect } from '@elastic/synthetics';journey('My Example Journey', ({ page, params }) => {// Only relevant for the push command to create// monitors in Kibanamonitor.use({id: 'example-monitor',schedule: 10,});step('launch application', async () => {await page.goto(params.url);});step('assert title', async () => {const header = await page.locator('h1');expect(await header.textContent()).toBe('todos');});
});
关于如何书写浏览器检测器,请详细阅读官方文档 Scripting browser monitors | Elastic Observability [8.8] | Elastic。这里就不再累述了。
我们打开其中的一个 monitor:
我们可以打开其中的 screenshot:
显然这个是打开网址的首页:
在其中的一个 sceenshot 里,我们甚至可以看到有添加3个 task 的页面。
上面是删除其中的一个 task 的页面。
点击上面的详细情况:
我们可以清楚地看到时间花在哪里了。这个为我们优化应用非常有帮助。
好了,今天就先讲到这里。希望大家对 Synthetics monitoring 有一个初步的了解。如果有兴趣的话,可以应用到自己的实际项目中去。