高频面题: 你们线上服务 QPS 多少?你是怎么统计的?

一、什么是QPS?

QPSQueries Per Second 是每秒查询率 ,是 一台服务器 每秒能够相应的查询次数,是对一个特定的查询服务器 在规定时间内 所处理流量多少的衡量标准, 即每秒的响应请求数,也即是最大吞吐能力。

一般来说,QPS 的计算是通过在特定的时间段内,统计系统处理的查询请求总数,然后除以这个时间段的秒数得到。例如,在 1 分钟内系统处理了 6000 个查询请求,那么平均下来 QPS 就是 6000÷60 = 100。用公式表示为:

二、什么是TPS?

TPSTransactions Per Second 通常被定义为每秒事务处理数,是衡量系统处理能力的重要性能指标。

理论计算: 与 QPS 的计算类似,一般是在特定的时间段内,统计系统完成的事务总数,然后除以这个时间段的秒数,就可以得到 TPS 的值。用公式表示为:

例如,在 5 分钟内系统完成了 3000 个事务,那么平均下来 TPS 就是3000/(5*6)=10

实际计算: 在实际应用中,计算 TPS 可能会更加复杂。因为事务的执行时间可能会有很大差异,有些事务可能只需要几毫秒就能完成,而有些事务可能需要几秒甚至更长时间。为了更准确地反映系统的性能,通常会采用一些性能测试工具来模拟实际的业务场景,记录在一段时间内系统处理的事务数量,并根据这些数据计算出 TPS。这些工具会考虑事务的响应时间、并发用户数等因素,以提供更全面、准确的性能评估。

什么是事务?

一个事务是指一个客户机向服务器发送一起完整的 开始 start 请求,内部各种ACID 事务属性的 并发数据操作, 最后 提交一个commit操作结束整个Transaction的过程。

所以从上面可以看出来,一个事务包含明确的三阶段:开始,处理,commit/rollback。

一个事务的中间环节,会包含多个并行的sql的操作。

本质上事务是对 多个并发操作进行数据一致性 的管理,事务的ACID规则如下:

spring框架有本身自带的事务传播性,数据库也有事务,数据库事务包含事务的start,数据操作,事务commit等非常清晰的阶段。当数据库开启事务后,当前线程改变数据库数据,并未提交当前事务,那其他线程读数据库的时候会出现脏读,幻读。

在web服务器领域来说,事务可以指用户的一次完整的交互处理,这次交互处理里边, 包含了多次的服务端api调用。一个web服务器包含包含多次api请求,多次api响应。

三、QPS和TPS的关系

  • 1、 TPS 即每秒处理事务数,从web应用的角度来说,包括了

    • 1)用户通过client工具,开始发起请求
    • 2)client工具执行N个服务端的API调用
    • 3)client进行API结果的聚合再渲染,最后呈现给用户

这三个过程组成一个事务,每秒能够完成N事务,Tps也就是N;

  • 2、 QpsQueries Per Second 是每秒查询率,从web应用的角度来说,就是单次api的调用Qps 基本类似于 Tps,但是不同的是:

    • 用户通过client工具完成一个页面的一次访问,形成一个Tps;
    • 如果一次页面请求,产生多次对服务器的api请求,这个Tps 包含多个 qps。
    • 如果一次页面请求,产生1次对服务器的api请求,这个Tps 包含1个 qps。也就是 tps=qps

四、什么是RT,响应时间

响应时间: 执行一个请求从开始到最后收到响应数据所花费的总体时间。

响应时间(Response Time)是指从系统或设备接收到请求开始,到系统或设备对该请求做出完整响应所经历的时间。它反映了系统处理请求的速度和效率,是衡量系统性能的关键指标之一。这个过程涵盖了从请求的发起、传输、处理到响应返回的整个流程。例如,在网络访问中,当用户在浏览器中输入一个网址并按下回车键后,从用户发出请求的那一刻起,到浏览器完全显示出网页内容为止,所经过的时间就是此次操作的响应时间。

