229 lines
5.2 KiB
Markdown
229 lines
5.2 KiB
Markdown
# DMS分页功能实现文档
|
||
|
||
## 概述
|
||
|
||
为了解决当待测试的节点数量非常多时出现的内存溢出问题,我们实现了DMS API的分页获取功能。原来的实现一次性获取所有数据(pageSize=100000),现在改为分页获取,大大减少了内存使用。
|
||
|
||
## 问题背景
|
||
|
||
### 原始问题
|
||
```
|
||
MemoryError
|
||
```
|
||
|
||
### 原因分析
|
||
- 原代码使用 `pageSize=100000` 一次性获取所有API数据
|
||
- 当API数量很大时,会导致内存溢出
|
||
- JSON序列化大量数据时也会消耗大量内存
|
||
|
||
## 解决方案
|
||
|
||
### 1. 分页获取API列表
|
||
|
||
**修改文件**: `ddms_compliance_suite/input_parser/parser.py`
|
||
|
||
**主要改进**:
|
||
- 添加 `page_size` 参数(默认1000)
|
||
- 实现循环分页获取逻辑
|
||
- 收集并返回分页统计信息
|
||
|
||
```python
|
||
def parse_dms_spec(self, domain_mapping_path: str, base_url: str,
|
||
headers: Optional[Dict[str, str]] = None,
|
||
ignore_ssl: bool = False,
|
||
page_size: int = 1000) -> Optional[Tuple[ParsedDMSSpec, Dict[str, Any]]]:
|
||
```
|
||
|
||
**分页逻辑**:
|
||
```python
|
||
while True:
|
||
list_url = urljoin(base_url, f"/api/schema/manage/schema?pageNo={page_no}&pageSize={page_size}")
|
||
# 获取当前页数据
|
||
# 检查是否还有更多页面
|
||
# 更新分页统计信息
|
||
```
|
||
|
||
### 2. 分页信息收集
|
||
|
||
**返回的分页信息**:
|
||
```json
|
||
{
|
||
"page_size": 1000,
|
||
"total_pages": 15,
|
||
"total_records": 14523,
|
||
"pages_fetched": 15
|
||
}
|
||
```
|
||
|
||
### 3. 命令行支持
|
||
|
||
**修改文件**: `run_api_tests.py`
|
||
|
||
**新增参数**:
|
||
```bash
|
||
--page-size 1000 # DMS API分页大小,默认1000
|
||
```
|
||
|
||
**使用示例**:
|
||
```bash
|
||
python run_api_tests.py \
|
||
--dms ./assets/doc/dms/domain.json \
|
||
--base-url https://www.dev.ideas.cnpc \
|
||
--page-size 500 \
|
||
--ignore-ssl
|
||
```
|
||
|
||
### 4. API服务器支持
|
||
|
||
**修改文件**: `api_server.py`
|
||
|
||
**配置参数**:
|
||
```json
|
||
{
|
||
"dms": "./assets/doc/dms/domain.json",
|
||
"base-url": "https://www.dev.ideas.cnpc",
|
||
"page-size": 500,
|
||
"ignore-ssl": true
|
||
}
|
||
```
|
||
|
||
**响应格式**:
|
||
```json
|
||
{
|
||
"status": "completed",
|
||
"message": "Tests finished.",
|
||
"report_directory": "/path/to/reports",
|
||
"summary": { ... },
|
||
"pagination": {
|
||
"page_size": 500,
|
||
"total_pages": 30,
|
||
"total_records": 14523,
|
||
"pages_fetched": 30
|
||
}
|
||
}
|
||
```
|
||
|
||
## 性能优化
|
||
|
||
### 内存使用对比
|
||
|
||
| 分页大小 | 估算内存使用 | 请求次数 | 推荐场景 |
|
||
|---------|-------------|---------|----------|
|
||
| 100 | ~10MB | 多 | 内存受限环境 |
|
||
| 500 | ~50MB | 中等 | 平衡选择 |
|
||
| 1000 | ~100MB | 较少 | 默认推荐 |
|
||
| 5000 | ~500MB | 很少 | 高性能环境 |
|
||
|
||
### 建议配置
|
||
|
||
**开发环境**:
|
||
```bash
|
||
--page-size 100 # 快速测试,减少内存使用
|
||
```
|
||
|
||
**测试环境**:
|
||
```bash
|
||
--page-size 500 # 平衡性能和内存
|
||
```
|
||
|
||
**生产环境**:
|
||
```bash
|
||
--page-size 1000 # 默认配置,性能最优
|
||
```
|
||
|
||
## 安全特性
|
||
|
||
### 防护机制
|
||
|
||
1. **最大页数限制**: 防止无限循环
|
||
```python
|
||
if page_no > 1000: # 最多1000页
|
||
logger.warning("Reached maximum page limit (1000), stopping pagination")
|
||
break
|
||
```
|
||
|
||
2. **空页面检测**: 自动停止分页
|
||
```python
|
||
if not page_records:
|
||
logger.info(f"No more records found on page {page_no}, stopping pagination")
|
||
break
|
||
```
|
||
|
||
3. **错误处理**: 网络异常时的优雅降级
|
||
```python
|
||
except requests.exceptions.RequestException as e:
|
||
self.logger.error(f"Failed to fetch API list from DMS: {e}")
|
||
return None, {}
|
||
```
|
||
|
||
## 向后兼容性
|
||
|
||
- 所有现有的调用方式仍然有效
|
||
- `page_size` 参数是可选的,默认值为1000
|
||
- 不使用分页信息的代码不受影响
|
||
|
||
## 测试
|
||
|
||
### 测试脚本
|
||
```bash
|
||
python test_pagination.py # 基本分页测试
|
||
python test_pagination.py --api-server # API服务器集成测试
|
||
```
|
||
|
||
### 验证要点
|
||
1. 分页获取的总记录数与一次性获取相同
|
||
2. 内存使用显著降低
|
||
3. 分页信息准确反映获取状态
|
||
4. 网络异常时能正确处理
|
||
|
||
## 监控和日志
|
||
|
||
### 日志输出示例
|
||
```
|
||
[INFO] Fetching API list with pagination (page_size=1000)
|
||
[INFO] Fetched 1000 records from page 1, total: 1000
|
||
[INFO] Fetched 1000 records from page 2, total: 2000
|
||
[INFO] Fetched 523 records from page 15, total: 14523
|
||
[INFO] Reached end of data. Total records: 14523
|
||
[INFO] DMS分页信息: 总记录数=14523, 页面大小=1000, 获取页数=15/15
|
||
```
|
||
|
||
### 性能指标
|
||
- 总记录数
|
||
- 分页大小
|
||
- 获取页数
|
||
- 估算内存使用
|
||
- 网络请求次数
|
||
|
||
## 故障排除
|
||
|
||
### 常见问题
|
||
|
||
1. **内存仍然不足**
|
||
- 减小 `page_size` 值(如100或50)
|
||
- 检查其他内存消耗源
|
||
|
||
2. **网络超时**
|
||
- 增加请求超时时间
|
||
- 检查网络连接稳定性
|
||
|
||
3. **分页信息不准确**
|
||
- 检查DMS API响应格式
|
||
- 验证 `total` 字段的准确性
|
||
|
||
### 调试技巧
|
||
```bash
|
||
# 启用详细日志
|
||
python run_api_tests.py --dms ... --verbose
|
||
|
||
# 使用小分页测试
|
||
python run_api_tests.py --dms ... --page-size 10
|
||
```
|
||
|
||
## 未来改进
|
||
|
||
1. **并行分页**: 同时获取多个页面
|
||
2. **缓存机制**: 缓存已获取的页面数据
|
||
3. **断点续传**: 支持从中断点继续获取
|
||
4. **压缩传输**: 减少网络传输数据量
|