139 lines
4.8 KiB
Markdown
139 lines
4.8 KiB
Markdown
# A2A 智能网关(gateway)
|
||
|
||
基于设计文档《A2A需求分析-网关-K8s全链路架构详细设计方案》实现的智能网关核心服务。
|
||
|
||
本期范围:**网关核心 + 可视化运维后台**。Agent/CLI 为预留接口,K8s 算力层不实际部署。
|
||
|
||
## 技术栈
|
||
|
||
- 后端:Python + FastAPI + Uvicorn + redis-py(asyncio)
|
||
- 存储:Redis(任务池 / Agent 池 / 调度索引 / 心跳 ZSet / 审计日志)
|
||
- 前端:Vue 3 + Vite + Element Plus(完整运维后台)
|
||
- 后台任务:asyncio 循环(心跳扫描 / 调度 / 超时检查),配 Redis 分布式锁防多实例重复执行
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
gateway/
|
||
├── docker-compose.yml # 本地一键启动 Redis
|
||
├── requirements.txt # Python 依赖
|
||
├── .env.example # 环境变量示例
|
||
├── backend/
|
||
│ ├── app/
|
||
│ │ ├── main.py # FastAPI 入口
|
||
│ │ ├── config.py # 配置
|
||
│ │ ├── constants.py # Redis 键名/TTL/状态常量
|
||
│ │ ├── models/schemas.py # Pydantic 模型
|
||
│ │ ├── repository/ # Redis 存储层(task/agent/log)
|
||
│ │ ├── services/ # 业务服务(任务/Agent/调度/心跳/通信/超时/锁)
|
||
│ │ ├── api/ # 路由(cli/agent/admin)
|
||
│ │ ├── middleware.py # 日志中间件
|
||
│ │ └── scheduler_loop.py # 后台任务循环
|
||
│ └── tests/ # 单元与集成测试
|
||
└── frontend/ # Vue3 + Element Plus 运维后台
|
||
```
|
||
|
||
## 快速启动
|
||
|
||
### 1. 启动 Redis
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
无 Docker 时需本机提供 Redis 实例,并设置 `REDIS_URL`。
|
||
|
||
### 2. 启动后端
|
||
|
||
```bash
|
||
cd backend
|
||
pip install -r ../requirements.txt
|
||
# 复制 .env.example 为 .env 并按需修改
|
||
uvicorn app.main:app --host 0.0.0.0 --port 8000
|
||
```
|
||
|
||
接口文档(Swagger):http://localhost:8000/docs
|
||
|
||
### 3. 启动前端运维后台
|
||
|
||
```bash
|
||
cd frontend
|
||
# 使用 Node >= 18(推荐 18/20/22)
|
||
npm install
|
||
npm run dev
|
||
```
|
||
|
||
访问 http://localhost:5173 ,Vite 已将 `/api` 代理到后端 `:8000`。
|
||
|
||
### 4. 运行后端测试
|
||
|
||
```bash
|
||
cd backend
|
||
python -m pytest -q
|
||
```
|
||
|
||
## 核心机制
|
||
|
||
### 任务池(Redis)
|
||
|
||
- `task:info:{request_id}`:任务全量信息(Hash)
|
||
- `task:pending` / `task:running`:调度状态索引(Set)
|
||
- 状态流转:pending → running → success/failed
|
||
- TTL 默认 24h 自动归档;RequestID 幂等去重
|
||
|
||
### Agent 池(Redis)
|
||
|
||
- `agent:info:{agent_id}`:Agent 信息(Hash)
|
||
- `agent:heartbeat`:心跳时间戳(ZSet,score=最后心跳)
|
||
- `agent:tag:{tag}`:能力标签索引(Set)
|
||
- 心跳保活:网关每 60s 扫描,连续 120s 未心跳标记 offline
|
||
|
||
### 规则调度
|
||
|
||
标签精准匹配 → 负载过滤(当前负载 < 并发上限)→ 最低负载(停留时间久者优先)→ 绑定 Agent 并下发。
|
||
|
||
### 认证
|
||
|
||
CLI 提交任务与 Agent 注册时,请求体必须携带 `auth` 字段,值须与网关配置的 `GATEWAY_AUTH`(`.env` 中设置)一致,否则返回 `401`。示例:
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8000/api/cli/tasks \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"auth": "<GATEWAY_AUTH>", "task_type": "compile", "task_tags": ["build"], "payload": {"cmd": "python -m build"}}'
|
||
```
|
||
|
||
### 预留 Agent 协议接口
|
||
|
||
> 所有接口中 `register` 必须携带 `auth` 字段,其余接口以已注册的 `agent_id` 关联身份。
|
||
|
||
| 接口 | 说明 |
|
||
| --- | --- |
|
||
| `POST /api/agent/register` | Agent 启动注册(`auth` + 能力标签、并发上限、地址) |
|
||
| `POST /api/agent/unregister` | 优雅注销 |
|
||
| `POST /api/agent/heartbeat` | 心跳(约每 10s,同步负载) |
|
||
| `POST /api/agent/result` | 任务结果回传 |
|
||
|
||
### 通信中转
|
||
|
||
以 `RequestID + AgentID` 双维度关联 CLI 会话与 Agent,正向下发任务指令、反向回传进度与结果。本期为状态机闭环 + 日志记录,实际网络下发由 Agent 接入时扩展。
|
||
|
||
## 运维后台
|
||
|
||
- 任务管理:列表 / 筛选 / 详情 / 进度 / 取消
|
||
- Agent 管理:卡片网格 / 标签 / 负载 / 心跳 / 离线高亮
|
||
- 日志审计:全链路时间线,按 RequestID / AgentID 筛选
|
||
- 手动管控:取消任务 / 重置任务 / 下线 Agent
|
||
|
||
## 环境变量
|
||
|
||
见 `.env.example`,关键参数:
|
||
|
||
| 变量 | 默认 | 说明 |
|
||
| --- | --- | --- |
|
||
| `REDIS_URL` | `redis://localhost:6379/0` | Redis 连接 |
|
||
| `HEARTBEAT_SCAN_INTERVAL` | `60` | 心跳扫描间隔(秒) |
|
||
| `AGENT_HEARTBEAT_TIMEOUT` | `120` | 心跳超时剔除阈值(秒) |
|
||
| `DISPATCH_INTERVAL` | `2` | 调度循环间隔(秒) |
|
||
| `TASK_TIMEOUT_CHECK_INTERVAL` | `5` | 任务超时检查间隔(秒) |
|
||
| `DEFAULT_TASK_TIMEOUT` | `3600` | 任务默认超时(秒) |
|
||
| `TASK_TTL` | `86400` | 任务数据保留 TTL(秒) | |