响应时间RT(Response-time),是一个系统最重要的指标之一,它的数值大小直接反应了系统的快慢。单节点QPS公式:QPS=1000ms/RT假设一个节点RT是10ms,则可以很容易的计算出QPS,QPS = 100010 = 100对同一个分布式系统而言,支持的节点数越多,QPS越高。多节点场景,如果把节点提升到2,那么整个系统的QPS则为 2*(1000/10) = 200,可见QPS随着节点横向扩展、节点的增加而线性增长,当然,那QPS上不去就加节点,听起来很有道理,但是往往现实并非如此,为啥:一个请求的处理链路上受影响的环节很多, 不能只解决某一层的吞吐量,而是需要所有的层都要同步提升。

五、什么是并发数?

并发数(并发度):指系统同时能处理的请求数量,同样反应了系统的负载能力。并发数:系统同时处理的request/事务数

并发数 = QPS*平均响应时间

这个是一个理论的并发数。注意,这个并发数,和jemeter的并发数不一样。jmeter中的并发数,就是同时启动的线程数线程组设置为100个线程,运行过程中未出现任何异常,满足100个线程并发操作需求,那么并发数就是100

六、吐吞量

系统的吞吐量(承压能力)与request对CPU的消耗、外部接口、IO等等紧密关联。单个request 对CPU消耗越高,IO速度越慢,那么,系统吞吐能力越低,反之越高。系统吞吐量几个重要参数:QPS(TPS)、并发数、响应时间。

  1. QPS(TPS):(Query Per Second)每秒钟request/事务 数量
  2. 并发数:系统同时处理的request/事务数
  3. 响应时间:一般取平均响应时间

理解了上面三个要素的意义之后,就能推算出它们之间的关系:

QPS(TPS)= 并发数 / 平均响应时间并发数 = QPS * 平均响应时间

七、什么是PV、UV、DAU、MAU

还有一些相关的概念

PV

PV(Page View):即页面浏览量,通常是指网站或应用中某个页面被用户加载和浏览的次数。每一次用户打开或刷新一个页面,PV 值就会增加 1。

一个用户在一天内打开了某个网站的 5 个不同页面,并且在其中一个页面上刷新了 3 次,那么当天该网站的 PV 就是 8。PV 可以直观地反映出网站页面的被访问情况,是衡量网站流量的基础指标之一。

UV

UV(Unique Visitor):即独立访客数,指在一定时间内访问网站或应用的不同用户的数量。通常通过用户的 IP 地址、设备 ID 或其他唯一标识来判断是否为同一个用户,无论该用户在这段时间内访问了多少次网站或应用,都只算作 1 个 UV。

举例:在一天内,有 100 个不同的用户访问了某个网站,其中有 20 个用户访问了多次,那么当天该网站的 UV 就是 100。UV 能够更准确地反映出实际访问网站或应用的用户数量,有助于了解网站或应用的受众规模。

DAU

DAU(Daily Active User):即日活跃用户数,是指在一天内使用过网站或应用的独立用户数量。这里的 “使用” 可以包括打开应用、浏览页面、发送消息等各种操作。DAU 主要用于衡量网站或应用在一天内的活跃用户规模,反映了产品的日常吸引力和用户粘性。

举例:一款手机游戏在某一天有 50 万不同的用户登录并进行了游戏操作,那么当天该游戏的 DAU 就是 50 万。通过分析 DAU 的变化趋势,可以了解产品的用户活跃情况是否稳定,以及新功能或运营活动对用户活跃度的影响,与UV概念相似。

MAU

MAU(Month Active User):即月活跃用户数,是指在一个月内使用过网站或应用的独立用户数量。与 DAU 类似,MAU 是从月度维度来衡量用户活跃度的指标,它能够反映产品在较长时间段内的用户留存和活跃情况。

