compliance/docs/DMS_Pagination_Feature.md
2025-08-18 23:56:08 +08:00

5.2 KiB
Raw Blame History

DMS分页功能实现文档

概述

为了解决当待测试的节点数量非常多时出现的内存溢出问题我们实现了DMS API的分页获取功能。原来的实现一次性获取所有数据pageSize=100000现在改为分页获取大大减少了内存使用。

问题背景

原始问题

MemoryError

原因分析

  • 原代码使用 pageSize=100000 一次性获取所有API数据
  • 当API数量很大时会导致内存溢出
  • JSON序列化大量数据时也会消耗大量内存

解决方案

1. 分页获取API列表

修改文件: ddms_compliance_suite/input_parser/parser.py

主要改进:

  • 添加 page_size 参数默认1000
  • 实现循环分页获取逻辑
  • 收集并返回分页统计信息
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]]]:

分页逻辑:

while True:
    list_url = urljoin(base_url, f"/api/schema/manage/schema?pageNo={page_no}&pageSize={page_size}")
    # 获取当前页数据
    # 检查是否还有更多页面
    # 更新分页统计信息

2. 分页信息收集

返回的分页信息:

{
    "page_size": 1000,
    "total_pages": 15,
    "total_records": 14523,
    "pages_fetched": 15
}

3. 命令行支持

修改文件: run_api_tests.py

新增参数:

--page-size 1000    # DMS API分页大小默认1000

使用示例:

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

配置参数:

{
    "dms": "./assets/doc/dms/domain.json",
    "base-url": "https://www.dev.ideas.cnpc",
    "page-size": 500,
    "ignore-ssl": true
}

响应格式:

{
    "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 很少 高性能环境

建议配置

开发环境:

--page-size 100    # 快速测试,减少内存使用

测试环境:

--page-size 500    # 平衡性能和内存

生产环境:

--page-size 1000   # 默认配置,性能最优

安全特性

防护机制

  1. 最大页数限制: 防止无限循环

    if page_no > 1000:  # 最多1000页
        logger.warning("Reached maximum page limit (1000), stopping pagination")
        break
    
  2. 空页面检测: 自动停止分页

    if not page_records:
        logger.info(f"No more records found on page {page_no}, stopping pagination")
        break
    
  3. 错误处理: 网络异常时的优雅降级

    except requests.exceptions.RequestException as e:
        self.logger.error(f"Failed to fetch API list from DMS: {e}")
        return None, {}
    

向后兼容性

  • 所有现有的调用方式仍然有效
  • page_size 参数是可选的默认值为1000
  • 不使用分页信息的代码不受影响

测试

测试脚本

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 字段的准确性

调试技巧

# 启用详细日志
python run_api_tests.py --dms ... --verbose

# 使用小分页测试
python run_api_tests.py --dms ... --page-size 10

未来改进

  1. 并行分页: 同时获取多个页面
  2. 缓存机制: 缓存已获取的页面数据
  3. 断点续传: 支持从中断点继续获取
  4. 压缩传输: 减少网络传输数据量