乐趣区

关于c#:5-堪比JMeter的Net压测工具-Crank-实战篇-接口以及场景压测

1. 前言

通过之前的学习,咱们曾经把握了 crank 的配置以及对应 http 基准工具 bombardier、wrk、wrk2 的用法,本篇文章介绍一下如何将其用于实战,在理论的我的项目中咱们如何应用 crank 来实现压测工作。

2. 我的项目背景

目前有一个我的项目,咱们心愿通过压测来理解其 QPS、吞吐量、以及临界值,并通过压测来剖析出其瓶颈在哪里?并通过解决瓶颈问题以进步 QPS、吞吐量等指标

先看下咱们手头把握了什么:

  • 我的项目信息

    • 我的项目中的接口根本都须要登录
    • 通过与开发沟通能够失去每个页面的接口信息以及参数信息
  • 环境信息

    • 压测我的项目有独自的环境部署利用、Redis、数据库等根底配置

此处我的项目名咱们暂定为 ProjectA。

3. 如何发展

首先咱们先回顾一下 Agent、Controller 的职责以及特点

  • Controller

    • 做任务调度以及后果输入
    • 无需独自服务器,能够在本机执行发送命令,须要与 Agent 相通
  • Agent

    • 工作的理论执行者
    • 单任务执行,不能做到接管到多个工作并同时执行,先收到哪个工作,哪个工作会先执行
    • 雷同一个工作能够被多个 Agent 同时执行,最终指标后果会主动累加,能够通过晋升 Agent 来模仿更高的并发能力

3.1. 思路

  • 先做好独自接口的压测,大略把握每个接口的指标状况
  • 同时压测多个接口,实现对场景的压测
  • 通过压测察看应用服务器、根底服务器的 CPU、带宽、内存等指标,察看 Redis、数据库、音讯队列等根底组件状况,依据压测的返回后果失去每个场景的根底指标
  • 通过剖析发现瓶颈、而后再思考如何冲破瓶颈,晋升 QPS、吞吐量等

3.2. 如何做?

理解到单个 Agent 同时执行多个工作会进行排队,无奈做到多任务同时执行,那么咱们能够通过多个 Agent 同时执行不同的工作来模仿用户拜访页面。

3.2.1. 构建 Agent

之前与开发沟通失去每个页面最多可发送的申请是 6 个,那么咱们筹备 6 个 Agent,别离为 Agent1、Agent2、Agent3、Agent4、Agent5、Agent6

咱们这里应用 Docker 来启动 Agent、Agent 对内凋谢端口: 5010、对外端口随机,镜像应用咱们自建的: doddgu/crankagent:net5.0

并新建 load.yml 为之后压测应用:

profiles:
  crankAgent1:
    jobs:
      load:
        endpoints:
          - http://localhost:5010
  crankAgent2:
    jobs:
      load:
        endpoints:
          - http://localhost:5011
  crankAgent3:
    jobs:
      load:
        endpoints:
          - http://localhost:5012
  crankAgent4:
    jobs:
      load:
        endpoints:
          - http://localhost:5013
  crankAgent5:
    jobs:
      load:
        endpoints:
          - http://localhost:5014
  crankAgent6:
    jobs:
      load:
        endpoints:
          - http://localhost:5015

load.yml 中记录了所有的压测机信息,其信息个别不做批改,咱们能够作为公共的配置来应用无需每个我的项目都独自保护一份新的

3.2.2. 构建压测脚本

在这里咱们抉择 wrk2 作为本次基准测试工具,抉择 wrk2 的起因是:

  • 反对随机参数
  • 可反对设置恒定的吞吐量负载
  • 具备 wrk 的所有性能

此时咱们针对 ProjectA 我的项目新建配置:project.profiles.yml,作为本次压测的环境配置来应用,其配置如下

imports:
  - https://raw.githubusercontent.com/doddgu/crank/sample/samples/wrk2/common/load.profiles.yml # 这边倡议应用近程 load.profiles.yml 地址。(如果输出的是本地门路、则需输出与以后命令所在门路的相对路径)