举例:一个社交应用在某个月内有 1000 万不同的用户至少登录过一次,那么该应用这个月的 MAU 就是 1000 万。MAU 常用于评估产品的长期用户价值和市场占有率,也是投资者和企业管理者关注的重要指标之一。

八、最佳线程数量

刚好消耗完服务器的瓶颈资源的临界线程数,公式如下

最佳线程数量=((线程等待时间+线程cpu时间)/线程cpu时间)* cpu数量

在尼恩《 Java高并发核心编程 卷2 加强版》一书中,对以上公式进行了细致的介绍。无论io密集型线程池、cpu密集型线程池,都满足上面的公式。

特性:

  • 在达到最佳线程数的时候,线程数量继续递增,则QPS不变,而响应时间变长,持续递增线程数量,则QPS开始下降。
  • 每个系统都有其最佳线程数量,但是不同状态下,最佳线程数量是会变化的。
  • 瓶颈资源可以是CPU,可以是内存,可以是锁资源,IO资源:超过最佳线程数-导致资源的竞争,超过最佳线程数-响应时间递增。

九、吞吐量 评估

比较关键的关键的问题来了:

假设你的项目的用户量有百万级,然后每天有几千万请求,高峰期每秒有好几千请求。每个服务会有多高的QPS?

那么这个时候,你的服务会有多高的QPS?按二八定律来看,如果每天 80% 的访问集中在 20% 的时间里,这 20% 时间就叫做峰值时间。

  • 公式:( 总PV数 * 80% ) / ( 每天秒数 * 20% ) = 峰值时间每秒请求数(QPS)
  • 机器:峰值时间每秒QPS / 单台机器的QPS = 需要的机器

1、每天300w PV 的在单台机器上,这台机器需要多少QPS?( 3000000 * 0.8 ) / (86400 * 0.2 ) = 139 (QPS)2、如果一台机器的QPS是58,需要几台机器来支持? 139 / 58 = 3

十、 你们线上QPS 多少,你是怎么知道的?

为什么需要监控 QPS? QPS 是衡量后端服务性能的关键指标,可以帮助你及时发现性能瓶颈和问题。

QPS 是直观反映系统处理能力的关键指标。通过监控 QPS,能清晰了解系统在单位时间内可处理的查询请求数量,从而判断系统性能的高低。如在电商大促期间,监控订单系统的 QPS,可明确系统能否应对高并发下单请求。

持续监控 QPS 有助于发现系统性能的变化趋势。若 QPS 持续下降,可能意味着系统出现性能瓶颈或故障,需及时优化;若 QPS 稳步上升,说明系统性能优化措施有效或业务增长良好。

Prometheus 是什么? Prometheus 是一个开源监控框架,用于收集和存储时序数据,例如度量标准和日志。

如何配置 Prometheus 监控后端服务? 在springboot 应用中完成指标 my_app_requests_total 的暴露,在 prometheus.yml 配置文件中指定要监控的指标。

Grafana 是什么? Grafana 是一个开源的可视化工具,用于创建和共享交互式仪表盘,展示 Prometheus 等监控系统收集的数据。

如何可视化 QPS 数据? 在 Grafana 中创建一个仪表盘,添加一个图形面板,显示 my_app_requests_total{method=“GET”} 度量标准。

从0到1 实现线上 QPS的监控 的核心流程

SpringBoot添加actuator和prometheus依赖,然后使用 actuator暴露prometheus 端点;SpringBoot中配置prometheus数据采集Bean,实现端点数据的url 暴露服务。

Prometheus启动文件中添加监控的后台服务信息,如数据采集间隔、服务IP:PROT等;进行指标数据的拉取和时序数据的打标。

Grafana配置:使用 Metrics browser配置监控的指标:包括uri、outcome等等;完成 Transform配置数据转换:最后进行Labels to fields配置图例名称的配置。

1. 配置 Spring Boot 项目

SpringBoot添加actuator和prometheus依赖,然后使用 actuator暴露prometheus 端点;SpringBoot中配置prometheus数据采集Bean,实现端点数据的url 暴露服务。

