Skip to content

Commit 4327a02

Browse files
committed
fix fasthttpuser & update readme & add github link
1 parent ffa1470 commit 4327a02

File tree

16 files changed

+527
-181
lines changed

16 files changed

+527
-181
lines changed

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ LMeterX is a professional large language model performance testing platform that
1818

1919
## ✨ Core Features
2020

21-
- **Universal compatibility**: Supports any language/multimodal/CoT model (GPT/Claude/Llama, etc.) service API stress testing
22-
- **Smart load testing**: Precise concurrency control & Real user simulation
23-
- **Professional metrics**: TTFT, TPS, RPS, success/error rate, etc
24-
- **Multi-scenario support**: Text conversations & Multimodal (image+text) & Custom dataset
25-
- **Visualize the results**: Performance reports & AI Summary & Model arena
26-
- **Real-time monitoring**: Hierarchical monitoring of tasks and services
27-
- **Enterprise ready**: Docker deployment & Web management console & Scalable architecture
21+
- **Full Model Compatibility** - Supports mainstream LLMs like GPT, Claude, and Llama with one-click stress testing
22+
- **High-Load Stress Testing** - Simulates high-concurrency requests to accurately detect model performance limits
23+
- **Multi-Scenario Coverage** - Supports streaming/non-streaming, supports text/multimodal/custom datasets<sup>![NEW](https://img.shields.io/badge/NEW-brightgreen?style=flat-square)</sup>
24+
- **Professional Metrics** - Core performance metrics including first token latency, throughput(RPS、TPS), and success rate
25+
- **AI Smart Reports** - AI-powered performance analysis<sup>![NEW](https://img.shields.io/badge/NEW-brightgreen?style=flat-square)</sup>margin-left: 8px;">NEW</sup>, multi-dimensional model comparison and visualization
26+
- **Web Console** - One-stop management for task creation, stopping, status tracking, and full-chain log monitoring
27+
- **Enterprise-level Deployment** - Docker containerization with elastic scaling and distributed deployment support
2828

2929
## 🏗️ System Architecture
3030

3131
LMeterX adopts a microservices architecture design, consisting of four core components:
3232

33-
1. **Backend API Service**: FastAPI-based REST API service responsible for task management and result storage
33+
1. **Backend Service**: FastAPI-based REST API service responsible for task management and result storage
3434
2. **Load Testing Engine**: Locust-based load testing engine that executes actual performance testing tasks
3535
3. **Frontend Interface**: Modern Web interface based on React + TypeScript + Ant Design
3636
4. **MySQL Database**: Stores test tasks, result data, and configuration information
@@ -117,7 +117,6 @@ LMeterX/
117117
├── docker-compose.yml # Docker Compose configuration
118118
├── Makefile # Run complete code checks
119119
├── README.md # English README
120-
└── README_CN.md # Chinese README
121120
```
122121

123122
### Development Environment Setup
@@ -142,7 +141,7 @@ LMeterX/
142141
- [Deployment Guide](docs/DEPLOYMENT_GUIDE.md) - Detailed deployment instructions and configuration guide
143142
- [Contributing Guide](docs/CONTRIBUTING.md) - How to participate in project development and contribute code
144143

145-
## 🤝 Contributors
144+
## 👥 Contributors
146145

147146
Thanks to all developers who have contributed to the LMeterX project:
148147

@@ -154,5 +153,6 @@ Thanks to all developers who have contributed to the LMeterX project:
154153
This project is licensed under the [Apache 2.0 License](LICENSE).
155154

156155
---
157-
156+
<div align="center">
158157
**⭐ If this project helps you, please give us a Star! Your support is our motivation for continuous improvement.**
158+
</div>

README_CN.md

Lines changed: 59 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,24 @@ LMeterX 是一个专业的大语言模型性能测试平台,支持对 LLM 服
1616
<img src="docs/images/images.gif" alt="LMeterX Demo" width="700"/>
1717
</div>
1818

19-
## 核心功能
19+
## 核心特性
2020

21-
- **通用兼容性**:支持任何语言/多模态/CoT模型(GPT/Claude/Llama等)服务API压测
22-
- **智能负载测试**:精确并发控制 & 真实用户模拟
23-
- **专业性能指标**:TTFT、TPS、RPS、成功/错误率等
24-
- **多场景支持**:文本对话 & 多模态(图像+文本)& 自定义数据集
25-
- **可视化结果**:性能报告一键生成 & AI智能分析 & 多维度模型对比
26-
- **实时监控**:任务和服务的分层监控
27-
- **企业就绪**: Docker部署 & Web管理控制台 &可扩展架构
21+
- **全模型兼容** - 支持 GPTClaude、Llama 等主流大模型,一键发起压测
22+
- **高负载压测** - 模拟高并发请求,精准探测模型性能极限
23+
- **多场景覆盖** - 支持流式/非流式、文本/多模态/自定义数据集<sup>![NEW](https://img.shields.io/badge/NEW-brightgreen?style=flat-square)</sup>
24+
- **专业指标统计** - 首Token延迟、吞吐量(RPS、TPS)、成功率等核心性能指标
25+
- **AI智能报告** - AI智能分析报告<sup>![NEW](https://img.shields.io/badge/NEW-brightgreen?style=flat-square)</sup>,多维度多模型可视化结果对比
26+
- **Web控制台** - 提供任务创建、停止、状态跟踪、全链路日志监控等一站式管理
27+
- **企业级部署** - Docker容器化,支持弹性扩展与分布式部署
2828

2929
## 🏗️ 系统架构
3030

31-
LMeterX 采用微服务架构设计,由以下四个核心组件构成
31+
LMeterX 采用微服务架构,由四个核心组件构成
3232

33-
1. **后端 API 服务**:基于 FastAPI REST API 服务,负责任务管理和结果存储
34-
2. **压测引擎**:基于 Locust 的负载测试引擎,执行实际的性能测试任务
35-
3. **前端界面**:基于 React + TypeScript + Ant Design 的现代化 Web 界面
36-
4. **MySQL 数据库**存储测试任务、结果数据和配置信息
33+
- **后端API服务** - FastAPI REST API,负责任务管理和数据存储
34+
- **压测引擎** - Locust负载测试引擎,执行性能测试任务
35+
- **前端界面** - React + TypeScript + Ant Design 现代化Web界面
36+
- **MySQL数据库** - 存储测试任务、结果数据和配置信息
3737

3838
<div align="center">
3939
<img src="docs/images/tech-arch.png" alt="LMeterX tech arch" width="800"/>
@@ -54,80 +54,67 @@ LMeterX 采用微服务架构设计,由以下四个核心组件构成:
5454
使用预构建的 Docker 镜像,一键启动所有服务:
5555

5656
```bash
57-
# 下载并运行一键部署脚本
57+
# 一键启动所有服务
5858
curl -fsSL https://raw.githubusercontent.com/MigoXLab/LMeterX/main/quick-start.sh | bash
5959
```
6060

6161
### 使用指南
6262

63-
1. **访问 Web 界面**http://localhost:8080
64-
2. **创建测试任务**
65-
- 配置目标 API 地址和模型参数
66-
- 选择测试类型(文本对话/图文对话)
67-
- 设置并发用户数和测试持续时间
68-
- 配置其他高级参数(可选)
69-
3. **监控测试过程**:实时查看测试日志和性能指标
70-
4. **测试结果查看和导出**:查看详细的性能结果并导出报告
71-
5. **AI分析服务**:在系统配置页面配置AI服务后,可在任务结果页面对性能结果进行AI评估和总结
63+
1. **访问界面** - 打开 http://localhost:8080
64+
2. **创建任务** - 配置API地址、模型参数、测试类型
65+
3. **实时监控** - 查看测试日志和性能指标
66+
4. **结果分析** - 查看详细性能结果,导出报告
67+
5. **AI分析** - 配置AI服务后,获得智能性能评估
7268

7369
## 🔧 配置说明
7470

75-
### 环境变量配置
71+
### 环境变量
7672

77-
#### 通用配置
7873
```bash
79-
SECRET_KEY=your_secret_key_here # 应用安全密钥
80-
FLASK_DEBUG=false # 调试模式开关
81-
```
82-
83-
#### 数据库配置
84-
```bash
85-
DB_HOST=mysql # 数据库主机地址
86-
DB_PORT=3306 # 数据库端口
87-
DB_USER=lmeterx # 数据库用户名
88-
DB_PASSWORD=lmeterx_password # 数据库密码
89-
DB_NAME=lmeterx # 数据库名称
90-
```
91-
92-
#### 前端配置
93-
```bash
94-
VITE_API_BASE_URL=/api # API 基础路径
74+
# 通用配置
75+
SECRET_KEY=your_secret_key_here
76+
FLASK_DEBUG=false
77+
78+
# 数据库配置
79+
DB_HOST=mysql
80+
DB_PORT=3306
81+
DB_USER=lmeterx
82+
DB_PASSWORD=lmeterx_password
83+
DB_NAME=lmeterx
84+
85+
# 前端配置
86+
VITE_API_BASE_URL=/api
9587
```
9688

9789
## 🤝 开发指南
9890

99-
> 我们欢迎所有形式的贡献!请阅读我们的 [贡献指南](docs/CONTRIBUTING.md) 了解详情
91+
> 💡 **欢迎贡献**!查看 [贡献指南](docs/CONTRIBUTING.md) 了解详情
10092
10193
### 技术栈
10294

103-
LMeterX 采用现代化的技术栈,确保系统的可靠性和可维护性:
95+
- **后端** - Python + FastAPI + SQLAlchemy + MySQL
96+
- **压测引擎** - Python + Locust + 自定义扩展
97+
- **前端** - React + TypeScript + Ant Design + Vite
98+
- **部署** - Docker + Docker Compose + Nginx
10499

105-
- **后端服务**:Python + FastAPI + SQLAlchemy + MySQL
106-
- **压测引擎**:Python + Locust + 自定义扩展
107-
- **前端界面**:React + TypeScript + Ant Design + Vite
108-
- **部署运维**:Docker + Docker Compose + Nginx
109100

110-
### 项目结构
111-
112-
```LMeterX/
113-
├── backend/ # 后端服务
114-
├── st_engine/ # 压测引擎服务
115-
├── frontend/ # 前端服务
116-
├── docs/ # 文档目录
117-
├── docker-compose.yml # Docker Compose配置
118-
├── Makefile # 运行完整代码检查
119-
├── README.md # 英文README
120-
└── README_CN.md # 中文README
101+
```
102+
LMeterX/
103+
├── backend/ # 后端服务
104+
├── st_engine/ # 压测引擎
105+
├── frontend/ # 前端服务
106+
├── docs/ # 文档
107+
├── docker-compose.yml
108+
└── README_CN.md # 中文说明
121109
```
122110

123111
### 开发环境搭建
124112

125-
1. **Fork 项目**到您的 GitHub 账户
126-
2. **克隆您的 Fork**,创建开发分支进行开发
127-
3. **遵循代码规范**,使用清晰的提交信息(遵循约定式提交规范)
128-
4. **运行代码检查**:在提交 PR 之前,确保代码检查、格式化和测试均已通过,可执行 `make all`
129-
5. **编写清晰文档**:为新功能或变更撰写相应的文档
130-
6. **积极参与 Review**:在审核过程中积极响应反馈
113+
1. **Fork项目** → 克隆到本地
114+
2. **创建分支** → 进行功能开发
115+
3. **代码检查** → 运行 `make all` 确保质量
116+
4. **提交PR** → 遵循约定式提交规范
117+
5. **文档更新** → 为新功能撰写文档
131118

132119
## 🗺️ 发展路线图
133120

@@ -139,12 +126,12 @@ LMeterX 采用现代化的技术栈,确保系统的可靠性和可维护性:
139126

140127
## 📚 相关文档
141128

142-
- [部署指南](docs/DEPLOYMENT_GUIDE_CN.md) - 详细的部署说明和配置指南
143-
- [贡献指南](docs/CONTRIBUTING.md) - 如何参与项目开发和贡献代码
129+
- [部署指南](docs/DEPLOYMENT_GUIDE_CN.md) - 详细部署说明
130+
- [贡献指南](docs/CONTRIBUTING.md) - 参与开发指南
144131

145-
## 🤝 贡献者
132+
## 👥 贡献者
146133

147-
感谢所有为 LMeterX 项目做出贡献的开发者
134+
感谢所有为 LMeterX 做出贡献的开发者
148135

149136
- [@LuckyYC](https://github.com/LuckyYC) - 项目维护者 & 核心开发者
150137
- [@del-zhenwu](https://github.com/del-zhenwu) - 核心开发者
@@ -155,4 +142,8 @@ LMeterX 采用现代化的技术栈,确保系统的可靠性和可维护性:
155142

156143
---
157144

145+
<div align="center">
146+
158147
**⭐ 如果这个项目对您有帮助,请给我们一个 Star!您的支持是我们持续改进的动力。**
148+
149+
</div>

backend/service/analysis_service.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ async def analyze_task_svc(
7878
try:
7979
ai_config = await get_ai_service_config_internal_svc(request)
8080
except HTTPException as e:
81-
error_msg = (
82-
f"Failed to get AI service configuration for task {task_id}: {str(e)}"
83-
)
81+
error_msg = f"Failed to get AI service configuration. {str(e)}"
8482
logger.error(error_msg, exc_info=True)
8583
return AnalysisResponse(
8684
task_id=task_id,

backend/service/task_service.py

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import json
77
import os
8+
import ssl
89
import time
910
import uuid
1011
from typing import Dict, List, Optional, Tuple, Union
@@ -831,6 +832,77 @@ def _prepare_request_payload(body: TaskCreateReq) -> Dict:
831832
raise ValueError("Request payload is required for custom API endpoints")
832833

833834

835+
def _validate_certificate_files(
836+
cert_file: str, key_file: Optional[str]
837+
) -> Tuple[bool, str]:
838+
"""
839+
Validate certificate files.
840+
"""
841+
try:
842+
if not cert_file:
843+
return False, "No certificate file provided"
844+
845+
def _exists(path: str) -> bool:
846+
return isinstance(path, str) and len(path) > 0 and os.path.exists(path)
847+
848+
def _is_pkcs12(path: str) -> bool:
849+
lower = path.lower()
850+
return lower.endswith(".p12") or lower.endswith(".pfx")
851+
852+
def _read(path: str) -> str:
853+
try:
854+
with open(path, "r", encoding="utf-8", errors="ignore") as f:
855+
return f.read()
856+
except Exception:
857+
return ""
858+
859+
if not _exists(cert_file):
860+
return False, f"Certificate file does not exist: {cert_file}"
861+
if _is_pkcs12(cert_file):
862+
return (
863+
False,
864+
"P12/PFX certificates are not supported, please convert to a PEM file containing the private key",
865+
)
866+
867+
cert_text = _read(cert_file)
868+
if "BEGIN CERTIFICATE" not in cert_text:
869+
return (
870+
False,
871+
"Certificate file is not a valid PEM format (missing BEGIN CERTIFICATE)",
872+
)
873+
874+
if key_file:
875+
if not _exists(key_file):
876+
return False, f"Private key file does not exist: {key_file}"
877+
if _is_pkcs12(key_file):
878+
return (
879+
False,
880+
"Private key file cannot be P12/PFX, please provide a PEM private key",
881+
)
882+
key_text = _read(key_file)
883+
if (
884+
"BEGIN PRIVATE KEY" not in key_text
885+
and "BEGIN RSA PRIVATE KEY" not in key_text
886+
and "BEGIN EC PRIVATE KEY" not in key_text
887+
):
888+
return False, "Private key file is not a valid PEM private key"
889+
else:
890+
# 仅提供了一个 cert_file,需同时包含证书+私钥
891+
if (
892+
"BEGIN PRIVATE KEY" not in cert_text
893+
and "BEGIN RSA PRIVATE KEY" not in cert_text
894+
and "BEGIN EC PRIVATE KEY" not in cert_text
895+
):
896+
return (
897+
False,
898+
"Only a certificate file was provided, but it does not contain a private key, please upload the private key or provide a merged PEM file",
899+
)
900+
901+
return True, ""
902+
except Exception as e:
903+
return False, f"Certificate validation error: {str(e)}"
904+
905+
834906
def _prepare_client_cert(body: TaskCreateReq):
835907
"""Prepare SSL certificate configuration for the HTTP client."""
836908
client_cert: Optional[Union[str, Tuple[str, str]]] = None
@@ -841,14 +913,17 @@ def _prepare_client_cert(body: TaskCreateReq):
841913
# Use absolute paths directly from upload service
842914
if cert_file or key_file:
843915
try:
916+
is_valid, err_msg = _validate_certificate_files(cert_file, key_file or None)
917+
if not is_valid:
918+
logger.error(f"Invalid client certificate configuration: {err_msg}")
919+
return None
920+
844921
if cert_file and key_file:
845922
# Both cert and key files provided
846-
if os.path.exists(cert_file) and os.path.exists(key_file):
847-
client_cert = (cert_file, key_file)
923+
client_cert = (cert_file, key_file)
848924
elif cert_file:
849925
# Only cert file provided (combined cert+key file)
850-
if os.path.exists(cert_file):
851-
client_cert = cert_file
926+
client_cert = cert_file
852927
except Exception as e:
853928
logger.error(f"Error preparing certificate configuration: {e}")
854929
return None
@@ -950,6 +1025,21 @@ async def test_api_endpoint_svc(request: Request, body: TaskCreateReq):
9501025
)
9511026
return await _handle_non_streaming_response(response)
9521027

1028+
except ssl.SSLError as e:
1029+
msg = str(e)
1030+
hint = ""
1031+
if "PEM lib" in msg or "PEM routines" in msg:
1032+
hint = "Client certificate/private key format error: only PEM is supported. Please upload a PEM file containing the private key, or provide both PEM certificate and PEM private key; P12/PFX is not supported."
1033+
elif "no certificate or crl found" in msg:
1034+
hint = (
1035+
"No valid certificate content found, please confirm the file is correct"
1036+
)
1037+
logger.error(f"SSL error when testing API endpoint: {e}")
1038+
return {
1039+
"status": "error",
1040+
"error": f"SSL error: {msg}. {hint}",
1041+
"response": None,
1042+
}
9531043
except httpx.TimeoutException as e:
9541044
logger.error(f"Request timeout when testing API endpoint: {e}")
9551045
return {

0 commit comments

Comments
 (0)