profiles:

  local: # 本地环境
    variables:
      serverAddress: localhost # 应用服务域
      serverPort: 80 # 应用服务端口
      connections: 256 # 每个线程解决时放弃关上的 HTTP 连贯总数 N = 连接数 / 线程数
      threads: 32 # 线程数
      warmup: 3 # 预热工夫: 3s
      duration: 180 # 测试时长: 3 分钟
      rate:  # 吞吐量参数(每秒总申请数)

project.profiles.yml 中记录了指定我的项目的各环境的配置,我的项目本人独立保护即可

除了我的项目信息、压测机配置之外,咱们还须要有中央保护咱们压测的接口信息,这边我的做法是将 api 独立拆分进去,每个 yml 只配置一个接口的压测信息,至于为什么不放到一块,而要独自拆离开呢?

这块思考到咱们压测的最小单元是 API 接口,如果把 API 接口独立拆离开,那么能够对单接口压测,而如果咱们须要场景压测,也能够通过组合接口实现多接口同时压测,并且一旦咱们实现了某个接口的压测编写,后续不须要再改变这个配置,如果咱们依照场景拆分成不同的 yml,在 yml 中再依据定义不同的 scenario 来做,那么后续场景新减少接口,还须要再更改这个场景的 yml,并且 scenario 中的场景实际上也是依据接口维度辨别的,目前 crank 并不能实现单个场景工作同时解决,基于以上起因,这边咱们新调整好的配置格局为:

新增 load.benchmarks.yml

imports:
  - https://raw.githubusercontent.com/doddgu/crank/sample/src/Microsoft.Crank.Jobs.Wrk2/wrk2.yml
  - https://raw.githubusercontent.com/doddgu/crank/sample/samples/wrk2/common/project.profiles.yml

jobs:
  server:
    source:
      repository: https://github.com/doddgu/crank
      branchOrCommit: sample
      project: samples/hello/hello.csproj
    readyStateText: Application started.

scenarios:
  api:
    application: # 理论压测我的项目时可移除此节点,此处是为模仿应用服务启动
      job: server
      variables:
        duration: 1
    load:
      job: wrk2
      variables:
        serverPath: /user/get
        script: request.lua
        duration: 1

profiles:
  defaultParamLocal: # 本地环境的参数信息
    variables: 
      serverQueryString: ?id={1}
      serverQueryParameter: 1||2 # 随机申请 /get?id=1、/get?id=2

依照此格局保留,后续新增接口也能够疾速复制,简略批改即可疾速实现压测工作的编写,这样一来,如果咱们心愿对 localhost:5000/user/get 这个接口做压测,仅须要在 crank 管制端输出:

crank --config load.benchmarks.yml --scenario api --load.framework net5.0 --application.framework net5.0 --profile local --profile crankAgent1 --description "获取用户详情" --profile defaultParamLocal

3.2.3. 构建批处理命令

但作为一个开发人员,总是心愿事件能更简略一点,每次输出命令太麻烦了,所以就想到了通过批处理疾速实现工作的发送,最终的我的项目构造就变成了

benchmarks
├─ defaultTitle              接口名称 (Description)
└─ load.bat                  最终执行的脚本,其中指定了要指定的 yml 配置、场景、以及工作环境是.net 5.0
└─ load.benchmarks.yml       yml 配置
└─ load.local.bat            测试本地环境时要执行的脚本、格局:load.{环境}.bat
└─ README.md                 帮忙文档 

每次通过双击 load.{环境}.bat 就实现了对以后接口的压力测试,而后就是期待后果输入……

| application           |                |
| --------------------- | -------------- |
| CPU Usage (%)         | 1              |
| Cores usage (%)       | 10             |
| Working Set (MB)      | 85             |
| Private Memory (MB)   | 278            |
| Build Time (ms)       | 3,469          |
| Start Time (ms)       | 352            |
| Published Size (KB)   | 93,323         |
| .NET Core SDK Version | 5.0.404        |
| ASP.NET Core Version  | 5.0.13+55738ff |
| .NET Runtime Version  | 5.0.13+b3afe99 |