添加依赖在 pom.xml 文件中添加 Spring Boot Actuator 和 Prometheus 依赖:

<dependencies>
    <!-- Spring Boot Actuator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator</artifactId>
    </dependency>
    <!-- Micrometer Prometheus Registry -->
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-registry-prometheus</artifactId>
    </dependency>
</dependencies>

配置 Actuator 暴露的端点

application.propertiesapplication.yml 中配置 Actuator 暴露的端点

# 暴露所有 Actuator 端点
management.endpoints.web.exposure.include=*
# 暴露 Prometheus 端点
management.endpoints.web.exposure.include=prometheus

management.metrics.web.server.request.metric-name = http.server.requests

配置 Prometheus 数据采集 Bean

创建一个配置类,配置 Prometheus 数据采集 Bean:

@SpringBootApplication
@ServletComponentScan
public class OneApplication {

    public static void main(String[] args) {
        SpringApplication.run(OneApplication.class, args);
    }

    // 非常重要
    @Bean
    MeterRegistryCustomizer<MeterRegistry> configurer(
            @Value("${spring.application.name}") String applicationName) {
        return (registry) -> registry.config().commonTags("application", "spring-boot-app");
    }
}

这个应用程序可能是一个 Web 服务,使用 Spring Boot 框架开发,并且可能集成了一些监控功能,如使用 Micrometer 进行指标监控。MeterRegistry 是 Micrometer 库中的核心组件,用于收集和管理指标,例如记录请求计数、请求时长、内存使用等, 这个是非入侵的。通过这个 configurer Bean,我们为所有的指标添加了一个通用的标签,使得在监控系统中查看指标时,可以清晰地知道这些指标来自哪个应用程序。

启动springboot项目后,查看输出的指标

http://localhost:8080/actuator/prometheus参考如下:

# HELP http_server_requests_seconds
# TYPE http_server_requests_seconds summary
# http_server_requests_seconds_count 表示请求次数3次
http_server_requests_seconds_count{application="hello",exception="None",method="POST",outcome="SUCCESS",status="200",uri="/prometheus/post/{id}",} 3.0
# http_server_requests_seconds_sum 表示3次请求总响应时长是 3.021s
http_server_requests_seconds_sum{application="hello",exception="None",method="POST",outcome="SUCCESS",status="200",uri="/prometheus/post/{id}",} 3.0210991
http_server_requests_seconds_count{application="hello",exception="None",method="GET",outcome="SUCCESS",status="200",uri="/actuator/prometheus",} 110.0
http_server_requests_seconds_sum{application="hello",exception="None",method="GET",outcome="SUCCESS",status="200",uri="/actuator/prometheus",} 3.8388842
# HELP 是对这个指标的描述
# HELP http_server_requests_seconds_max
# 这个指标类型
# TYPE http_server_requests_seconds_max gauge
# http_server_requests_seconds_max 表示所有请求中,最长响应时间的一次是 2.00s
http_server_requests_seconds_max{application="hello",exception="None",method="POST",outcome="SUCCESS",status="200",uri="/prometheus/post/{id}",} 2.0021618
http_server_requests_seconds_max{application="hello",exception="None",method="GET",outcome="SUCCESS",status="200",uri="/actuator/prometheus",} 0.0345458

数据统计标识:

序号 标识 描述
1 http_server_requests_seconds_count 请求量
2 http_server_requests_seconds_sum 请求总耗时
3 http_server_requests_seconds_max 请求最大耗时

指标的最后的部分是类型, 主要的类型有:Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要)一般 需要的 常规 指标 数据, 都可以通过上面的指标统计出来的。

1. 当前在线总数, 折线图, 时间线和人数
2. 吞吐量 - 每个时间点处理的请求数 - 折线图
3. 接口响应时长 - 每个接口的响应时长,横坐标是时间线,折线图
4. 错误分布 - 状态码各个请求分布

