Blame view

docs/工作总结-微服务性能优化与架构.md 18 KB
208e079a   tangwang   TODO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  # 工作总结:微服务性能优化与架构
  
  本文档汇总**三个微服务的性能优化****架构设计****性能测试基线**,便于汇报与后续复现。
  
  ---
  
  ## 一、完成三个微服务的性能优化
  
  ### 1. 文本向量(Embedding)
  
  **调研与选型**:对 TEI(Text Embeddings Inference)、vLLM 与原有 SentenceTransformers 方案进行对比评估。
  
  | 方案 | 特点 | 结论 |
  |------|------|------|
  | **SentenceTransformers** | 本地 Python 进程,单机推理,无独立服务化 | 此前用于 Qwen3-Embedding-0.6B,扩展性与运维性一般 |
  | **vLLM** | 高吞吐推理框架,更适合生成式与重排混合场景 | 纯 embedding 场景通常不作为首选 |
  | **TEI** | HuggingFace 官方 embedding 专用推理服务,Docker 部署 | **当前最优选型** |
  
5bac9649   tangwang   文本 embedding 与图片 ...
19
  **当前方案**:以 **TEI** 为文本向量后端,模型为 `Qwen/Qwen3-Embedding-0.6B`;文本 embedding 服务(端口 **6005**)将 `POST /embed/text` 请求转发至 TEI(默认端口 **8080**)。
208e079a   tangwang   TODO
20
21
22
23
  
  **具体配置与脚本**
  - **配置**`config/config.yaml` → `services.embedding.backend: "tei"`,`services.embedding.backends.tei.base_url: "http://127.0.0.1:8080"`、`model_id: "Qwen/Qwen3-Embedding-0.6B"`、`timeout_sec: 20`
  - **启动**`scripts/start_tei_service.sh`(Docker 容器);环境变量:`TEI_DEVICE=cuda`(默认)、`TEI_PORT=8080`、`TEI_MODEL_ID=Qwen/Qwen3-Embedding-0.6B`、`TEI_VERSION=1.9`、`TEI_MAX_BATCH_TOKENS=4096`、`TEI_MAX_CLIENT_BATCH_SIZE=24`、`TEI_DTYPE=float16`;T4 自动选镜像 `ghcr.io/huggingface/text-embeddings-inference:turing-1.9`
5bac9649   tangwang   文本 embedding 与图片 ...
24
  - **编排**`./scripts/service_ctl.sh start tei` 或 `start embedding`(text embedding 会校验 TEI `/health` 后再就绪)。
208e079a   tangwang   TODO
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  
  **工程化收益**
  - **独立服务**:TEI 以 Docker 容器运行,与主程序 `.venv` 解耦;embedding 使用 `.venv-embedding`,便于独立扩缩容与升级。
  - **协议统一**:与 `local_st`(SentenceTransformers)可插拔,通过 `config.yaml` 的 `services.embedding.backend` 或环境变量 `EMBEDDING_BACKEND` 切换。
  - **T4 适配**:按 GPU 架构自动选择镜像(T4 用 `turing-*`,Ampere+ 用 `cuda-*`);`TEI_MAX_BATCH_TOKENS`、`TEI_MAX_CLIENT_BATCH_SIZE`、`TEI_DTYPE` 已按短文本场景调优。
  - **健康检查与编排**`service_ctl.sh` 对 tei 校验容器存在且 `GET http://127.0.0.1:8080/health` 成功;embedding 启动前会等待 TEI 健康。
  
  详见:`docs/TEI_SERVICE说明文档.md`、`docs/QUICKSTART.md` §4。
  
  ---
  
  ### 2. 重排(Reranker)
  
  **后端**:vLLM 部署 **Qwen3-Reranker-0.6B**,对外提供 `POST /rerank`(query + docs → scores),端口 **6007**
  
  **针对 T4 的优化(已落地配置)**
  - **精度**`dtype: "float16"`,降低显存与计算量。
  - **Prefix Caching**`enable_prefix_caching: true`,对重复前缀(如相同 query)做缓存,减少重复计算。
  - **CUDA 图**`enforce_eager: false`(默认),利用 vLLM 的 CUDA graph 降低 kernel 启动开销。
