Skip to content

后端 API 参考文档 (Backend API Reference)

本文档提供后端接口的快速参考。完整 API 手册请参阅 02-api-reference-full.md

基本信息:

  • Base URL: http://localhost:8000 (默认)
  • Content-Type: application/json
  • 当前版本: v0.1.0

1. 核心流程 (Usage Workflow)

使用本后端进行仿真实验的标准流程:

  1. 检查健康状态: GET /health 确保数据库和 UNET 适配器正常。
  2. 发现场景: GET /scenarios 获取可用的场景文件列表(DB + YAML 合并)。
  3. 创建运行 (Run): POST /runs 提交场景与策略配置,获得 run_id
  4. 启动运行: POST /runs/{run_id}/start 触发后台执行。
  5. 实时监控:
    • 连接 WS /ws/runs/{run_id} 接收进度与指标推送;
    • 或轮询 GET /runs/{run_id}/status 获取实时状态。
  6. 查询结果:
    • GET /runs/{run_id} 查看运行详情与摘要。
    • GET /runs/{run_id}/metrics 查看统计指标。
    • GET /runs/{run_id}/traces 查看通信链路记录。
    • GET /runs/{run_id}/artifacts 查看/下载运行产物。
    • GET /runs/{run_id}/events 查看运行事件日志。
  7. 停止运行: POST /runs/{run_id}/stop (可选,若未自动结束)。

2. 接口概览 (Endpoints Summary)

2.1 系统与资源

检查健康状态 (Health Check)

GET /health

返回服务全局健康状态,包括数据库、适配器、节点 TCP 可达性及深度检查。

Response (200 OK) — 对应 HealthResponse 模型:

json
{
  "status": "healthy",
  "checks": {
    "api": { "ok": true },
    "database": { "ok": true, "detail": null }
  },
  "healthy_nodes": 3,
  "total_nodes": 3,
  "db": {
    "ok": true,
    "tables": { "dt_runs": true, "dt_run_summary": true, "dt_run_events": true },
    "detail": null
  },
  "adapter": {
    "ok": true,
    "backend": "fjagepy",
    "detail": null,
    "unet_host": "198.144.181.94",
    "unet_port": 1100,
    "node_endpoints": [
      { "node": "A", "endpoint": "tcp://198.144.181.94:1101", "reachable": true, "detail": null }
    ]
  },
  "nodes": [
    {
      "node_id": 1,
      "name": "A",
      "ok": true,
      "phy_ok": true,
      "agents": 5,
      "services": ["phy", "node_info", "transport"],
      "unet_addr": 1,
      "detail": null
    }
  ]
}

节点健康检查 (Node Health)

GET /health/nodes

仅返回节点层面的深度检查结果(网关连接 + probe + PHY)。

Response (200 OK) — 对应 NodeHealthResponse 模型:

json
{
  "status": "healthy",
  "nodes": [
    {
      "node_id": 1,
      "name": "A",
      "ok": true,
      "phy_ok": true,
      "agents": 5,
      "services": ["phy", "node_info"],
      "unet_addr": 1,
      "detail": null
    }
  ],
  "healthy_count": 3,
  "total_count": 3
}

获取系统配置 (Get Config)

GET /config

Response (200 OK) — 对应 ConfigResponse 模型:

json
{
  "unet_host": "198.144.181.94",
  "unet_port": 1100,
  "node_endpoints": [
    { "node": "A", "endpoint": "tcp://198.144.181.94:1101" }
  ],
  "location_init": {
    "enabled": true,
    "mode": "fail_fast",
    "script_path": "scripts/unet_test_location.py",
    "timeout_seconds": 30.0
  },
  "db_url_masked": "mysql+pymysql://xiaokai:***@usw-cynosdbmysql-grp-rj8i8a3n.sql.tencentcdb.com:25567/unet_dt",
  "adapter_backend": "fjagepy"
}

获取策略列表 (List Strategies)

GET /strategies

Response (200 OK) — 对应 StrategyListResponse 模型:

json
{
  "items": [
    { "id": "round_robin", "name": "Round Robin" },
    { "id": "adaptive_qos", "name": "Adaptive QoS" }
  ],
  "total": 2
}

2.2 场景管理 (Scenario Management)

获取场景列表 (List Scenarios)

GET /scenarios

合并数据库与本地 YAML 两种来源的场景。

Response (200 OK) — 对应 ScenarioMergedListResponse 模型:

json
{
  "items": [
    {
      "id": "demo_line3",
      "name": "3节点线性拓扑",
      "source": "yaml",
      "created_at": null,
      "updated_at": null
    },
    {
      "id": "custom-scene-01",
      "name": "自定义场景",
      "source": "db",
      "created_at": "2026-02-15T10:00:00",
      "updated_at": "2026-02-16T12:00:00"
    }
  ],
  "total": 2
}