| load                  |                |
| --------------------- | -------------- |
| Build Time (ms)       | 3,281          |
| Start Time (ms)       | 0              |
| Published Size (KB)   | 74,276         |
| .NET Core SDK Version | 5.0.404        |
| ASP.NET Core Version  | 5.0.13+55738ff |
| .NET Runtime Version  | 5.0.13+b3afe99 |
| First Request (ms)    | 86             |
| Requests/sec          | 2              |
| Requests              | 2              |
| Mean latency (ms)     | 2.68           |
| Max latency (ms)      | 2.68           |
| Bad responses         | 0              |
| Socket errors         | 0              |
| Latency 50th (ms)     | 2.68           |
| Latency 75th (ms)     | 2.68           |
| Latency 90th (ms)     | 2.68           |
| Latency 99th (ms)     | 2.68           |
| Latency 99.9th (ms)   | 2.68           |
| Latency 99.99th (ms)  | 2.68           |
| Latency 99.999th (ms) | 2.68           |

3.2.4. 构建场景压测批处理命令

通过下面的一番操作,咱们曾经能够很容易的对单接口进行压测,但目前想模仿实现多接口同时压测,还须要再革新一下,之前咱们想到,crank 目前只能实现独自压测工作,那是不是有多个 Agent,每个 Agent 独自压测一个接口,并同时启动多个 Agent 同时压测是不是能够模仿进去场景压测,那我通过批处理工作多点几次不同的接口压测不就能够了,基于以上思考,又做了一个批处理脚本,用于调用多个接口的压测工作启动,最初的构造如下所示:

Crank
├─ benchmarks                压测脚本
│  ├─ api                   接口压测脚本               
│  │  ├─ add               
│  │  └─ get                  
│  ├─ scipts               lua 脚本             
│  │  ├─ common            lua 公共脚本
│  │  │  ├─ oauth.lua     认证 lua 脚本
│  │  │  ├─ util.lua      lua 工具类脚本
│  │  ├─ request.lua       封装申请 lua 脚本   
│  ├─ scripts.tar           lua 脚本压缩包
├─ common                            
│  ├─ load.profiles.yml     agent 负载机配置
│  ├─ project.profiles.yml  我的项目配置
│  ├─ scripts.profiles      crank 执行 script 配置,用于对输入后果的二次解决
│  ├─ project.profiles.yml  我的项目配置
├─ scripts                   场景压测脚本
│  ├─ 用户.bat              用户压测     
└─ env                       环境配置,标记以后须要压测的环境在哪个配置文件中存储
└─ env.local                 本地环境,存储本地环境的配置信息
└─ README.md                 帮忙文档 

4. 结尾

通过下面的操作咱们曾经实现了对单接口以及单场景的压测,通过控制台能够清晰的看到每个接口的压测后果,咱们只须要急躁期待压测工作完结,并整顿压测后果数据,最初进行汇总咱们的工作就实现了,但压测后果的收集也是一个麻烦费劲的工作,作为一个开发,是不想把工夫破费到这些整顿表格的事件上,那咱们如何做能够把整顿表格数据的工作节省下来让咱们能够歇会儿呢……

源码地址:https://github.com/doddgu/cra…

参考链接:

  • https://www.cnblogs.com/xinzh…

开源地址

MASA.BuildingBlocks:https://github.com/masastack/…

MASA.Contrib:https://github.com/masastack/…

MASA.Utils:https://github.com/masastack/…

MASA.EShop:https://github.com/masalabs/M…

MASA.Blazor:https://github.com/BlazorComp…

如果你对咱们的 MASA Framework 感兴趣,无论是代码奉献、应用、提 Issue,欢送分割咱们

退出移动版