菜单
开源

使用 Pyroscope 的网约车教程

本教程演示了 Pyroscope 的一个基本用例:通过分析“网约车”应用程序。在本示例中,您将学习

  • 如何使用 Pyroscope 对应用程序进行埋点,包括动态标记函数的技术。
  • 如何在 Grafana 中使用 Profiles View 查看生成的分析数据。
  • 如何将 Pyroscope 与 Grafana 集成以可视化分析数据。

开始之前

完成本教程需要具备以下先决条件

  • Git
  • Docker
  • Docker Compose 插件 (包含在 Docker Desktop 中)

提示

在交互式学习环境中尝试本教程: 使用 Pyroscope 的网约车教程

这是一个已安装所有依赖项的完全配置环境。

Grafana Killercoda 仓库中提供反馈、报告 bug 和提出问题。

背景

在本教程中,您将分析一个简单的“网约车”应用程序。该应用程序是一个模拟网约车服务的 Python Flask 应用。该应用有三个端点,位于 server.py 文件中

  • /bike : 调用 order_bike(search_radius) 函数订购自行车
  • /car : 调用 order_car(search_radius) 函数订购汽车
  • /scooter : 调用 order_scooter(search_radius) 函数订购电动滑板车

为了模拟高可用分布式系统,该应用部署在 3 个不同地区的 3 个独立服务器上

  • us-east
  • eu-north
  • ap-south

这通过在 Docker 容器中运行三个服务器实例来模拟。每个服务器实例都标记了其所代表的地区。

Getting started sample application
入门示例应用程序

在此场景中,负载生成器将向这三个服务器及其各自的端点发送模拟负载。这使您能够按地区和车辆类型查看应用程序的性能。

克隆仓库

  1. 将仓库克隆到您的本地机器

    bash
    git clone https://github.com/grafana/pyroscope.git && cd pyroscope
  2. 导航到教程目录

    bash
    cd examples/language-sdk-instrumentation/python/rideshare/flask

启动应用程序

使用 Docker Compose 启动应用程序

bash
docker compose up -d

下载所需的镜像并构建演示应用程序可能需要几分钟。准备就绪后,您将看到以下输出

console
 ✔ Network flask_default  Created
 ✔ Container flask-ap-south-1  Started
 ✔ Container flask-grafana-1  Started
 ✔ Container flask-pyroscope-1  Started
 ✔ Container flask-load-generator-1 Started
 ✔ Container flask-eu-north-1 Started
 ✔ Container flask-us-east-1 Started

可选:要验证容器正在运行,请运行

bash
docker ps -a

在 Grafana 中访问 Profiles Drilldown

Grafana 包含您可用于查看分析数据的 Profiles Drilldown 应用。要访问 Profiles Drilldown,请打开浏览器并导航到 https://:3000/a/grafana-pyroscope-app/profiles-explorer

标记工作原理

在此示例中,应用程序使用 Python SDK 集成了 Pyroscope。该 SDK 允许您使用元数据标记函数,这些元数据可用于在 Profiles Drilldown 中过滤和分组分析数据。本示例使用静态和动态标记。

首先,让我们看一个静态标记的用例。在 server.py 文件中,找到 Pyroscope 配置

python
 pyroscope.configure(
     application_name = app_name,
     server_address   = server_addr,
     basic_auth_username = basic_auth_username, # for grafana cloud
     basic_auth_password = basic_auth_password, # for grafana cloud
     tags             = {
         "region":   f'{os.getenv("REGION")}',
     }
 )

此标记被视为静态,因为它在应用程序启动时设置且不会更改。在此情况下,它对于按地区分组分析数据很有用,让您可以查看应用程序在每个地区的性能。

  1. 使用以下 URL 打开 Grafana: https://:3000/a/grafana-pyroscope-app/profiles-explorer
  2. 在主菜单中,选择 Explore > Profiles
  3. Exploration 路径中,选择 Labels
  4. Group by labels 部分,选择 region 标签页。

您现在应该会看到应用程序正在运行的地区列表。您可以看到 eu-north 地区正在经历最大负载。

Region Tag
地区标记