fb973d19   tangwang   configs
44
  - **按文档长度分批**`sort_by_doc_length: true`,请求内先按文档长度排序再按 `infer_batch_size` 分批推理,减少 padding 浪费。
208e079a   tangwang   TODO
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  - **参数搜索结论**:在 T4、1000-doc 口径下对 `infer_batch_size` 做了 24/32/48/64 对比;**单请求延迟(c=1)** 上 `infer_batch_size=64` 最优,故当前默认 `infer_batch_size: 64`;`max_model_len: 256` 满足 query+doc 短文本场景;`gpu_memory_utilization: 0.36` 与 T4 16GB 匹配。
  
  **具体配置**`config/config.yaml` → `services.rerank.backends.qwen3_vllm`):
  ```yaml
  model_name: "Qwen/Qwen3-Reranker-0.6B"
  engine: "vllm"
  max_model_len: 256
  tensor_parallel_size: 1
  gpu_memory_utilization: 0.36
  dtype: "float16"
  enable_prefix_caching: true
  enforce_eager: false
  infer_batch_size: 64
  sort_by_doc_length: true
208e079a   tangwang   TODO
59
60
61
62
63
64
65
66
67
68
  instruction: "Given a shopping query, rank product titles by relevance"
  ```
  环境变量覆盖:`RERANK_BACKEND`、`RERANKER_SERVICE_URL`、`RERANK_VLLM_INFER_BATCH_SIZE`、`RERANK_VLLM_SORT_BY_DOC_LENGTH` 等。启停:`./scripts/service_ctl.sh start reranker`,健康:`curl -sS http://127.0.0.1:6007/health`
  
  详见:`reranker/DEPLOYMENT_AND_TUNING.md`、`reranker/README.md`
  
  ---
  
  ### 3. 图片向量(Image Embedding)
  
4747e2f4   tangwang   embedding perform...
69
  **方案****clip-as-service**(CN-CLIP,模型由配置控制),由独立服务提供图片向量化能力。
208e079a   tangwang   TODO
70
71
72
  
  **具体内容**
  - **端口**:clip-as-service 默认 **51000**`CNCLIP_PORT`);文本走 TEI(8080),图片走 clip-as-service。
5bac9649   tangwang   文本 embedding 与图片 ...
73
  - **API**:文本 embedding 服务默认暴露 `POST /embed/text`(6005),图片 embedding 服务默认暴露 `POST /embed/image`(6008);图片请求由 `embeddings/server.py` 按配置调用实现 `ImageEncoderProtocol` 的后端(clip-as-service 或本地 CN-CLIP)。
208e079a   tangwang   TODO
74
  - **环境与启停**:CN-CLIP 使用独立虚拟环境 `.venv-cnclip`;启动 `scripts/start_cnclip_service.sh`,或 `./scripts/service_ctl.sh start cnclip`;设备可通过 `CNCLIP_DEVICE=cuda`(默认)或 `cpu` 指定。
4747e2f4   tangwang   embedding perform...
75
  - **配置**:图片后端在 `config/config.yaml` 的 `services.embedding` 下配置(若存在 image 相关 backend);clip-as-service 默认模型由 `embeddings/config.py` 的 `CLIP_AS_SERVICE_MODEL_NAME` 控制,flow 配置在 `third-party/clip-as-service/server/torch-flow-temp.yml`
208e079a   tangwang   TODO
76
77
78
79
80
81
82
83
84
85
  
  详见:`docs/CNCLIP_SERVICE说明文档.md`、`embeddings/README.md`
  
  ---
  
  ### 4. 翻译(Translation)
  
  **背景**:原使用 DeepL,后迁移至 **qwen-mt**(如 `qwen-mt-flash`)。qwen-mt 云端限速约 **RPM=60(每分钟 60 请求)**,此前未做大商品量压测,未暴露问题;高并发索引或查询场景下易触限。
  
  **当前方案**
0fd2f875   tangwang   translate
86
87
88
89
  - **统一 translator service**:业务侧统一走 6006,按 `model + scene` 选择能力,不再存在翻译 provider 分支。
  - **配置入口**`config/config.yaml` → `services.translation`,显式声明 `service_url`、`default_model`、`default_scene`、各 capability 的 `backend`、`base_url/api_url`、timeout 与本地模型运行参数。
  - **内部规则收口**:scene 集合、语言码映射、LLM prompt 模板、本地模型方向约束统一放在 `translation/` 内部,不再散落在 `config/`、`query/` 等位置。
  - **调用位置**:QueryParser 与 Indexer 均通过 `translation.create_translation_client()` 获取客户端,不写死 URL 或模型名。