具体,请参见配套视频《第47章:工业级底座:基于GPA 实现 Springcloud 底座的 工业级 监控治理》

2. 配置 Prometheus

2.1 下载并启动 Prometheus

从 Prometheus 官网下载相应版本的 Prometheus,并解压。

2.2 配置 Prometheus 启动文件 prometheus.yml

prometheus.yml 中添加以下内容:

global:
  scrape_interval: 15s  # 采集间隔
scrape_configs:
  - job_name: 'prometheus'
    metrics_path: '/actuator/prometheus'  # 从 Spring Boot Actuator 的 Prometheus 端点采集数据
    static_configs:
      - targets: ['localhost:9090']  # 替换为你的服务 IP 和端口

解释

  • scrape_interval 定义了 Prometheus 从目标拉取数据的时间间隔,这里是 15 秒。
  • job_name 是监控任务的名称,这里叫 prometheus。
  • metrics_path 是 Prometheus 采集数据的路径,这里指向 Spring Boot Actuator 的 Prometheus 端点。
  • targets 是要监控的服务地址。

3. 启动 Prometheus

在 Prometheus 的根目录下运行:

./prometheus --config.file=prometheus.yml

4. 配置 Grafana

4.1 下载并启动 Grafana

从 Grafana 官网下载并启动 Grafana。

4.2 配置数据源

打开 Grafana 页面,登录后添加 Prometheus 作为数据源。在 Configuration -> Data Sources 中添加一个新的数据源,选择 Prometheus,并输入 Prometheus 的 URL(默认是 http://localhost:9090)。

4.3 配置指标

Create -> Dashboard -> Add Query 中,使用 PromQL 表达式进行指标查询。例如,使用 下面的公式统计qps

rate(http_server_requests_seconds_count{uri="/api/v1/prometheus/test"}[5m])

上面是一个 PromQL表达式,PromQL (Prometheus Query Language)是 Prometheus 的查询语言,用于从 Prometheus 的时间序列数据库中检索和操作数据。

它可以用来计算和聚合指标数据,以生成有用的统计信息,例如计算速率、总和、平均值等。http_server_requests_seconds_count 这是一个指标名称,通常是在使用 Spring Boot Actuator 与 Micrometer 集成时,用于统计 HTTP 服务器请求的数量。

这个指标会记录每个请求的计数,根据不同的标签(如 uri)进行区分。{uri="/api/v1/prometheus/test"} 这是一个标签选择器,用于筛选出 http_server_requests_seconds_count 指标中 uri 标签等于 /api/v1/prometheus/test 的时间序列数据。通过使用标签选择器,可以将指标数据进行分类和筛选,以便你只关注特定的请求或服务。[5m] 这表示时间范围,这里是 5 分钟。这个时间范围用于指定 rate 函数的计算窗口。rate() 函数用于计算时间序列在给定时间范围内的每秒平均增长率。具体计算步骤如下:

  • 它首先查看在指定的 5 分钟( [5m])时间窗口内的 http_server_requests_seconds_count 指标数据。
  • 然后计算该指标,在这个时间窗口内的每秒平均增长率。对于 http_server_requests_seconds_count 指标,这可以看作是在过去 5 分钟内每秒请求的平均增长率。

5. 查看和分析 QPS

在 Grafana 中创建一个面板,将 QPS 指标添加到面板中,使用上述 PromQL 表达式进行绘制。你可以查看 QPS 的实时趋势、历史趋势,以及不同时间范围的 QPS 数据。

6. 优化和调整

根据 QPS 监控结果,你可以调整 Spring Boot 应用程序的性能,如添加缓存、优化数据库查询、增加服务器等。调整 Prometheus 的采集间隔和配置,以获取更精确的数据。进一步优化 Grafana 面板,添加告警规则等。具体实操,请参见视频《第47章:工业级底座:基于GPA 实现 Springcloud 底座的 工业级 监控治理》