获取场景详情 (Get Scenario)

GET /scenarios/{scenario_id}

Response (200 OK) — 对应 ScenarioFullResponse 模型:

json
{
  "id": "demo_line3",
  "name": "3节点线性拓扑",
  "nodes": [
    { "id": 1, "name": "A", "position": [0, 0], "tcp": "tcp://198.144.181.94:1101" }
  ],
  "traffic": [
    { "flow_id": "f1", "src": 1, "dst": 2, "period_ms": 1000, "payload_bytes": 64 }
  ],
  "run": { "seed": 42, "dt_seconds": 1.0, "steps": 60, "output_dir": "runs" },
  "unet": null,
  "source": "yaml",
  "created_at": null,
  "updated_at": null
}

创建场景 (Create Scenario)

POST /scenarios

Request Body — 对应 ScenarioCreateRequest

json
{
  "id": "my-scenario",
  "name": "自定义场景",
  "nodes": [{ "id": 1, "name": "A", "position": [0, 0], "tcp": null }],
  "traffic": [{ "flow_id": "f1", "src": 1, "dst": 2, "period_ms": 1000, "payload_bytes": 64 }],
  "run": { "seed": 42, "dt_seconds": 1.0, "steps": 60, "output_dir": "runs" }
}

Response (201 Created) — 返回 ScenarioFullResponse

更新场景 (Update Scenario)

PUT /scenarios/{scenario_id}

Request Body — 对应 ScenarioUpdateRequest(所有字段可选)。

Response (200 OK) — 返回 ScenarioFullResponse

删除场景 (Delete Scenario)

DELETE /scenarios/{scenario_id}

Response: 204 No Content

导入场景 (Import from YAML)

POST /scenarios/import

json
{ "yaml_path": "scenarios/demo_line3.yaml" }

导出场景 (Export to YAML)

POST /scenarios/{scenario_id}/export

Response (200 OK)

json
{ "scenario_id": "my-scenario", "output_path": "scenarios/my-scenario.yaml" }

2.3 运行管理 (Run Management)

创建运行 (Create Run)

POST /runs

Request Body — 对应 RunCreateRequest

json
{
  "scenario_id": "demo_line3",
  "strategy_id": "round_robin",
  "mode": "mock",
  "steps": 100,
  "dt_seconds": 1.0,
  "seed": 42,
  "run_id": "my-run-001"
}

Response (201 Created) — 对应 RunItem

json
{
  "id": "my-run-001",
  "scenario_id": "demo_line3",
  "strategy_id": "round_robin",
  "mode": "mock",
  "status": "created",
  "steps": 100,
  "current_step": 0,
  "dt_seconds": 1.0,
  "seed": 42,
  "created_at": "2026-02-11T10:00:00",
  "started_at": null,
  "finished_at": null,
  "output_dir": null,
  "error_message": null
}

获取运行列表 (List Runs)

GET /runs?limit=50&offset=0

Response (200 OK) — 对应 RunListResponse

json
{
  "items": [/* RunItem[] */],
  "limit": 50,
  "offset": 0
}

获取运行详情 (Get Run Detail)

GET /runs/{run_id}

Response (200 OK) — 对应 RunDetailResponse

json
{
  "run": { /* RunItem */ },
  "summary": {
    "run_id": "my-run-001",
    "avg_throughput_bps": 850.5,
    "avg_loss_rate": 0.05,
    "p95_delay_ms": 120.0,
    "trace_count": 100,
    "received_count": 95,
    "updated_at": "2026-02-11T10:05:00"
  }
}

获取运行实时状态 (Get Run Status)

GET /runs/{run_id}/status

用于前端轮询替代 WebSocket。

Response (200 OK) — 对应 RunStatusResponse

json
{
  "run": { /* RunItem */ },
  "summary": { /* RunSummaryItem | null */ },
  "current_step": 50,
  "total_steps": 100,
  "latest_metrics": {
    "step_id": 50,
    "t_window_start_ms": 49000,
    "t_window_end_ms": 50000,
    "throughput_bps": 1024.0,
    "loss_rate": 0.02,
    "delay_p50_ms": 45.0,
    "delay_p95_ms": 95.0,
    "sent_count": 10,
    "recv_count": 9,
    "sync_error_ms": 1.2,
    "overhead_ms": 3.5
  }
}

启动 / 停止运行

  • POST /runs/{run_id}/start → 返回 RunItem
  • POST /runs/{run_id}/stop → 返回 RunItem