cd4ce66d   tangwang   trans logs
90
  - **缓存**:translator service 对所有 translation capability 统一接入 Redis 缓存;每个 capability 通过 `use_cache` 控制开关,key 格式固定为 `trans:{model}:{target_lang}:{source_text[:4]}{sha256}`
208e079a   tangwang   TODO
91
92
93
94
95
  - **场景支撑**:在线索引(indexer)与 query 请求(QueryParser)共用同一套 provider 配置;可按环境或租户通过修改 `config.yaml` 或环境变量切换 provider/model。
  - **待配合****金伟侧对索引侧翻译调用做流量控制**(限流/排队/批量聚合),避免索引高峰打满 qwen 限速,影响在线 query 翻译。
  
  ---
  
a3275468   tangwang   已把本仓库里的 `/indexer...
96
  ### 5. 内容理解字段(已迁出)
208e079a   tangwang   TODO
97
  
a3275468   tangwang   已把本仓库里的 `/indexer...
98
  `qanchors`、`enriched_attributes`、`enriched_tags`、`enriched_taxonomy_attributes` 这些字段模型仍保留在索引结构里,`suggestion/builder.py` 等消费侧也仍可继续使用 ES 中已有的 `qanchors`。但字段生成服务与其本地实现已经迁移到独立项目,本仓库不再提供 `/indexer/enrich-content`,也不再在 indexer 构建链路内自动补齐这些字段。
208e079a   tangwang   TODO
99
  
a3275468   tangwang   已把本仓库里的 `/indexer...
100
  当前边界:
208e079a   tangwang   TODO
101
  
a3275468   tangwang   已把本仓库里的 `/indexer...
102
103
104
  - 本仓库负责基础 doc 构建、多语言字段、向量、规格聚合等索引能力。
  - 独立内容理解服务负责生成 `qanchors` / `enriched_*`
  - 上游索引程序负责把两侧结果合并后写入 ES。
208e079a   tangwang   TODO
105
106
107
108
109
  
  ---
  
  ## 二、架构
  
0fd2f875   tangwang   translate
110
  ### 1. Translator Service 与动态选择翻译
208e079a   tangwang   TODO
111
  
0fd2f875   tangwang   translate
112
  - **设计**:翻译已从 provider 架构中独立出来,采用 **一个 translator service + 多个 capability backend**;配置单一来源为 `config/config.yaml` 的 `services.translation` 块,`service_url` / `default_model` / `default_scene` 不再接受环境变量静默覆盖。
208e079a   tangwang   TODO
113
  - **翻译(具体实现)**
0fd2f875   tangwang   translate
114
115
116
117
118
    - **业务入口**`translation.create_translation_client()`
    - **服务编排**`translation/service.py`
    - **后端实现**`translation/backends/qwen_mt.py`、`translation/backends/llm.py`、`translation/backends/deepl.py`、`translation/backends/local_seq2seq.py`
    - **调用方**`query/query_parser.py`、`indexer/incremental_service.py`、`indexer/indexing_utils.py`
  - **效果**:仅改 `services.translation.default_model` 或启用的 capability,即可切换云端/本地翻译能力;调用方始终只连 6006。
208e079a   tangwang   TODO
119
120
121
122
123
  
  ### 2. 服务的监控与拉起机制
  
  - **脚本**`scripts/service_ctl.sh` 统一负责各服务的生命周期与监控;依赖 `scripts/lib/load_env.sh` 与项目根目录 `.env`
  - **服务与端口**
7b8d9e1a   tangwang   评估框架的启动脚本
124
    - 核心:backend **6002**、indexer **6004**、frontend **6003**、eval-web **6010**(搜索评估 UI)。
5bac9649   tangwang   文本 embedding 与图片 ...
125
    - 可选:embedding(text) **6005**、embedding-image **6008**、translator **6006**、reranker **6007**、tei **8080**、cnclip **51000**
