diff --git a/docs/content.zh/docs/getting-started/benchmark.md b/docs/content.zh/docs/getting-started/benchmark.md deleted file mode 100644 index e41f4a7..0000000 --- a/docs/content.zh/docs/getting-started/benchmark.md +++ /dev/null @@ -1,693 +0,0 @@ ---- -weight: 50 -title: "性能测试" ---- - -# 性能测试 - -INFINI Loadgen 是一款专为 Easysearch、Elasticsearch、OpenSearch 设计的轻量级性能测试工具。 - -Loadgen 的特点: - -- 性能强劲 -- 轻量级无依赖 -- 支持模板化参数随机 -- 支持高并发 -- 支持压测端均衡流量控制 -- 支持服务端返回值校验 - -> 下载地址: - -如果你希望直接参考仓库内的实战样例(压测、变量、JSON 断言、语料驱动等),请继续阅读: - -- [使用场景与实战示例]({{< relref "/docs/getting-started/use-cases" >}}) - -## Loadgen - -Loadgen 使用非常简单,下载解压之后会得到三个文件,一个可执行程序、一个配置文件 `loadgen.yml` 以及用于运行测试的 `loadgen.dsl`,配置文件样例如下: - -```yaml -env: - ES_USERNAME: elastic - ES_PASSWORD: elastic - ES_ENDPOINT: http://localhost:8000 -``` - -测试文件样例如下: - -```text -# runner: { -# // total_rounds: 1 -# no_warm: false, -# // Whether to log all requests -# log_requests: false, -# // Whether to log all requests with the specified response status -# log_status_codes: [0, 500], -# assert_invalid: false, -# assert_error: false, -# }, -# variables: [ -# { -# name: "ip", -# type: "file", -# path: "dict/ip.txt", -# // Replace special characters in the value -# replace: { -# '"': '\\"', -# '\\': '\\\\', -# }, -# }, -# { -# name: "id", -# type: "sequence", -# }, -# { -# name: "id64", -# type: "sequence64", -# }, -# { -# name: "uuid", -# type: "uuid", -# }, -# { -# name: "now_local", -# type: "now_local", -# }, -# { -# name: "now_utc", -# type: "now_utc", -# }, -# { -# name: "now_utc_lite", -# type: "now_utc_lite", -# }, -# { -# name: "now_unix", -# type: "now_unix", -# }, -# { -# name: "now_with_format", -# type: "now_with_format", -# // https://programming.guide/go/format-parse-string-time-date-example.html -# format: "2006-01-02T15:04:05-0700", -# }, -# { -# name: "suffix", -# type: "range", -# from: 10, -# to: 1000, -# }, -# { -# name: "bool", -# type: "range", -# from: 0, -# to: 1, -# }, -# { -# name: "list", -# type: "list", -# data: ["medcl", "abc", "efg", "xyz"], -# }, -# { -# name: "id_list", -# type: "random_array", -# variable_type: "number", // number/string -# variable_key: "suffix", // variable key to get array items -# square_bracket: false, -# size: 10, // how many items for array -# }, -# { -# name: "str_list", -# type: "random_array", -# variable_type: "number", // number/string -# variable_key: "suffix", // variable key to get array items -# square_bracket: true, -# size: 10, // how many items for array -# replace: { -# // Use ' instead of " for string quotes -# '"': "'", -# // Use {} instead of [] as array brackets -# "[": "{", -# "]": "}", -# }, -# }, -# ], - -POST $[[env.ES_ENDPOINT]]/medcl/_search -{ "track_total_hits": true, "size": 0, "query": { "terms": { "patent_id": [ $[[id_list]] ] } } } -# request: { -# runtime_variables: {batch_no: "uuid"}, -# runtime_body_line_variables: {routing_no: "uuid"}, -# basic_auth: { -# username: "$[[env.ES_USERNAME]]", -# password: "$[[env.ES_PASSWORD]]", -# }, -# }, -``` - -### 运行模式设置 - -默认配置下,Loadgen 会以性能测试模式运行,在指定时间(`-d`)内重复执行 `requests` 里的所有请求。如果只需要检查一次测试结果,可以通过 `runner.total_rounds` 来设置 `requests` 的执行次数。 - -### CLI 参数清单(常用) - -```bash -loadgen -run loadgen.dsl -config loadgen.yml -d 60 -c 100 -r 1000 -l 50000 -timeout 60 -compress -``` - -常用命令参数: - -- `-run` -- `-config` -- `-d` -- `-c` -- `-r` -- `-l` -- `-compress` -- `-timeout` -- `-dial-timeout` -- `-read-timeout` -- `-write-timeout` -- `-cpu` -- `-mem` -- `-log` -- `-debug` - -使用建议: - -- 第一步先用 `runner.total_rounds: 1` 验证逻辑和断言 -- 第二步再开启时长与并发参数压测 -- 第三步固定 QPS 或总请求量做可对比基线 - -### HTTP 响应头处理 - -默认配置下,Loadgen 会自动格式化 HTTP 的响应头(`user-agent: xxx` -> `User-Agent: xxx`),如果需要精确判断服务器返回的响应头,可以通过 `runner.disable_header_names_normalizing` 来禁用这个行为。 - -## 变量的使用 - -上面的配置中,`variables` 用来定义变量参数,根据 `name` 来设置变量标识,在构造请求的使用 `$[[变量名]]` 即可访问该变量的值,变量目前支持的类型有: - -| 类型 | 说明 | 变量参数 | -| ----------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `file` | 文件型外部变量参数 | `path`: 数据文件路径
`data`: 数据列表,会被附加到`path`文件内容后读取 | -| `list` | 自定义枚举变量参数 | `data`: 字符数组类型的枚举数据列表 | -| `sequence` | 32 位自增数字类型的变量 | `from`: 初始值
`to`: 最大值 | -| `sequence64` | 64 位自增数字类型的变量 | `from`: 初始值
`to`: 最大值 | -| `range` | 数字范围类型的变量,支持参数 `from` 和 `to` 来限制范围 | `from`: 初始值
`to`: 最大值 | -| `random_array` | 生成一个随机数组,数据元素来自`variable_key`指定的变量 | `variable_key`: 数据源变量
`size`: 输出数组的长度
`square_bracket`: `true/false`,输出值是否需要`[`和`]`
`string_bracket`: 字符串,输出元素前后会附加指定的字符串 | -| `uuid` | UUID 字符类型的变量 | | -| `now_local` | 当前时间、本地时区 | | -| `now_utc` | 当前时间、UTC 时区。输出格式:`2006-01-02 15:04:05.999999999 -0700 MST` | | -| `now_utc_lite` | 当前时间、UTC 时区。输出格式:`2006-01-02T15:04:05.000` | | -| `now_unix` | 当前时间、Unix 时间戳 | | -| `now_with_format` | 当前时间,支持自定义 `format` 参数来格式化时间字符串,如:`2006-01-02T15:04:05-0700` | `format`: 输出的时间格式 ([示例](https://www.geeksforgeeks.org/time-formatting-in-golang/)) | - -### 变量使用示例 - -`file` 类型变量参数加载自外部文本文件,每行一个变量参数,访问该变量时每次随机取其中一个,变量里面的定义格式举例如下: - -```text -# test/user.txt -medcl -elastic -``` - -附生成固定长度的随机字符串,如 1024 个字符每行: - -```bash -LC_CTYPE=C tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+= < /dev/random | head -c 1024 >> 1k.txt -``` - -### 环境变量 - -Loadgen 支持自动读取环境变量,环境变量可以在运行 Loadgen 时通过命令行传入,也可以在 `loadgen.dsl` 里指定默认的环境变量值,Loadgen 运行时会使用命令行传入的环境变量覆盖 `loadgen.dsl` 里的默认值。 - -配置的环境变量可以通过 `$[[env.环境变量]]` 来使用: - -```text -#// 配置环境变量默认值 -# env: { -# ES_USERNAME: "elastic", -# ES_PASSWORD: "elastic", -# ES_ENDPOINT: "http://localhost:8000", -# }, - -#// 使用运行时变量 -GET $[[env.ES_ENDPOINT]]/medcl/_search -{"query": {"match": {"name": "$[[user]]"}}} -# request: { -# // 使用运行时变量 -# basic_auth: { -# username: "$[[env.ES_USERNAME]]", -# password: "$[[env.ES_PASSWORD]]", -# }, -# }, -``` - -## 请求的定义 - -配置节点 `requests` 用来设置 Loadgen 将依次执行的请求,支持固定参数的请求,也可支持模板变量参数化构造请求,以下是一个普通的查询请求: - -```text -GET http://localhost:8000/medcl/_search?q=name:$[[user]] -# request: { -# username: elastic, -# password: pass, -# }, -``` - -上面的查询对 `medcl` 索引进行了查询,并对 `name` 字段执行一个查询,每次请求的值来自随机变量 `user`。 - -### 模拟批量写入 - -使用 Loadgen 来模拟 bulk 批量写入也非常简单,在请求体里面配置一条索引操作,然后使用 `body_repeat_times` 参数来随机参数化复制若干条请求即可完成一批请求的准备,如下: - -```text -POST http://localhost:8000/_bulk -{"index": {"_index": "medcl-y4", "_type": "doc", "_id": "$[[uuid]]"}} -{"id": "$[[id]]", "field1": "$[[user]]", "ip": "$[[ip]]", "now_local": "$[[now_local]]", "now_unix": "$[[now_unix]]"} -# request: { -# basic_auth: { -# username: "test", -# password: "testtest", -# }, -# body_repeat_times: 1000, -# }, -``` - -### 返回值判断 - -每个 `requests` 配置可以通过 `assert` 来设置是否需要检查返回值。`assert` 功能支持 INFINI Gateway 的大部分[条件判断功能](https://infinilabs.cn/docs/latest/gateway/references/flow/#条件类型)。 - -> 请阅读[《借助 DSL 来简化 Loadgen 配置》](https://infinilabs.cn/blog/2023/simplify-loadgen-config-with-dsl/)来了解更多细节。 - -```text -GET http://localhost:8000/medcl/_search?q=name:$[[user]] -# request: { -# basic_auth: { -# username: "test", -# password: "testtest", -# }, -# }, -# assert: { -# _ctx.response.status: 201, -# }, -``` - -请求返回值可以通过 `_ctx` 获取,`_ctx` 目前包含以下信息: - -| 参数 | 说明 | -| ------------------------- | --------------------------------------------------------------------------------------- | -| `_ctx.response.status` | HTTP 返回状态码 | -| `_ctx.response.header` | HTTP 返回响应头 | -| `_ctx.response.body` | HTTP 返回响应体 | -| `_ctx.response.body_json` | 如果 HTTP 返回响应体是一个有效的 JSON 字符串,可以通过 `body_json` 来访问 JSON 内容字段 | -| `_ctx.elapsed` | 当前请求发送到返回消耗的时间(毫秒) | - -如果请求失败(请求地址无法访问等),Loadgen 无法获取 HTTP 请求返回值,Loadgen 会在输出日志里记录 `Number of Errors`。如果配置了 `runner.assert_error` 且存在请求失败的请求,Loadgen 会返回 `exit(2)` 错误码。 - -如果返回值不符合判断条件,Loadgen 会停止执行当前轮次后续请求,并在输出日志里记录 `Number of Invalid`。如果配置了 `runner.assert_invalid` 且存在判断失败的请求,Loadgen 会返回 `exit(1)` 错误码。 - -### 动态变量注册 - -每个 `requests` 配置可以通过 `register` 来动态添加运行时参数,一个常见的使用场景是根据前序请求的返回值来动态设置后序请求的参数。 - -这个示例调用 `$[[env.ES_ENDPOINT]]/test` 接口获取索引的 UUID,并注册到 `index_id` 变量。后续的请求定义可以通过 `$[[index_id]]` 来获取这个值。 - -```text -GET $[[env.ES_ENDPOINT]]/test -# register: [ -# {index_id: "_ctx.response.body_json.test.settings.index.uuid"}, -# ], -# assert: (200, {}), -``` - -## 执行压测 - -执行 Loadgen 程序即可执行压测,如下: - -```text -$ loadgen -d 30 -c 100 -compress -run loadgen.dsl - __ ___ _ ___ ___ __ __ - / / /___\/_\ / \/ _ \ /__\/\ \ \ - / / // ///_\\ / /\ / /_\//_\ / \/ / -/ /__/ \_// _ \/ /_// /_\\//__/ /\ / -\____|___/\_/ \_/___,'\____/\__/\_\ \/ - -[LOADGEN] A http load generator and testing suit. -[LOADGEN] 1.0.0_SNAPSHOT, 83f2cb9, Sun Jul 4 13:52:42 2021 +0800, medcl, support single item in dict files -[07-19 16:15:00] [INF] [instance.go:24] workspace: data/loadgen/nodes/0 -[07-19 16:15:00] [INF] [loader.go:312] warmup started -[07-19 16:15:00] [INF] [app.go:306] loadgen now started. -[07-19 16:15:00] [INF] [loader.go:316] [GET] http://localhost:8000/medcl/_search -[07-19 16:15:00] [INF] [loader.go:317] status: 200,,{"took":1,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":0,"relation":"eq"},"max_score":null,"hits":[]}} -[07-19 16:15:00] [INF] [loader.go:316] [GET] http://localhost:8000/medcl/_search?q=name:medcl -[07-19 16:15:00] [INF] [loader.go:317] status: 200,,{"took":1,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":0,"relation":"eq"},"max_score":null,"hits":[]}} -[07-19 16:15:01] [INF] [loader.go:316] [POST] http://localhost:8000/_bulk -[07-19 16:15:01] [INF] [loader.go:317] status: 200,,{"took":120,"errors":false,"items":[{"index":{"_index":"medcl-y4","_type":"doc","_id":"c3qj9123r0okahraiej0","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":5735852,"_primary_term":3,"status":201}}]} -[07-19 16:15:01] [INF] [loader.go:325] warmup finished - -5253 requests in 32.756483336s, 524.61KB sent, 2.49MB received - -[Loadgen Client Metrics] -Requests/sec: 175.10 -Request Traffic/sec: 17.49KB -Total Transfer/sec: 102.34KB -Avg Req Time: 5.711022ms -Fastest Request: 440.448µs -Slowest Request: 3.624302658s -Number of Errors: 0 -Number of Invalid: 0 -Status 200: 5253 - -[Estimated Server Metrics] -Requests/sec: 160.37 -Transfer/sec: 93.73KB -Avg Req Time: 623.576686ms -``` - -Loadgen 在正式压测之前会将所有的请求执行一次来进行预热,如果出现错误会提示是否继续,预热的请求结果也会输出到终端,执行完成之后会输出执行的摘要信息。可以通过设置 `runner.no_warm` 来跳过这个检查阶段。 - -> 因为 Loadgen 最后的结果是所有请求全部执行完成之后的累计统计,可能存在不准的问题,建议通过打开 Kibana 的监控仪表板来实时查看 Elasticsearch 的各项运行指标。 - -### 命令行参数 - -Loadgen 会循环执行配置文件里面定义的请求,默认 Loadgen 只会运行 `5s` 就自动退出了,如果希望延长运行时间或者加大并发可以通过启动的时候设置参数来控制,通过查看帮助命令如下: - -```text -$ loadgen -help -Usage of loadgen: - -c int - Number of concurrent threads (default 1) - -compress - Compress requests with gzip - -config string - the location of config file (default "loadgen.yml") - -cpu int - the number of CPUs to use (default -1) - -d int - Duration of tests in seconds (default 5) - -debug - run in debug mode, loadgen will quit on panic immediately with full stack trace - -dial-timeout int - Connection dial timeout in seconds, default 3s (default 3) - -gateway-log string - Log level of Gateway (default "debug") - -l int - Limit total requests (default -1) - -log string - the log level, options: trace,debug,info,warn,error,off - -mem int - the max size of Memory to use, soft limit in megabyte (default -1) - -plugin value - load additional plugins - -r int - Max requests per second (fixed QPS) (default -1) - -read-timeout int - Connection read timeout in seconds, default 0s (use -timeout) - -run string - DSL config to run tests (default "loadgen.dsl") - -service string - service management, options: install,uninstall,start,stop - -timeout int - Request timeout in seconds, default 60s (default 60) - -v version - -write-timeout int - Connection write timeout in seconds, default 0s (use -timeout) -``` - -### 限制客户端压力 - -使用 Loadgen 并设置命令行参数 `-r` 可以限制客户端发送的每秒请求数,从而评估固定压力下 Elasticsearch 的响应时间和负载情况,如下: - -```bash -loadgen -d 30 -c 100 -r 100 -``` - -> 注意,在大量并发下,此客户端吞吐限制可能不完全准确。 - -### 限制请求的总条数 - -通过设置参数 `-l` 可以控制客户端发送的请求总数,从而制造固定的文档,修改配置如下: - -```text -#// loadgen-gw.dsl -POST http://localhost:8000/medcl-test/doc2/_bulk -{"index": {"_index": "medcl-test", "_id": "$[[uuid]]"}} -{"id": "$[[id]]", "field1": "$[[user]]", "ip": "$[[ip]]"} -# request: { -# basic_auth: { -# username: "test", -# password: "testtest", -# }, -# body_repeat_times: 1, -# }, -``` - -每次请求只有一个文档,然后执行 Loadgen - -```bash -loadgen -run loadgen-gw.dsl -d 600 -c 100 -l 50000 -``` - -执行完成之后,Elasticsearch 的索引 `medcl-test` 将增加 `50000` 条记录。 - -### 使用自增 ID 来确保文档的顺序性 - -如果希望生成的文档编号自增有规律,方便进行对比,可以使用 `sequence` 类型的自增 ID 来作为主键,内容也不要用随机数,如下: - -```text -POST http://localhost:8000/medcl-test/doc2/_bulk -{"index": {"_index": "medcl-test", "_id": "$[[id]]"}} -{"id": "$[[id]]"} -# request: { -# basic_auth: { -# username: "test", -# password: "testtest", -# }, -# body_repeat_times: 1, -# }, -``` - -### 上下文复用变量 - -在一个请求中,我们可能希望有相同的参数出现,比如 `routing` 参数用来控制分片的路由,同时我们又希望该参数也保存在文档的 JSON 里面, -可以使用 `runtime_variables` 来设置请求级别的变量,或者 `runtime_body_line_variables` 定义请求体级别的变量,如果请求体复制 N 份,每份的参数是不同的,举例如下: - -```text -# variables: [ -# {name: "id", type: "sequence"}, -# {name: "uuid", type: "uuid"}, -# {name: "now_local", type: "now_local"}, -# {name: "now_utc", type: "now_utc"}, -# {name: "now_unix", type: "now_unix"}, -# {name: "suffix", type: "range", from: 10, to 15}, -# ], - -POST http://192.168.3.188:9206/_bulk -{"create": {"_index": "test-$[[suffix]]", "_type": "doc", "_id": "$[[uuid]]", "routing": "$[[routing_no]]"}} -{"id": "$[[uuid]]", "routing_no": "$[[routing_no]]", "batch_number": "$[[batch_no]]", "random_no": "$[[suffix]]", "ip": "$[[ip]]", "now_local": "$[[now_local]]", "now_unix": "$[[now_unix]]"} -# request: { -# runtime_variables: { -# batch_no: "id", -# }, -# runtime_body_line_variables: { -# routing_no: "uuid", -# }, -# basic_auth: { -# username: "ingest", -# password: "password", -# }, -# body_repeat_times: 10, -# }, -``` - -我们定义了 `batch_no` 变量来代表一批文档里面的相同批次号,同时又定义了 `routing_no` 变量来代表每个文档级别的 routing 值。 - -### 自定义 Header - -```text -GET http://localhost:8000/test/_search -# request: { -# headers: [ -# {Agent: "Loadgen-1"}, -# ], -# disable_header_names_normalizing: false, -# }, -``` - -默认配置下,Loadgen 会自动格式化配置里的 HTTP 的请求头(`user-agent: xxx` -> `User-Agent: xxx`),如果需要精确设置 HTTP 请求头,可以通过设置 `disable_header_names_normalizing: true` 来禁用这个行为。 - -## 运行测试套件 - -Loadgen 支持批量运行测试用例,不需要重复编写测试用例,通过切换套件配置来快速测试不同的环境配置: - -```yaml -# loadgen.yml -env: - # Set up envrionments to run test suite - LR_TEST_DIR: ./testing # The path to the test cases. - # If you want to start gateway dynamically and automatically: - LR_GATEWAY_CMD: ./bin/gateway # The path to the executable of INFINI Gateway - LR_GATEWAY_HOST: 0.0.0.0:18000 # The binding host of the INFINI Gateway - LR_GATEWAY_API_HOST: 0.0.0.0:19000 # The binding host of the INFINI Gateway API server - # Set up other envrionments for the gateway and loadgen - LR_ELASTICSEARCH_ENDPOINT: http://localhost:19201 - CUSTOM_ENV: myenv -tests: - # The relative path of test cases under `LR_TEST_DIR` - # - # - gateway.yml: (Optional) the configuration to start the INFINI Gateway dynamically. - # When present, the gateway is started via `LR_GATEWAY_CMD` before the test runs. - # - loadgen.dsl or loadgen.yml: the configuration to run the loadgen tool. - # If both exist, `loadgen.dsl` has higher priority. - # - # The environments set in the top-level `env` section will be passed to the - # INFINI Gateway subprocess. Environments defined in a per-test `loadgen.yml` - # are also available to that test, with per-test values taking precedence. - - path: cases/gateway/echo/echo_with_context -``` - -### 环境变量配置 - -Loadgen 通过环境变量来动态配置 INFINI Gateway,环境变量在 `env` 里指定。以下环境变量是必选的: - -| 变量名 | 说明 | -| ------------- | ---------------- | -| `LR_TEST_DIR` | 测试用例所在目录 | - -如果测试用例里包含 `gateway.yml`(即需要 `loadgen` 动态启动 INFINI Gateway),则必须设置以下环境变量: - -| 变量名 | 说明 | -| ---------------- | ------------------------------- | -| `LR_GATEWAY_CMD` | INFINI Gateway 可执行文件的路径 | - -`LR_GATEWAY_HOST` 和 `LR_GATEWAY_API_HOST` 不再是 Loadgen 自身的配置,而是测试用例里常用的模板变量。在 `gateway.yml` 中,entry 和 api 的 binding 可以写成 `$[[env.LR_GATEWAY_HOST]]` 和 `$[[env.LR_GATEWAY_API_HOST]]`;在 `loadgen.yml` / `loadgen.dsl` 的请求 URL 里也可以引用它们。Loadgen 会解析 `gateway.yml` 自动探测所有需要监听的端口。 - -环境变量的优先级(针对测试配置文件中的 `$[[env.ENV_KEY]]`)为: - -```text -OS 环境变量 > 测试用例 loadgen.yml 的 env > 顶层 loadgen.yml 的 env -``` - -### 测试用例配置 - -测试用例在 `tests` 里配置,每个路径(`path`)指向一个测试用例的目录,每个测试用例需要配置 - -1. Gateway 配置文件: `gateway.yml`(可选,存在时会动态启动 INFINI Gateway) -2. 测试文件: `loadgen.dsl` 或 `loadgen.yml`。如果 2 者均存在,`loadgen.dsl` 具有更高的优先级 - -测试用例自己的 `loadgen.yml` 里也可以定义 `env:` 段,用于覆盖或补充顶层 `loadgen.yml` 的环境变量(优先级见上文)。 - -配置文件可以使用 `env` 下配置的环境变量(`$[[env.ENV_KEY]]`)。 - -`gateway.yml` 参考配置: - -```yaml -path.data: data -path.logs: log - -entry: - - name: my_es_entry - enabled: true - router: my_router - max_concurrency: 200000 - network: - binding: $[[env.LR_GATEWAY_HOST]] - -flow: - - name: hello_world - filter: - - echo: - message: "hello world" -router: - - name: my_router - default_flow: hello_world -``` - -`loadgen.dsl` 参考配置: - -``` -# runner: { -# total_rounds: 1, -# no_warm: true, -# log_requests: true, -# assert_invalid: true, -# assert_error: true, -# }, - -GET http://$[[env.LR_GATEWAY_HOST]]/ -# assert: { -# _ctx.response: { -# status: 200, -# body: "hello world", -# }, -# }, -``` - -### 测试套件运行 - -配置好测试 `loadgen.yml` 后,可以通过以下命令运行 Loadgen: - -```bash -loadgen -config loadgen.yml -``` - -Loadgen 会运行配置指定的所有测试用例,并输出测试结果: - -```text -$ loadgen -config loadgen.yml - __ ___ _ ___ ___ __ __ - / / /___\/_\ / \/ _ \ /__\/\ \ \ - / / // ///_\\ / /\ / /_\//_\ / \/ / -/ /__/ \_// _ \/ /_// /_\\//__/ /\ / -\____|___/\_/ \_/___,'\____/\__/\_\ \/ - -[LOADGEN] A http load generator and testing suit. -[LOADGEN] 1.0.0_SNAPSHOT, 83f2cb9, Sun Jul 4 13:52:42 2021 +0800, medcl, support single item in dict files -[02-21 10:50:05] [INF] [app.go:192] initializing loadgen -[02-21 10:50:05] [INF] [app.go:193] using config: /Users/kassian/Workspace/infini/src/infini.sh/testing/suites/dev.yml -[02-21 10:50:05] [INF] [instance.go:78] workspace: /Users/kassian/Workspace/infini/src/infini.sh/testing/data/loadgen/nodes/cfpihf15k34iqhpd4d00 -[02-21 10:50:05] [INF] [app.go:399] loadgen is up and running now. -[2023-02-21 10:50:05][TEST][SUCCESS] [setup/loadgen/cases/dummy] duration: 105(ms) - -1 requests in 68.373875ms, 0.00bytes sent, 0.00bytes received - -[Loadgen Client Metrics] -Requests/sec: 0.20 -Request Traffic/sec: 0.00bytes -Total Transfer/sec: 0.00bytes -Avg Req Time: 5s -Fastest Request: 68.373875ms -Slowest Request: 68.373875ms -Number of Errors: 0 -Number of Invalid: 0 -Status 200: 1 - -[Estimated Server Metrics] -Requests/sec: 14.63 -Transfer/sec: 0.00bytes -Avg Req Time: 68.373875ms - - -[2023-02-21 10:50:06][TEST][FAILED] [setup/gateway/cases/echo/echo_with_context/] duration: 1274(ms) -#0 request, GET http://$[[env.LR_GATEWAY_HOST]]/any/, assertion failed, skiping subsequent requests -1 requests in 1.255678s, 0.00bytes sent, 0.00bytes received - -[Loadgen Client Metrics] -Requests/sec: 0.20 -Request Traffic/sec: 0.00bytes -Total Transfer/sec: 0.00bytes -Avg Req Time: 5s -Fastest Request: 1.255678s -Slowest Request: 1.255678s -Number of Errors: 1 -Number of Invalid: 1 -Status 0: 1 - -[Estimated Server Metrics] -Requests/sec: 0.80 -Transfer/sec: 0.00bytes -Avg Req Time: 1.255678s - -``` diff --git a/docs/content.zh/docs/getting-started/use-cases.md b/docs/content.zh/docs/getting-started/use-cases.md deleted file mode 100644 index 8c5df8c..0000000 --- a/docs/content.zh/docs/getting-started/use-cases.md +++ /dev/null @@ -1,653 +0,0 @@ ---- -weight: 60 -title: 使用场景与实战示例 ---- - -# 使用场景与实战示例 - -本文基于现有测试样例整理,重点覆盖以下场景: - -- 性能压测(批量写入、混合请求、搜索) -- 易用模式(一次性验证、快速回归) -- 变量与上下文复用(字典、序列、运行时变量) -- 基于 JSON 返回值断言与动态变量注册 -- 如何用语料库数据驱动 JSON 请求与响应验证 - -如果你是第一次接触 Loadgen,建议先阅读安装与基础说明,再回到本文按场景复制示例。 - -## 样例来源 - -以下示例来自仓库内已有用例,便于直接复用: - -- [testing/setup/loadgen/cases/bulk/create.yml](https://github.com/infinilabs/testing/blob/main/setup/loadgen/cases/bulk/create.yml) -- [testing/setup/loadgen/cases/bulk/mixed.yml](https://github.com/infinilabs/testing/blob/main/setup/loadgen/cases/bulk/mixed.yml) -- [testing/setup/loadgen/cases/search/random_search.yml](https://github.com/infinilabs/testing/blob/main/setup/loadgen/cases/search/random_search.yml) -- [testing/setup/loadgen/cases/dummy/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/loadgen/cases/dummy/loadgen.yml) -- [testing/setup/easysearch/cases/crud/create_without_id/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/easysearch/cases/crud/create_without_id/loadgen.yml) -- [testing/setup/gateway/cases/filters/set_response/gateway.yml](https://github.com/infinilabs/testing/blob/main/setup/gateway/cases/filters/set_response/gateway.yml) -- [testing/setup/gateway/cases/filters/set_response/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/gateway/cases/filters/set_response/loadgen.yml) -- [testing/setup/gateway/cases/echo/echo_with_context/gateway.yml](https://github.com/infinilabs/testing/blob/main/setup/gateway/cases/echo/echo_with_context/gateway.yml) -- [testing/setup/gateway/cases/echo/echo_with_context/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/gateway/cases/echo/echo_with_context/loadgen.yml) -- [testing/setup/loadgen/assets/dict/ip.txt](https://github.com/infinilabs/testing/blob/main/setup/loadgen/assets/dict/ip.txt) -- [testing/setup/loadgen/assets/dict/user.txt](https://github.com/infinilabs/testing/blob/main/setup/loadgen/assets/dict/user.txt) -- [testing/setup/loadgen/assets/dict/type.txt](https://github.com/infinilabs/testing/blob/main/setup/loadgen/assets/dict/type.txt) - -## 场景 1:批量写入压测(高吞吐) - -适用目标:验证写入吞吐、节点负载、队列压力。 - -可直接参考样例: - -- [testing/setup/loadgen/cases/bulk/create.yml](https://github.com/infinilabs/testing/blob/main/setup/loadgen/cases/bulk/create.yml) - -关键点: - -- 使用 body_repeat_times 构造单请求多文档 -- 使用 runtime_variables 固定批次号 -- 使用 runtime_body_line_variables 为每条文档生成不同 routing - -可直接复用的核心片段(来自 [testing/setup/loadgen/cases/bulk/create.yml](https://github.com/infinilabs/testing/blob/main/setup/loadgen/cases/bulk/create.yml)): - -```yaml -requests: - - request: - method: POST - runtime_variables: - batch_no: uuid - runtime_body_line_variables: - routing_no: uuid - url: http://127.0.0.1:8000/_bulk - body_repeat_times: 1000 - body: | - { "create" : { "_index" : "ab-test-$[[suffix]]","_type":"_doc", "_id" : "$[[id]]" , "routing" : "$[[routing_no]]" } } - { "id" : "$[[uuid]]","routing_no" : "$[[routing_no]]","batch_number" : "$[[batch_no]]", "random_no" : "$[[suffix]]","ip" : "$[[ip]]","now_local" : "$[[now_local]]","now_with_format" : "$[[now_with_format]]","now_unix" : "$[[now_unix]]" } -``` - -推荐启动参数: - -- 基准压测:loadgen -run testing/setup/loadgen/cases/bulk/create.yml -d 60 -c 100 -- 固定 QPS:loadgen -run testing/setup/loadgen/cases/bulk/create.yml -d 60 -c 100 -r 2000 -- 固定请求总量:loadgen -run testing/setup/loadgen/cases/bulk/create.yml -d 600 -c 100 -l 50000 - -## 场景 2:混合请求压测(贴近真实流量) - -适用目标:模拟 create、update、delete 混合流量,观察集群稳定性。 - -可直接参考样例: - -- [testing/setup/loadgen/cases/bulk/mixed.yml](https://github.com/infinilabs/testing/blob/main/setup/loadgen/cases/bulk/mixed.yml) - -建议做法: - -- 先用小并发验证语义正确性(-c 1 -d 5) -- 再逐步提升并发和持续时间 -- 结合监控看失败率、慢请求、磁盘 IO 与队列积压 - -## 场景 3:搜索压测(查询延迟与吞吐) - -适用目标:评估查询性能和过滤条件命中差异。 - -可直接参考样例: - -- [testing/setup/loadgen/cases/search/random_search.yml](https://github.com/infinilabs/testing/blob/main/setup/loadgen/cases/search/random_search.yml) - -关键点: - -- 使用 file 变量从语料文件中随机取值 -- 请求中用变量拼接查询参数 -- 可结合 assert 校验结果结构 - -变量片段(来自 [testing/setup/loadgen/cases/search/random_search.yml](https://github.com/infinilabs/testing/blob/main/setup/loadgen/cases/search/random_search.yml)): - -```yaml -variables: - - name: ip - type: file - path: dict/ip.txt - - name: id - type: sequence - - name: uuid - type: uuid -``` - -## 场景 4:快速可用性检查(一次性验证) - -适用目标:部署后健康检查、CI 中快速回归。 - -可直接参考样例: - -- [testing/setup/loadgen/cases/dummy/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/loadgen/cases/dummy/loadgen.yml) - -关键点: - -- runner.total_rounds: 1 -- runner.no_warm: true -- runner.assert_invalid: true -- runner.assert_error: true - -这组配置适合在流水线中“快速失败”。 - -## 场景 5:变量与上下文复用 - -### 5.1 字典变量(语料库) - -语料文件示例: - -- [testing/setup/loadgen/assets/dict/ip.txt](https://github.com/infinilabs/testing/blob/main/setup/loadgen/assets/dict/ip.txt) -- [testing/setup/loadgen/assets/dict/user.txt](https://github.com/infinilabs/testing/blob/main/setup/loadgen/assets/dict/user.txt) - -变量定义示例: - -```yaml -variables: - - name: ip - type: file - path: testing/setup/loadgen/assets/dict/ip.txt - - name: user - type: file - path: testing/setup/loadgen/assets/dict/user.txt -``` - -说明: - -- file 变量每次请求会从文件中随机取一行 -- 适合模拟真实语料分布(用户、IP、关键字、标签) - -### 5.2 运行时变量复用 - -见样例: - -- [testing/setup/loadgen/cases/bulk/create.yml](https://github.com/infinilabs/testing/blob/main/setup/loadgen/cases/bulk/create.yml) - -这个模式用于“一批请求共享一个值,每行再拥有独立值”: - -- runtime_variables:请求级变量(例如 batch_no) -- runtime_body_line_variables:请求体每行变量(例如 routing_no) - -## 场景 6:JSON 返回值断言与动态变量注册 - -### 6.1 基于 body_json 断言 - -见样例: - -- [testing/setup/gateway/cases/filters/set_response/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/gateway/cases/filters/set_response/loadgen.yml) -- [testing/setup/easysearch/cases/crud/create_without_id/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/easysearch/cases/crud/create_without_id/loadgen.yml) - -典型断言: - -- _ctx.response.status -- _ctx.response.body_json.message -- _ctx.response.body_json._source.a - -断言片段(来自 [testing/setup/gateway/cases/filters/set_response/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/gateway/cases/filters/set_response/loadgen.yml)): - -```yaml -assert: - equals: - _ctx.response.status: 200 - _ctx.response.body_json.message: hello world -``` - -### 6.2 从 JSON 返回值注册变量(register) - -见样例: - -- [testing/setup/easysearch/cases/crud/create_without_id/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/easysearch/cases/crud/create_without_id/loadgen.yml) - -先注册: - -- doc_id: _ctx.response.body_json._id - -注册片段(来自 [testing/setup/easysearch/cases/crud/create_without_id/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/easysearch/cases/crud/create_without_id/loadgen.yml)): - -```yaml -register: - - doc_id: _ctx.response.body_json._id -``` - -后续请求复用: - -- URL 里使用 $[[doc_id]] 进行读取、更新、删除 - -这是一种非常实用的“链路式测试”写法。 - -## 场景 7:如何基于语料库做 JSON 请求与 JSON 响应验证 - -这个场景通常有两层: - -- 用语料库驱动请求内容(Loadgen 侧) -- 对 JSON 响应按字段断言(Loadgen 侧) - -### 7.1 语料驱动 JSON 请求 - -推荐方式: - -1. 把语料整理成文本行(例如用户、IP、类型) -2. 通过 file 变量读取 -3. 在 JSON body 中插入变量 - -现成语料可参考: - -- [testing/setup/loadgen/assets/dict/user.txt](https://github.com/infinilabs/testing/blob/main/setup/loadgen/assets/dict/user.txt) -- [testing/setup/loadgen/assets/dict/ip.txt](https://github.com/infinilabs/testing/blob/main/setup/loadgen/assets/dict/ip.txt) -- [testing/setup/loadgen/assets/dict/type.txt](https://github.com/infinilabs/testing/blob/main/setup/loadgen/assets/dict/type.txt) - -### 7.2 JSON 响应字段断言 - -参考: - -- [testing/setup/gateway/cases/filters/set_response/gateway.yml](https://github.com/infinilabs/testing/blob/main/setup/gateway/cases/filters/set_response/gateway.yml) -- [testing/setup/gateway/cases/filters/set_response/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/gateway/cases/filters/set_response/loadgen.yml) - -该用例中 Gateway 固定返回 JSON,Loadgen 使用 _ctx.response.body_json.message 做字段级断言。 - -响应构造片段(来自 [testing/setup/gateway/cases/filters/set_response/gateway.yml](https://github.com/infinilabs/testing/blob/main/setup/gateway/cases/filters/set_response/gateway.yml)): - -```yaml -flow: - - name: test - filter: - - set_response: - status: 200 - content_type: application/json - body: '{"message":"hello world"}' -``` - -### 7.3 上下文拼装响应内容 - -参考: - -- [testing/setup/gateway/cases/echo/echo_with_context/gateway.yml](https://github.com/infinilabs/testing/blob/main/setup/gateway/cases/echo/echo_with_context/gateway.yml) -- [testing/setup/gateway/cases/echo/echo_with_context/loadgen.yml](https://github.com/infinilabs/testing/blob/main/setup/gateway/cases/echo/echo_with_context/loadgen.yml) - -这种模式通过上下文变量拼接响应,再由 Loadgen 校验响应片段,适合做“动态响应内容”测试。 - -## 场景 8:建议的目录组织(便于团队协作) - -建议把压测工程拆成三层: - -- suites:环境与套件编排 -- setup/.../cases:按功能分组的用例 -- assets/dict:语料与字典 - -当前仓库可参考: - -- [testing/suites](https://github.com/infinilabs/testing/tree/main/suites) -- [testing/setup/loadgen/cases](https://github.com/infinilabs/testing/tree/main/setup/loadgen/cases) -- [testing/setup/loadgen/assets/dict](https://github.com/infinilabs/testing/tree/main/setup/loadgen/assets/dict) - -## 场景 9:性能测试实践建议 - -- 先验证正确性,再加压 -- 保持单次变更可对比(只改一个变量) -- 固定语料与随机语料分开测试 -- 关注 Number of Errors 与 Number of Invalid -- 对服务端性能结论,优先看监控平台而不是只看客户端汇总 - -## 场景 10:Loadgen 做 Coco AI 集成测试 - -我们已经在 Coco AI 项目里用 Loadgen 落地了集成测试,核心模式是: - -- 用一份公共 loadgen.yml 提供环境变量与全局 runner -- 用多份 DSL 场景文件表达权限、资源、行为测试 -- 用脚本自动执行全部 DSL,失败即中断 - -可直接参考(公开仓库): - -- [coco/tests/loadgen.yml](https://github.com/infinilabs/coco-server/blob/main/tests/loadgen.yml) -- [coco/tests/assets/run_integration_tests.py](https://github.com/infinilabs/coco-server/blob/main/tests/assets/run_integration_tests.py) -- [coco/tests/llm/scenario3.dsl](https://github.com/infinilabs/coco-server/blob/main/tests/llm/scenario3.dsl) -- [coco/tests/assistant/scenario1.dsl](https://github.com/infinilabs/coco-server/blob/main/tests/assistant/scenario1.dsl) -- [coco/tests/datasource/scenario1.dsl](https://github.com/infinilabs/coco-server/blob/main/tests/datasource/scenario1.dsl) - -### 10.0 DSL 怎么写(可直接复制) - -下面给出 3 组最常用 DSL 片段,覆盖“登录拿 token -> 带鉴权调用 -> 断言与链路变量”。 - -示例 A:登录并注册 token(register) - -```text -POST /account/login -{ - "email": "admin@mail.com", - "password": "$[[env.ADMIN_PASSWORD]]" -} -# assert: (200, {status: "ok"}), -# register: [ -# { admin_token: "_ctx.response.body_json.access_token" }, -# ] -``` - -示例 B:使用 token 调用业务接口(headers + 断言) - -```text -GET /model_provider/_search?from=0&size=10&query=llm_a -# request: { -# headers: [ -# {Authorization: "Bearer $[[admin_token]]"}, -# ], -# disable_header_names_normalizing: true, -# }, -# assert: (200, { -# "hits.total.value": 1 -# }) -``` - -示例 C:授权写入 + JSON 字段断言 - -```text -POST /resources/llm-provider/$[[env.LLM_A_ID]]/share -{ - "shares": [ - { - "resource_type": "llm-provider", - "resource_id": "$[[env.LLM_A_ID]]", - "principal_type": "user", - "principal_id": "$[[env.A_ID]]", - "permission": $[[env.EDIT_ACCESS]] - } - ], - "revokes": [] -} -# request: { -# headers: [ -# {Authorization: "Bearer $[[admin_token]]"}, -# ], -# disable_header_names_normalizing: true, -# }, -# assert: (200, { -# "created": [ -# { -# "resource_id": "$[[env.LLM_A_ID]]", -# "principal_id": "$[[env.A_ID]]", -# "permission": $[[env.EDIT_ACCESS]] -# } -# ] -# }) -``` - -### 10.1 单场景调试 - -当你只想调试某一类能力(例如 LLM 权限共享)时,可以直接运行单个 DSL: - -```bash -cd coco -loadgen -config ./tests/loadgen.yml -run ./tests/llm/scenario3.dsl -debug -``` - -对应的现成脚本: - -- [coco/tests/llm/test.sh](https://github.com/infinilabs/coco-server/blob/main/tests/llm/test.sh) - -最小可运行配置(loadgen.yml)示例: - -```yaml -runner: - total_rounds: 1 - no_warm: true - reset_context: true - assert_invalid: true - default_endpoint: "$[[env.COCO_SERVER]]" - -env: - COCO_SERVER: http://127.0.0.1:9000 - ADMIN_PASSWORD: PASSword_123 - LLM_A_ID: d4cnisa8sig62phqk9ug - A_ID: dd3626ce78553287cd9216f4e4974d26 - EDIT_ACCESS: 4 -``` - -### 10.2 全量集成回归 - -如果要做完整回归,使用 Python 脚本自动发现 tests 目录下所有 DSL 并串行执行: - -```bash -cd coco -python3 ./tests/assets/run_integration_tests.py -``` - -这个脚本会自动执行以下动作: - -1. 停止并清理环境 -2. 启动 Coco 服务 -3. 调用 loadgen 运行 DSL -4. 再次清理并进入下一个场景 - -相关脚本: - -- [coco/tests/assets/start_coco.sh](https://github.com/infinilabs/coco-server/blob/main/tests/assets/start_coco.sh) -- [coco/tests/assets/stop_coco.sh](https://github.com/infinilabs/coco-server/blob/main/tests/assets/stop_coco.sh) -- [coco/tests/assets/reset_coco_indices.sh](https://github.com/infinilabs/coco-server/blob/main/tests/assets/reset_coco_indices.sh) - -### 10.3 适用收益 - -这个模式对集成测试非常实用: - -- 同时验证 API 协议、鉴权、资源可见性与权限语义 -- 用 register 从登录响应里提取 token,实现跨步骤编排 -- 场景 DSL 可读性高,便于团队协作与评审 -- 可以平滑接入 CI,作为发布前强校验 - -### 10.4 DSL 编写速查(避免只看链接) - -1. 请求行:`METHOD /path` 或 `METHOD http://host/path` -2. 请求体:紧跟在请求行后,支持 JSON -3. 请求配置:放在 `# request: { ... },` 注释块 -4. 断言:放在 `# assert: (...)` 注释块 -5. 注册变量:放在 `# register: [ ... ]` 注释块 - -示例(完整链路最小版): - -```text -POST /account/login -{"email":"admin@mail.com","password":"$[[env.ADMIN_PASSWORD]]"} -# assert: (200, {status: "ok"}), -# register: [ -# { token: "_ctx.response.body_json.access_token" }, -# ] - -GET /account/profile -# request: { -# headers: [ -# {Authorization: "Bearer $[[token]]"}, -# ], -# disable_header_names_normalizing: true, -# }, -# assert: (200, { -# "status": "ok" -# }) -``` - -## 场景 11:全量变量与参数模板(建议复制后按需删减) - -这一节给一份“尽量完整”的模板,覆盖常见变量类型与参数。 - -### 11.1 变量类型全量示例 - -```text -# variables: [ -# { -# name: "ip", -# type: "file", -# path: "dict/ip.txt", -# data: ["10.0.0.1", "10.0.0.2"], -# replace: { -# '"': '\\"', -# '\\': '\\\\', -# }, -# }, -# { -# name: "user", -# type: "list", -# data: ["alice", "bob", "coco"], -# }, -# { -# name: "id", -# type: "sequence", -# from: 1, -# to: 999999, -# }, -# { -# name: "id64", -# type: "sequence64", -# from: 1, -# to: 999999999999, -# }, -# { -# name: "uuid", -# type: "uuid", -# }, -# { -# name: "now_local", -# type: "now_local", -# }, -# { -# name: "now_utc", -# type: "now_utc", -# }, -# { -# name: "now_utc_lite", -# type: "now_utc_lite", -# }, -# { -# name: "now_unix", -# type: "now_unix", -# }, -# { -# name: "now_fmt", -# type: "now_with_format", -# format: "2006-01-02T15:04:05-0700", -# }, -# { -# name: "suffix", -# type: "range", -# from: 10, -# to: 1000, -# }, -# { -# name: "id_list", -# type: "random_array", -# variable_type: "number", -# variable_key: "suffix", -# square_bracket: false, -# string_bracket: "", -# size: 10, -# }, -# { -# name: "str_list", -# type: "random_array", -# variable_type: "string", -# variable_key: "user", -# square_bracket: true, -# string_bracket: "\"", -# size: 5, -# replace: { -# '"': "'", -# "[": "{", -# "]": "}", -# }, -# }, -# ] -``` - -变量类型速览: - -- file -- list -- sequence -- sequence64 -- range -- random_array -- uuid -- now_local -- now_utc -- now_utc_lite -- now_unix -- now_with_format - -### 11.2 runner 参数全量示例 - -```text -# runner: { -# total_rounds: 1, -# no_warm: false, -# valid_status_codes_during_warmup: [200, 201, 404], -# log_requests: false, -# log_status_codes: [0, 400, 500], -# assert_invalid: false, -# assert_error: false, -# reset_context: false, -# disable_header_names_normalizing: false, -# default_endpoint: "$[[env.ES_ENDPOINT]]", -# default_basic_auth: { -# username: "$[[env.ES_USERNAME]]", -# password: "$[[env.ES_PASSWORD]]", -# }, -# }, -``` - -### 11.3 request 参数全量示例 - -```text -POST /_bulk -{"index": {"_index": "demo-$[[suffix]]", "_id": "$[[uuid]]", "routing": "$[[routing_no]]"}} -{"id":"$[[id]]","user":"$[[user]]","ip":"$[[ip]]","batch":"$[[batch_no]]","ts":"$[[now_fmt]]"} -# request: { -# basic_auth: { -# username: "$[[env.ES_USERNAME]]", -# password: "$[[env.ES_PASSWORD]]", -# }, -# headers: [ -# {Authorization: "Bearer $[[token]]"}, -# {X-Trace-Id: "$[[uuid]]"}, -# ], -# disable_header_names_normalizing: true, -# runtime_variables: { -# batch_no: "uuid", -# }, -# runtime_body_line_variables: { -# routing_no: "uuid", -# }, -# body_repeat_times: 100, -# }, -# assert: { -# _ctx.response.status: 200, -# }, -# register: [ -# { task_id: "_ctx.response.body_json.task" }, -# ] -``` - -## 常用命令清单 - -单用例运行: - -```bash -loadgen -run testing/setup/loadgen/cases/search/random_search.yml -d 30 -c 10 -``` - -固定 QPS: - -```bash -loadgen -run testing/setup/loadgen/cases/bulk/create.yml -d 60 -c 100 -r 1000 -``` - -固定总请求数: - -```bash -loadgen -run testing/setup/loadgen/cases/bulk/create.yml -d 600 -c 100 -l 50000 -``` - -套件运行: - -```bash -loadgen -config testing/suites/gateway-sample.yml -``` - -Coco AI 全量集成测试: - -```bash -cd coco -python3 ./tests/assets/run_integration_tests.py -``` -