接下来,看一个动态标记的用例。在 utils.py 文件中,找到以下函数

python
 def find_nearest_vehicle(n, vehicle):
     with pyroscope.tag_wrapper({ "vehicle": vehicle}):
         i = 0
         start_time = time.time()
         while time.time() - start_time < n:
             i += 1
         if vehicle == "car":
             check_driver_availability(n)

本示例使用 tag_wrapper 按车辆类型标记函数。请注意,此标记是动态的,它会根据车辆类型而变化。这对于按车辆分组分析数据非常有用,使我们能够查看应用程序在不同请求车辆类型下的性能。

使用 Profiles Drilldown 查看此标记如何使用

  1. 使用以下 URL 打开 Profiles Drilldown: https://:3000/a/grafana-pyroscope-app/profiles-explorer
  2. Exploration 路径中选择 Labels
  3. Group by labels 部分,选择 vehicle 标签页。

您现在应该会看到应用程序正在使用的车辆类型列表。您可以看到 car 正在经历最大负载。

识别性能瓶颈

分析应用程序输出的分析数据时,第一步是关注最大的节点,这是应用程序花费最多资源的地方。要发现这一点,您可以使用 Flame graph 视图

  1. 使用以下 URL 打开 Profiles Drilldown: https://:3000/a/grafana-pyroscope-app/profiles-explorer
  2. Exploration 路径中选择 Flame graph
  3. 验证 Service 下拉菜单中选择了 ride-sharing-app,并且 Profile type 下拉菜单中选择了 process_cpu/cpu

它应该看起来像这样

Bottleneck
瓶颈

Flask 的 dispatch_request 函数是与应用程序三个端点对应的三个函数的父级

  • order_bike
  • order_car
  • order_scooter

通过标记 regionvehicle 并查看 Labels 视图,您可以推断

  • /car 端点代码存在问题,其中 car 车辆标记消耗了 68% 的 CPU
  • 我们的某个地区存在问题,其中 eu-north 地区标记消耗了 54% 的 CPU

从火焰图中,您可以看到对于 eu-north 标记,最大的性能影响来自 find_nearest_vehicle() 函数,该函数消耗了接近 68% 的 CPU。要分析这一点,请使用比较下拉菜单直接进入比较页面。

比较两个时间段

Diff flame graph 视图允许您并排比较两个时间段。这对于识别性能随时间的变化非常有用。本示例将 eu-north 地区在给定时间段内的性能与其他地区进行比较。

  1. 使用以下 URL 在 Grafana 中打开 Profiles Drilldown: https://:3000/a/grafana-pyroscope-app/profiles-explorer
  2. Exploration 路径中选择 Diff flame graph
  3. Baseline 中,按 region 过滤并选择 != eu-north
  4. Comparison 中,按 region 过滤并选择 == eu-north
  5. Baseline 中,选择您要比较的时间段。

向下滚动并排比较两个时间段。请注意,eu-north 地区(右侧)显示在 find_nearest_vehicle 函数中花费了过多的时间。这似乎是由一个导致函数阻塞的互斥锁引起的。

Time Comparison
时间比较

本教程中 Pyroscope 如何与 Grafana 集成?

docker-compose.yml 文件包含一个预配置了 Pyroscope 插件的 Grafana 容器

yaml
  grafana:
    image: grafana/grafana:latest
    environment:
    - GF_INSTALL_PLUGINS=grafana-pyroscope-app
    - GF_AUTH_ANONYMOUS_ENABLED=true
    - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
    - GF_AUTH_DISABLE_LOGIN_FORM=true
    volumes:
    - ./grafana-provisioning:/etc/grafana/provisioning
    ports:
    - 3000:3000

Grafana 也预配置了 Pyroscope 数据源。

挑战

作为一项挑战,看看您能否使用 vehicle 标记生成类似的比较。

总结

在本教程中,您学习了如何使用 Pyroscope 对一个简单的“网约车”应用程序进行性能分析。您学习了一些核心的埋点概念,如标记,以及如何使用 Profiles Drilldown 来识别性能瓶颈。

后续步骤