7b8d9e1a   tangwang   评估框架的启动脚本
126
    - 端口可由环境变量覆盖:`API_PORT`、`INDEXER_PORT`、`FRONTEND_PORT`、`EVAL_WEB_PORT`、`EMBEDDING_TEXT_PORT`、`EMBEDDING_IMAGE_PORT`、`TRANSLATION_PORT`、`RERANKER_PORT`、`TEI_PORT`、`CNCLIP_PORT`
208e079a   tangwang   TODO
127
  - **命令**
3abbc95a   tangwang   重构(scripts): 整理sc...
128
    - `./scripts/service_ctl.sh start [service...]` 或 `up all` / `start all`(all 含 tei、cnclip、embedding、embedding-image、translator、reranker、backend、indexer、frontend、eval-web,按依赖顺序);`stop`、`restart`、`down` 同参数;`status` 默认列出所有服务。
208e079a   tangwang   TODO
129
130
131
    - 启动时:backend/indexer/frontend/embedding/translator/reranker 会写 pid 到 `logs/<service>.pid`,并执行 `wait_for_health`(GET `http://127.0.0.1:<port>/health`);reranker 健康重试 90 次,其余 30 次;TEI 校验 Docker 容器存在且 `/health` 成功;cnclip 无 HTTP 健康则仅校验进程/端口。
  - **监控常驻**
    - `./scripts/service_ctl.sh monitor-start <targets>` 启动后台监控进程,将 targets 写入 `logs/service-monitor.targets`,pid 写入 `logs/service-monitor.pid`,日志追加到 `logs/service-monitor.log`
32e9b30c   tangwang   scripts/ 根目录主要保留启...
132
133
    - 轮询间隔 `MONITOR_INTERVAL_SEC` 默认 **10** 秒;连续 **3** 次(`MONITOR_FAIL_THRESHOLD`)健康失败则触发重启;重启冷却 `MONITOR_RESTART_COOLDOWN_SEC` 默认 **30** 秒;每小时最多重启 `MONITOR_MAX_RESTARTS_PER_HOUR` 默认 **6** 次;超限时调用 `scripts/ops/wechat_alert.py` 告警(若存在)。
  - **日志**:各服务按日滚动到 `logs/<service>-<date>.log`,通过 `scripts/ops/daily_log_router.sh` 与 `LOG_RETENTION_DAYS`(默认 30)控制保留。
208e079a   tangwang   TODO
134
135
136
137
138
139
140
141
142
143
  
  详见:`scripts/service_ctl.sh` 内注释及 `docs/Usage-Guide.md`
  
  ### 3. Suggest 索引与增量
  
  - **当前**:suggest 索引由**全量脚本触发**,入口为 `main.py build-suggestions`,或封装脚本 `scripts/build_suggestions.sh <tenant_id> [args...]`
    - **全量示例**`./scripts/build_suggestions.sh 162 --mode full --days 30 --publish-alias`(重建建议索引,近 30 天数据,并发布别名)。
    - **增量示例**`./scripts/build_suggestions.sh 162 --mode incremental --overlap-minutes 30`(按 watermark 增量更新);脚本内部调用 `main.py build-suggestions --tenant-id <id> ...`
    - 构建逻辑在 `suggestion/builder.py` 的 `SuggestionIndexBuilder`:从 ES 商品索引(含 `title`、`qanchors`)与查询日志等拉取数据,写入 versioned 建议索引并切换 alias。
  - **尚未完成的“增量机制”**:指**自动/事件驱动的增量**(如商品变更或日志写入时自动刷新建议索引);当前 incremental 模式为“按 watermark 再跑一次构建”,仍为脚本主动触发,非持续增量流水线。