2.4 数据查询 (Artifacts)

获取指标 (Get Metrics)

GET /runs/{run_id}/metrics

Response (200 OK) — 对应 RunMetricsResponse

json
{
  "run_id": "my-run-001",
  "status": "finished",
  "artifact_dir": "runs/my-run-001",
  "source_file": "metrics.csv",
  "count": 100,
  "items": [
    {
      "step_id": 1,
      "t_window_start_ms": 0,
      "t_window_end_ms": 1000,
      "throughput_bps": 1024.0,
      "loss_rate": 0.0,
      "delay_p50_ms": 40.0,
      "delay_p95_ms": 50.0,
      "sent_count": 5,
      "recv_count": 5,
      "sync_error_ms": 0.5,
      "overhead_ms": 2.0
    }
  ]
}

获取链路追踪 (Get Traces)

GET /runs/{run_id}/traces?limit=200&offset=0

Response (200 OK) — 对应 RunTracesResponse

json
{
  "run_id": "my-run-001",
  "status": "finished",
  "artifact_dir": "runs/my-run-001",
  "source_file": "traces.csv",
  "total": 1500,
  "limit": 200,
  "offset": 0,
  "items": [
    {
      "run_id": "my-run-001",
      "step_id": 5,
      "seq": 101,
      "tx_time_ms": 5000,
      "src": 1,
      "dst": 2,
      "rx_time_ms": 5120,
      "payload_bytes": 64,
      "received": true,
      "source": "csv"
    }
  ]
}

获取运行产物 (Get Artifacts)

GET /runs/{run_id}/artifacts

Response (200 OK) — 对应 RunArtifactsResponse

json
{
  "run_id": "my-run-001",
  "artifact_dir": "runs/my-run-001",
  "files": [
    { "filename": "traces.csv", "exists": true, "size_bytes": 45678, "download_url": "/runs/my-run-001/artifacts/traces.csv" },
    { "filename": "metrics.csv", "exists": true, "size_bytes": 12345, "download_url": "/runs/my-run-001/artifacts/metrics.csv" },
    { "filename": "report.md", "exists": true, "size_bytes": 2048, "download_url": "/runs/my-run-001/artifacts/report.md" }
  ]
}

下载产物文件

GET /runs/{run_id}/artifacts/{filename}

支持的文件名:traces.csvmetrics.csvreport.mdscenario.yamlstrategy.jsonversions.json

获取运行事件 (Get Events)

GET /runs/{run_id}/events?limit=200&offset=0

Response (200 OK) — 对应 RunEventsResponse

json
{
  "run_id": "my-run-001",
  "items": [
    {
      "id": 1,
      "run_id": "my-run-001",
      "event_type": "state_change",
      "step_id": null,
      "payload": { "old_state": "created", "new_state": "running" },
      "created_at": "2026-02-11T10:00:05"
    }
  ],
  "total": 1
}

2.5 配置管理

手动触发位置初始化

POST /config/location-init/run

Response (200 OK) — 对应 LocationInitRunResponse

json
{
  "enabled": true,
  "ok": true,
  "skipped": false,
  "mode": "fail_fast",
  "command": ["python", "scripts/unet_test_location.py", "--scenario", "scenarios/demo_line3.yaml"],
  "return_code": 0,
  "stdout": "total=3, ok=3, failed=0",
  "stderr": "",
  "duration_ms": 1500,
  "warning": null
}

3. 实时推送 (WebSocket)

URL: ws://localhost:8000/ws/runs/{run_id}

建立连接后,服务器会推送 JSON 格式的事件流。

事件信封 (Event Envelope)

所有消息均遵循以下格式(对应 RunEventEnvelope):

json
{
  "type": "state",
  "run_id": "my-run-001",
  "ts_ms": 1700000000123,
  "payload": { ... }
}

事件类型 (Event Types)

type说明payload 字段
state状态变更id, status, scenario_id, strategy_id, mode, steps, ...
step仿真步进step_id, progress_percent
schedule调度决策策略相关字段
metrics实时指标avg_throughput_bps, avg_loss_rate, p95_delay_ms, ...
sync时间同步信息同步相关字段
artifacts产物生成完成文件信息

连接时自动推送当前 statemetrics 快照。


4. 常见错误码

状态码说明
400 Bad Request无效的请求参数(如非法的产物文件名)
404 Not Found请求的资源(Run ID, Scenario ID, Artifact)不存在
409 Conflict当前状态不允许执行该操作(如对 finished 的运行再次 start
422 Unprocessable Entity参数校验失败(如 JSON 格式错误、必填项缺失)
500 Internal Server Error服务器内部异常,请检查后端日志