a3275468   tangwang   已把本仓库里的 `/indexer...
144
  - **依赖**:suggest 候选依赖商品侧 **内容理解字段**(qanchors/tags);`sources: ["query_log", "qanchor"]` 表示候选来自查询日志与 qanchor。字段生成职责已迁移到独立内容理解服务。
208e079a   tangwang   TODO
145
146
147
148
149
150
151
  
  详见:`suggestion/builder.py`、`suggestion/ARCHITECTURE_V2.md`、`main.py`(build-suggestions 子命令)。
  
  ---
  
  ## 三、性能测试报告摘要
  
3abbc95a   tangwang   重构(scripts): 整理sc...
152
  以下数据来自 `docs/性能测试报告.md`,测试时间 **2026-03-12**,环境:**8 vCPU**(Intel Xeon Platinum 8255C @ 2.50GHz)、**约 15Gi 可用内存**;租户 **162** 文档数约 **53**(search/search/suggestions/rerank 与文档规模相关)。压测工具:`benchmarks/perf_api_benchmark.py`,场景×并发矩阵,每档 **20s**
208e079a   tangwang   TODO
153
154
155
156
  
  **复现命令(四场景×四并发)**
  ```bash
  cd /data/saas-search
3abbc95a   tangwang   重构(scripts): 整理sc...
157
  .venv/bin/python benchmarks/perf_api_benchmark.py \
208e079a   tangwang   TODO
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
    --scenario backend_search,backend_suggest,embed_text,rerank \
    --concurrency-list 1,5,10,20 \
    --duration 20 \
    --tenant-id 162 \
    --backend-base http://127.0.0.1:6002 \
    --embedding-base http://127.0.0.1:6005 \
    --translator-base http://127.0.0.1:6006 \
    --reranker-base http://127.0.0.1:6007 \
    --output perf_reports/2026-03-12/perf_matrix_report.json
  ```
  执行前需启动服务:`./scripts/service_ctl.sh start embedding translator reranker backend`,并通过各端口 `/health` 检查。Reranker 单独 386-docs 口径复现见性能测试报告 §7.4 与 §13。
  
  ### 3.1 向量化服务(embed_text)
  
  | 并发 | 请求数 | 成功率 | 吞吐(RPS) | Avg(ms) | P95(ms) | Max(ms) |
  |-----:|-------:|-------:|----------:|--------:|--------:|--------:|
  | 1    | 966   | 100%  | 48.27     | 20.63   | 23.41   | 49.80   |
  | 5    | 1796  | 100%  | 89.57     | 55.55   | 69.62   | 109.84  |
  | 10   | 2095  | 100%  | 104.42    | 95.22   | 117.66  | 152.48  |
  | 20   | 2393  | 100%  | 118.70    | 167.37  | 212.21  | 318.70  |
  
  **结论**:随并发提升吞吐持续增长,延迟平滑上升,扩展性较好。
  
  ---
  
  ### 3.2 Reranker(rerank)
  
  口径:query 固定 `wireless mouse`,每次请求 **386 docs**,句长 15–40 词随机(从 1000 词池采样);配置 `rerank_window=384`。复现命令:
  ```bash
3abbc95a   tangwang   重构(scripts): 整理sc...
187
  .venv/bin/python benchmarks/perf_api_benchmark.py \
208e079a   tangwang   TODO
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
    --scenario rerank --duration 20 --concurrency-list 1,5,10,20 --timeout 60 \
    --rerank-dynamic-docs --rerank-doc-count 386 --rerank-vocab-size 1000 \
    --rerank-sentence-min-words 15 --rerank-sentence-max-words 40 \
    --rerank-query "wireless mouse" --rerank-seed 20260312 \
    --reranker-base http://127.0.0.1:6007 \
    --output perf_reports/2026-03-12/rerank_realistic/rerank_386docs.json
  ```
  
  | 并发 | 请求数 | 成功率 | 吞吐(RPS) | Avg(ms) | P95(ms) | Max(ms) |
  |-----:|-------:|-------:|----------:|--------:|--------:|--------:|
  | 1    | 14    | 100%  | 0.67      | 1498.64 | 1799.25 | 2160.96 |
  | 5    | 15    | 100%  | 0.62      | 8011.99 | 9725.61 | 9726.02 |
  | 10   | 20    | 100%  | 0.61      | 16217.12| 18043.05| 18050.04|
  | 20   | 20    | 100%  | 0.60      | 33252.35| 33456.74| 33480.14|
  
  **结论**:在 386 docs/请求 的真实口径下,吞吐约 **0.6 rps**,延迟随并发明显上升(并发 20 时 P95 约 33.5s),是当前整条链路的**最重瓶颈**。与 DashScope 云后端对比:单并发 vLLM 延迟更优;并发 5+ 时云后端吞吐更高(约 1.3x–6x),在线高并发场景可优先考虑云后端。
  
  ---
  
  ### 3.3 搜索(backend_search)
  
  | 并发 | 请求数 | 成功率 | 吞吐(RPS) | Avg(ms) | P95(ms) | Max(ms) |
  |-----:|-------:|-------:|----------:|--------:|--------:|--------:|
  | 1    | 160   | 100%  | 7.98      | 124.89 | 228.06 | 345.49 |
  | 5    | 161   | 100%  | 7.89      | 628.91 | 1271.49| 1441.02|
  | 10   | 181   | 100%  | 8.78      | 1129.23| 1295.88| 1330.96|
  | 20   | 161   | 100%  | 7.63      | 2594.00| 4706.44| 4783.05|
  
3abbc95a   tangwang   重构(scripts): 整理sc...
216
  **结论**:吞吐约 **8 rps** 平台化,延迟随并发上升明显,符合“检索 + 向量 + 重排”重链路特征。多租户补测(文档数 500–10000,见报告 §12)表明:文档数越大,RPS 下降、延迟升高;tenant 0(10000 doc)在并发 20 出现部分 ReadTimeout(成功率 59.02%),需注意 timeout 与容量规划;补测命令示例:`for t in 0 1 2 3 4; do .venv/bin/python benchmarks/perf_api_benchmark.py --scenario backend_search --concurrency-list 1,5,10,20 --duration 20 --tenant-id $t --output perf_reports/2026-03-12/search_tenant_matrix/tenant_${t}.json; done`
208e079a   tangwang   TODO
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  
  ---
  
  ### 3.4 Suggest(backend_suggest)
  
  | 并发 | 请求数 | 成功率 | 吞吐(RPS) | Avg(ms) | P95(ms) | Max(ms) |
  |-----:|-------:|-------:|----------:|--------:|--------:|--------:|
  | 1    | 3502  | 100%  | 175.09    | 5.68    | 8.70    | 15.98   |
  | 5    | 4168  | 100%  | 208.10    | 23.93   | 36.93   | 59.53   |
  | 10   | 4152  | 100%  | 207.25    | 48.05   | 59.45   | 127.20  |
  | 20   | 4190  | 100%  | 208.99    | 95.20   | 110.74  | 181.37  |
  
  **结论**:吞吐高且稳定(**约 200+ rps**),对并发友好,与 search/rerank 相比压力较小。
  
  ---
  
  ## 四、总结
  
  | 维度 | 要点 |
  |------|------|
  | **Embedding** | TEI 替代 SentenceTransformers/vLLM 作为文本向量后端,兼顾性能与工程化(Docker、配置化、T4 调优);图片向量由 clip-as-service 承担。 |
  | **Reranker** | vLLM + Qwen3-Reranker-0.6B,针对 T4 做 float16、prefix caching、CUDA 图、按长度分批及 batch/长度参数搜索;高并发场景可选用 DashScope 云后端。 |
  | **翻译** | 因 qwen-mt 限速(RPM≈60),迁移至可配置的 qwen-flash 等方案,支撑在线索引与 query;需金伟侧对索引做流量控制。 |
a3275468   tangwang   已把本仓库里的 `/indexer...
240
  | **内容理解** | 字段模型仍可被检索与 suggest 消费,但生成服务已迁移到独立项目;本仓库不再内置该实现。 |
208e079a   tangwang   TODO
241
242
243
244
245
  | **架构** | Provider 动态选择翻译;service_ctl 统一监控与拉起;suggest 目前全量脚本触发,增量待做。 |
  | **性能基线** | 向量化扩展性良好;reranker 为整链瓶颈(386 docs 约 0.6 rps);search 约 8 rps;suggest 约 200+ rps。 |
  
  **关键文件与复现**
  - 配置:`config/config.yaml`(services、rerank、query_config)、`.env`(端口与 API Key)。
3abbc95a   tangwang   重构(scripts): 整理sc...
246
  - 脚本:`scripts/service_ctl.sh`(启停与监控)、`benchmarks/perf_api_benchmark.py`(压测)、`scripts/build_suggestions.sh`(suggest 构建)。
208e079a   tangwang   TODO
247
  - 完整步骤与多租户/rerank 对比见:`docs/性能测试报告.md`