Compare commits

...

12 Commits

@ -1,81 +0,0 @@
# 后端联调指南
## 环境与代理
- 前端目录:`frontend-vue`
- 开发代理:`frontend-vue/vite.config.ts:25-30` 将前端的 `/api` 代理到后端 `VITE_API_TARGET`
- 环境变量:
- `frontend-vue/.env.development` 示例:`VITE_API_TARGET=https://your-backend.example.com`
- 可选:`VITE_DEV_HOST`、`VITE_ALLOWED_HOSTS` 控制本地开发主机与允许的外网访问
- 启动与构建:
- 开发:`cd frontend-vue && npm i && npm run dev`
- 预览:`npm run preview`
## 鉴权与凭证
- 认证头:`Authorization: Bearer <token>`
- 前端存储:
- `localStorage` 键名:`cm_user`、`cm_token`
- 应用启动恢复:`frontend-vue/src/app/main.ts:10-12`
- 路由守卫:`frontend-vue/src/app/router/index.ts:23-30` 未登录重定向到登录页;基于 `meta.roles` 进行角色校验
## 关键接口规范
- 健康检查:`GET /v1/health`
- 登录:`POST /v1/user/login`
- 请求体:`{ username, password }`
- 响应体:`{ token, user: { username, role, email? } }`
- 注册:`POST /v1/user/register`
- 请求体:`{ username, email, password, fullName }`
- 响应体:`{ token?, user: { username, role, email? } }`
- 用户列表:`GET /api/v1/users`
- 响应体:`{ users: Array<{ username, role, email }> }` 或 `Array<{ username, role, email }>`
- 前端选择逻辑:仅匹配当前登录用户名;未匹配则显示错误提示
- 权限不足(例如操作员 403页面显示权限提示
- 角色值规范化:后端返回的 `role` 会统一转为小写并支持常见别名(如 `administrator`→`admin`、`ops`→`operator`
- 集群与节点:
- `GET /v1/clusters``[{ uuid, host, ip, count, health }]`
- `POST /v1/clusters`、`DELETE /v1/clusters/:id`、`POST /v1/clusters/:id/start|stop`
- `GET /v1/nodes?cluster=<uuid>``[{ name, ip, status, cpu, mem, updated }]`
- `POST /v1/nodes/:name/start|stop`、`DELETE /v1/nodes/:name`
- 指标:
- CPU 趋势:`GET /v1/metrics/cpu_trend?cluster=<uuid>` → `{ times: string[], values: number[] }`
- 内存使用:`GET /v1/metrics/memory_usage?cluster=<uuid>` → `{ used: number, free: number }`
- 诊断:
- 故障摘要:`GET /v1/faults/summary?node=<name>|cluster=<host>` → `{ code, time, scope }`
- AI 对话历史:`GET /v1/ai/history?sessionId=<id>` → `{ messages: Array<{ role, content, reasoning? }> }`
- AI 对话:`POST /v1/ai/chat` → `{ reply, reasoning? }`
## 前端数据绑定要点
- 个人主页:`frontend-vue/src/app/views/Profile.vue`
- 仅使用后端数据;加载中与错误态可视化
- 角色标签映射:`frontend-vue/src/app/constants/roles.ts`
- 角色来源:
- 登录/注册优先采用后端返回的 `user.role``role``frontend-vue/src/app/stores/auth.ts:55-72,74-91`
- 诊断页与导航:
- 路由授权:`diagnosis` 允许 `admin/operator``frontend-vue/src/app/router/index.ts:12`
- 侧边栏入口基于角色显示(`frontend-vue/src/app/components/Sidebar.vue:7`
## 联调步骤
- 设置 `VITE_API_TARGET` 指向后端地址,确保后端允许来自前端的 CORS 与 Host
- 启动前端后检查 `GET /v1/health` 返回正常
- 使用真实账号登录,确认:
- `GET /v1/user/me` 返回用户信息,个人主页字段显示为后端数据
- 侧边栏与页面访问受角色控制
- 仪表板与诊断页数据来自后端接口
- 常见问题:
- Token 无效或过期 → 返回 `401`,需要重新登录
- 代理失败 → 检查 `VITE_API_TARGET` 与后端协议/端口
- 外网访问本地开发 → 配置 `VITE_ALLOWED_HOSTS`,参考 `Cloudflare-Tunnel-Guide.md`
## 参考文件
- `frontend-vue/vite.config.ts`
- `frontend-vue/src/app/main.ts`
- `frontend-vue/src/app/router/index.ts`
- `frontend-vue/src/app/stores/auth.ts`
- `frontend-vue/src/app/views/Profile.vue`
- `frontend-vue/src/app/components/Sidebar.vue`
- `frontend-vue/src/app/constants/roles.ts`

@ -1,65 +0,0 @@
# Cloudflare Tunnel 跨网络访问教程(方案 B
## 适用场景
- 你与远程主机不在同一局域网,需要临时向公网暴露本地开发端口(前端 5173、后端 8000
- 仅用于演示和联调;生产请使用命名隧道、反向代理与严格鉴权
## 准备
- 平台WindowsPowerShell
- 目录:在项目根目录执行(已下载 `cloudflared.exe`
## 步骤一:下载 cloudflared已完成
- 命令(参考):
```
$ProgressPreference = 'SilentlyContinue'; \
$url = 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe'; \
$out = Join-Path (Get-Location) 'cloudflared.exe'; \
Invoke-WebRequest -Uri $url -OutFile $out; \
Write-Host "Downloaded: $out"
```
## 步骤二启动前端隧道Vite 5173
- 启动命令:
```
.\cloudflared.exe tunnel --protocol http2 --url http://localhost:5173
```
- 终端会打印一个临时域名(示例):
```
https://<随机>.trycloudflare.com
```
- 远程访问:在浏览器打开该域名即可访问你的前端页面
- 提示:保持命令行进程运行;若 HMR 异常,可在 `frontend-vue/.env` 设置:
```
VITE_HMR_HOST=<上述临时域名>
VITE_HMR_PORT=443
```
## 步骤三启动后端隧道API 8000
- 启动命令:
```
根目录执行
.\cloudflared.exe tunnel --protocol http2 --url http://localhost:8000 --no-autoupdate
```
- 终端会打印另一个临时域名;将前端代理目标指向该域名:
```
VITE_API_TARGET=https://<后端临时域名>
```
## 验证
- 前端:打开前端临时域名首页;访问 `/<任意页面>``/@vite/client`HMR 检测)
- 后端:访问 `https://<后端临时域名>/api/v1/health` 返回 200 即可
## 常见问题
- QUIC 连接超时:增加 `--protocol http2`(已使用)
- 日志提示未找到证书Quick Tunnel 可忽略;若使用命名隧道请按官方文档配置证书
- 端口未监听:确保本地 `npm run dev``uvicorn` 已启动5173、8000
## 安全与说明
- 临时域名仅用于演示Cloudflare 可能回收,随时重启生成新域名
- 不要在开发环境暴露敏感信息;生产务必启用 TLS 与鉴权,并限制来源
## 关闭隧道
- 在运行隧道的终端按 `Ctrl + C` 即可
## 参考
- 官方文档https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/run-tunnel/trycloudflare/

@ -1,206 +1,114 @@
# 后端部署与启动指南
本指南介绍如何在本地或服务器环境部署并启动后端服务FastAPI。后端默认提供 `/api/v1` 前缀的接口,前端通过 Vite 代理到该服务。
## 环境准备
- 操作系统Windows/Linux/Mac 均可
- 必备软件:
- Python 3.10+(建议 3.10 或以上)
- PostgreSQL 14+(或兼容版本)
- 代码位置:`backend/` 为后端根目录
## 安装依赖
1) 创建并激活虚拟环境Windows 示例):
```
cd backend
python -m venv .venv
.\.venv\Scripts\activate
```
Linux/Mac 示例:
```
# Hadoop 故障诊断系统 - 后端服务 (FastAPI)
本项目是 Hadoop 故障诊断系统的后端核心,基于 FastAPI 构建,提供集群监控、日志采集、指标分析以及基于 AI 的智能故障诊断功能。
## 🚀 核心功能
- **用户与认证**: 基于 JWT 的无状态认证,支持用户注册、登录及权限管理。
- **集群与节点管理**: 支持 Hadoop 集群的注册、SSH 连通性校验、HDFS UUID 获取及节点状态管理。
- **指标采集与监控**:
- 自动采集集群及节点的 CPU、内存使用率。
- 提供实时指标查询与趋势图数据支持。
- **Hadoop 日志管理**:
- 远程日志读取:通过 SSH 实时读取各节点 Hadoop 日志。
- 自动日志采集:增量 tail 模式采集日志并持久化至数据库。
- 批量回填:支持对历史日志进行批量同步。
- **AI 智能诊断**:
- 集成 LangChain 与 OpenAI提供流式对话接口 (SSE)。
- 智能智能体 (Agent) 可自动调用工具:查看日志、执行远程命令、分析集群状态。
- **系统执行日志**: 记录所有远程运维操作与系统任务的执行过程。
## 🛠 技术栈
- **框架**: [FastAPI](https://fastapi.tiangolo.com/) - 高性能异步 Web 框架。
- **数据库**: [PostgreSQL](https://www.postgresql.org/) + [SQLAlchemy (Async)](https://www.sqlalchemy.org/) - 异步 ORM 驱动。
- **SSH 通信**: [Paramiko](https://www.paramiko.org/) - 处理远程命令执行与日志读取。
- **AI/LLM**: [LangChain](https://www.langchain.com/) + OpenAI API - 实现故障诊断智能体。
- **任务调度**: 内置线程化采集器,支持异步指标与日志采集任务。
- **认证**: PyJWT + Passlib (BCrypt) - 安全的身份验证。
## 📂 项目结构
```text
backend/
├── app/
│ ├── agents/ # AI 智能体定义与工具编排
│ ├── deps/ # FastAPI 依赖注入(如认证、数据库)
│ ├── models/ # SQLAlchemy 异步模型
│ ├── routers/ # API 路由模块集群、指标、日志、AI等
│ ├── services/ # 业务逻辑服务SSH管理、LLM调用等
│ ├── workers/ # 异步任务处理逻辑
│ ├── config.py # 环境变量与全局配置
│ ├── db.py # 数据库引擎与会话管理
│ ├── main.py # 应用入口与路由注册
│ └── log_collector.py # 日志采集器核心实现
├── scripts/ # 数据库初始化与验证脚本
├── tests/ # 单元测试与集成测试
├── requirements.txt # 依赖清单
└── start_backend.sh # 一键启动脚本
```
## ⚙️ 环境变量配置
`backend/` 目录下创建 `.env` 文件,配置如下关键参数:
| 参数 | 描述 | 默认值 |
| :--- | :--- | :--- |
| `DATABASE_URL` | PostgreSQL 异步连接串 | `postgresql+asyncpg://postgres:password@localhost:5432/hadoop_fault_db` |
| `JWT_SECRET` | JWT 签名密钥 | `dev-secret` |
| `JWT_EXPIRE_MINUTES` | 令牌有效期(分钟) | `60` |
| `SSH_PORT` | 默认远程 SSH 端口 | `22` |
| `SSH_TIMEOUT` | SSH 连接超时时间 | `10` |
| `HADOOP_LOG_DIR` | Hadoop 远程日志默认路径 | `/usr/local/hadoop/logs` |
| `APP_TIMEZONE` | 系统时区 | `Asia/Shanghai` |
| `OPENAI_API_KEY` | OpenAI 密钥(用于 AI 诊断) | - |
## 🛠 安装与启动
### 1. 环境准备
- Python 3.10+
- PostgreSQL 14+
### 2. 安装依赖
```bash
cd backend
python3 -m venv .venv
source .venv/bin/activate
```
2) 安装依赖:
```
source .venv/bin/activate # Windows: .\.venv\Scripts\activate
pip install -r requirements.txt
```
## 数据库配置
后端通过环境变量读取数据库连接,优先使用 `DATABASE_URL`;若未设置,则使用 `DB_HOST/DB_PORT/DB_NAME/DB_USER/DB_PASSWORD` 组合。
- 方式一:设置组合连接串 `DATABASE_URL`
```
# .env
DATABASE_URL=postgresql+asyncpg://<user>:<password>@<host>:<port>/<db>
JWT_SECRET=please-change-it
JWT_EXPIRE_MINUTES=60
```
- 方式二:分别设置参数
```
# .env
DB_HOST=localhost
DB_PORT=5432
DB_NAME=hadoop_fault_db
DB_USER=postgres
DB_PASSWORD=your_password
JWT_SECRET=please-change-it
JWT_EXPIRE_MINUTES=60
```
配置文件读取逻辑见 `backend/app/config.py`,默认值为:
- `DATABASE_URL` 默认 `postgresql+asyncpg://postgres:password@localhost:5432/hadoop_fault_db`
- `JWT_SECRET` 默认 `dev-secret`
- `JWT_EXPIRE_MINUTES` 默认 `60`
## 初始化数据库
项目提供 PostgreSQL 建表脚本,含核心业务表与初始数据:
- 脚本路径:`doc/project/数据库建表脚本_postgres.sql`
使用 `psql` 导入Windows 示例):
```
psql -h <host> -U <user> -d <db> -f "doc/project/数据库建表脚本_postgres.sql"
```
Linux/Mac 示例:
```
psql -h <host> -U <user> -d <db> -f ./doc/project/数据库建表脚本_postgres.sql
```
> 提示:若需远程访问 PostgreSQL请确认
> - `postgresql.conf``listen_addresses='*'`(或包含服务器地址)
> - `pg_hba.conf` 中允许来源网段,例如:`host all all 192.168.43.0/24 scram-sha-256`
## 启动数据库
PostgreSQL 15 启动与管理:
pg_ctl 方式(受限环境推荐):
```
# 启动
sudo -u postgres /usr/lib/postgresql/15/bin/pg_ctl -D /var/lib/postgresql/15/main -o "-c config_file=/etc/postgresql/15/main/postgresql.conf" -l /var/log/postgresql/postgresql-15-main.log start
# 状态
sudo -u postgres /usr/lib/postgresql/15/bin/pg_ctl -D /var/lib/postgresql/15/main status
# 停止
sudo -u postgres /usr/lib/postgresql/15/bin/pg_ctl -D /var/lib/postgresql/15/main stop
# 重启
sudo -u postgres /usr/lib/postgresql/15/bin/pg_ctl -D /var/lib/postgresql/15/main restart
```
systemd 方式(标准环境):
```
# 启动所有集群
sudo systemctl start postgresql
# 启动指定实例(根据系统实际单元名可能为 postgresql@15-main
sudo systemctl start postgresql@15-main
# 查看状态
sudo systemctl status postgresql
sudo systemctl status postgresql@15-main
```
进入psql命令行
PGPASSWORD='shenyongye123da*' psql -h 127.0.0.1 -U echo -d hadoop_fault_db
开机自启动:
```
# 所有集群自启
sudo systemctl enable postgresql
# 指定实例自启
sudo systemctl enable postgresql@15-main
```
取消自启动与验证:
```
# 取消自启(指定实例)
sudo systemctl disable postgresql@15-main
# 查看是否启用enabled/disabled
systemctl is-enabled postgresql@15-main
# 重启后验证监听状态
sudo -u postgres /usr/lib/postgresql/15/bin/pg_isready
```
连接验证:
```
# 管理员
export PGPASSWORD='password'
psql -h 127.0.0.1 -U postgres -d hadoop_fault_db -c "SELECT 1;"
# 应用账户 echo
export PGPASSWORD='shenyongye123da*'
psql -h 127.0.0.1 -U echo -d hadoop_fault_db -c "SELECT current_user;"
```
日志查看:
```
sudo tail -n 100 /var/log/postgresql/postgresql-15-main.log
### 3. 初始化数据库
执行 `scripts/` 目录下的 SQL 脚本或通过内置脚本初始化:
```bash
# 导入 SQL 脚本
psql -h <host> -U <user> -d <db> -f ../doc/project/数据库建表脚本_postgres.sql
```
## 启动服务
开发模式(自动重载):
```
# 通用方式(推荐)
进入backend目录:
### 4. 启动服务
```bash
# 开发模式
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
# Windows 若未配置 python 到 PATH可使用 Python Launcher
在backend目录中:
py -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
# 使用虚拟环境中的解释器(绝对可靠):
.\.venv\Scripts\python.exe -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
```
生产模式(示例,仅供参考):
```
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000
# 或 Windows
py -m uvicorn app.main:app --host 0.0.0.0 --port 8000
# 或使用虚拟环境解释器:
.\.venv\Scripts\python.exe -m uvicorn app.main:app --host 0.0.0.0 --port 8000
或使用提供的启动脚本:
```bash
bash start_backend.sh
```
前端代理默认将 `/api` 代理到 `http://localhost:8000`。如需修改,在 `frontend-vue/vite.config.ts` 中设置 `VITE_API_TARGET`
## 📖 API 接口预览
## 快速联调
健康检查:
```
curl http://localhost:8000/api/v1/health
```
注册用户:
```
curl -X POST http://localhost:8000/api/v1/user/register \
-H "Content-Type: application/json" \
-d '{
"username":"user001",
"email":"user001@example.com",
"password":"StrongPass1",
"fullName":"测试用户"
}'
```
登录获取令牌:
```
curl -X POST http://localhost:8000/api/v1/user/login \
-H "Content-Type: application/json" \
-d '{"username":"user001","password":"StrongPass1"}'
```
携带令牌访问当前用户:
```
curl http://localhost:8000/api/v1/user/me -H "Authorization: Bearer <token>"
```
所有接口均带有 `/api/v1` 前缀。
## 可选:本地验证脚本
项目已提供端到端验证脚本:`backend/scripts/verify_register.py`
- **Health**: `GET /health`
- **Auth**: `POST /auth/login`, `POST /auth/register`
- **Clusters**: `GET /clusters`, `POST /clusters/register`
- **Metrics**: `GET /metrics/trend`, `POST /metrics/collector/start`
- **Hadoop Logs**: `GET /hadoop/logs/all/{log_type}`, `GET /hadoop/collectors/status`
- **AI**: `POST /ai/chat` (支持 SSE 流式返回)
在已激活的虚拟环境中运行Windows 示例):
```
.\.venv\Scripts\python.exe .\scripts\verify_register.py
```
Linux/Mac 示例:
```
python ./scripts/verify_register.py
```
## 接口清单(节选)
- `GET /api/v1/health` 健康检查
- `POST /api/v1/user/register` 注册新用户,返回 `token`
- `POST /api/v1/user/login` 登录并返回 `token`
- `GET /api/v1/user/me` 获取当前用户信息(需 `Authorization: Bearer <token>`
详细接口文档启动后访问:`http://localhost:8000/docs`
## 其他说明
- 演示账户(仅用于快速体验):`admin/admin123`、`ops/ops123`、`obs/obs123`
- 安全建议:生产环境务必设置强随机的 `JWT_SECRET`,并限制数据库访问来源
- 若依赖安装失败或 `python` 命令不可用,请确认已安装 Python 并将其加入系统 PATH或使用虚拟环境中的解释器路径运行命令
## 🧪 验证与测试
运行端到端验证脚本:
```bash
python scripts/verify_register.py
```

@ -12,6 +12,7 @@ class User(Base):
password_hash: Mapped[str] = mapped_column(String(255))
full_name: Mapped[str] = mapped_column(String(100))
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
sort: Mapped[int] = mapped_column(default=0)
last_login: Mapped[str | None] = mapped_column(TIMESTAMP(timezone=True), nullable=True)
created_at: Mapped[str] = mapped_column(TIMESTAMP(timezone=True))
updated_at: Mapped[str] = mapped_column(TIMESTAMP(timezone=True))

@ -20,11 +20,13 @@ class CreateUserRequest(BaseModel):
email: str
role: str
status: str
sort: int = 0
class UpdateUserRequest(BaseModel):
role: str | None = None
status: str | None = None
sort: int | None = None
class ChangePasswordRequest(BaseModel):
currentPassword: str
@ -96,7 +98,7 @@ def _require_permission(user, permission: str):
async def list_users(user=Depends(get_current_user), db: AsyncSession = Depends(get_db)):
try:
_require_permission(user, "auth:manage")
result = await db.execute(select(User).limit(500))
result = await db.execute(select(User).order_by(User.sort.desc()).limit(500))
rows = result.scalars().all()
users = []
for u in rows:
@ -107,6 +109,7 @@ async def list_users(user=Depends(get_current_user), db: AsyncSession = Depends(
"email": u.email,
"role": rk or "observer",
"status": _active_to_status(u.is_active),
"sort": u.sort,
}
)
return {"users": users}
@ -148,6 +151,7 @@ async def create_user(req: CreateUserRequest, user=Depends(get_current_user), db
password_hash=password_hash,
full_name=req.username,
is_active=_status_to_active(req.status),
sort=req.sort,
last_login=None,
created_at=now,
updated_at=now,
@ -178,6 +182,8 @@ async def update_user(username: str, req: UpdateUserRequest, user=Depends(get_cu
if req.status not in {"enabled", "disabled"}:
raise HTTPException(status_code=400, detail="invalid_status")
updates["is_active"] = _status_to_active(req.status)
if req.sort is not None:
updates["sort"] = req.sort
if req.role is not None:
if req.role not in {"admin", "operator", "observer"}:
raise HTTPException(status_code=400, detail={"errors": [{"field": "role", "message": "不允许的角色"}]})

File diff suppressed because it is too large Load Diff

Binary file not shown.

@ -1,6 +0,0 @@
nohup: ignoring input
time="2026-01-04T05:01:29.583454678Z" level=info msg="Start initial configuration in progress"
time="2026-01-04T05:01:29.584823865Z" level=info msg="Geodata Loader mode: memconservative"
time="2026-01-04T05:01:29.584846097Z" level=info msg="Geosite Matcher implementation: succinct"
time="2026-01-04T05:01:29.585254618Z" level=info msg="Can't find MMDB, start download"
time="2026-01-04T05:01:32.229953886Z" level=info msg="Initial configuration complete, total time: 2646ms"

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

@ -1,29 +1,51 @@
@startuml
title 日志诊断与自动修复流程
title 核心业务流程时序图 (Updated)
actor User
actor Admin
participant Frontend as FE
participant FastAPI as API
participant Flume
database MySQL as DB
queue Redis
participant "FastAPI Auth" as Auth
participant "FastAPI Diagnosis" as Diag
participant "Agents (DA/PA/RA)" as Agents
database PostgreSQL as DB
participant LLM
participant "Hadoop Cluster" as Cluster
Flume -> API : 推送结构化日志
API -> DB : 写入 fault_record
FE -> API : 查询 /api/logs/query
API -> FE : 返回日志列表
== 用户注册与审批 ==
User -> FE : 提交注册信息
FE -> Auth : POST /api/auth/register
Auth -> DB : 写入用户 (status=pending)
Admin -> FE : 查看审批队列
FE -> Auth : GET /api/auth/pending_users
Auth -> DB : 查询
Admin -> FE : 批准注册
FE -> Auth : POST /api/auth/approve/{uid}
Auth -> DB : 更新用户 (status=active)
User -> FE : 登录 (正确/错误凭据)
FE -> Auth : POST /api/auth/login
Auth -> DB : 校验
Auth -> FE : 返回 JWT / 错误提示
API -> LLM : call_llm_diagnose(logs)
LLM --> API : 返回 FixCommand(JSON)
API -> DB : 写入 exec_log
API -> Redis : 缓存/发布修复任务
API -> FE : WebSocket 推送诊断结果
== 故障诊断与自动修复 ==
Cluster -> Diag : 推送日志 (Flume/SSH)
Diag -> DB : 记录 Fault (status=detected)
User -> FE : 点击 "AI 诊断"
FE -> Diag : POST /api/diagnosis/trigger
Diag -> Agents : 调用 DiagnosisAgent
Agents -> LLM : 分析日志上下文
LLM -> Agents : 返回根因与建议 (FixCommand)
Agents -> Diag : 诊断结果 (Risk Level)
Diag -> DB : 更新 Fault (status=analyzing)
Diag -> FE : WebSocket 推送报告
FE -> API : /api/repair/execute
API -> "修复脚本" : 执行Shell/Hadoop命令
"修复脚本" -> API : stdout/stderr
API -> DB : 更新 exec_log
API -> FE : 返回执行结果
User -> FE : 确认执行修复 (High risk needs approval)
FE -> Diag : POST /api/repair/execute
Diag -> Agents : 调用 PolicyAgent (评估风险)
Agents -> Agents : 调用 RepairAgent
Agents -> Cluster : SSH 执行修复脚本
Cluster -> Agents : 返回 stdout/stderr
Agents -> Diag : 修复完成
Diag -> DB : 记录 ExecLog & 更新 Fault (status=resolved/failed)
Diag -> FE : 推送最终结果
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

@ -1,36 +1,52 @@
@startuml
title 故障检测系统总体架构
title 故障检测系统总体架构 (Aligned with Backend)
node "Hadoop Cluster" {
[NameNode]
[DataNode] as DN1
[DataNode] as DN2
[ResourceManager]
[DataNode / NodeManager] as Node
}
cloud "Flume Agents" as Flume
Flume --> DN1 : 采集HDFS/YARN日志
Flume --> DN2 : 采集HDFS/YARN日志
cloud "Log & Metrics Collection" {
[Flume Agent] as Flume
[SSH Probe Service] as Probe
Flume --> Node : 采集 Hadoop 日志
Probe --> Node : 采集系统指标 (CPU/Mem/Disk)
}
component "FastAPI Service" as API
database "PostgreSQL" as DB
queue "Redis" as Cache
API --> DB : 写入/查询故障记录
API --> Cache : 状态缓存/队列
API --> "LLM Diagnose" : 调用大模型\n返回FixCommand
package "Backend Service (FastAPI)" {
component "Auth Router" as Auth
component "Cluster/Node Router" as ClusterSvc
component "Fault/Log Router" as FaultSvc
component "AI/Chat Router" as ChatSvc
component "Orchestrator" as Orchestrator
component "DiagnosisAgent" as DA
component "PolicyAgent" as PA
component "RepairAgent" as RA
Auth --> [PostgreSQL] : users
ClusterSvc --> [PostgreSQL] : clusters, nodes
FaultSvc --> [PostgreSQL] : fault_records, hadoop_exec_logs
ChatSvc --> [PostgreSQL] : chat_sessions, chat_messages
Orchestrator --> DA
Orchestrator --> PA
Orchestrator --> RA
DA --> [LLM Service] : LangChain / OpenAI
RA --> [Hadoop Cluster] : SSH (Paramiko)
}
component "Agent Orchestrator" as Orchestrator
component "Diagnosis Agent" as DA
component "Repair Agent" as RA
component "Policy Agent" as PA
API --> Orchestrator : 触发诊断/修复流程
Orchestrator --> DA : 传递结构化日志
Orchestrator --> PA : 风险评估与审批策略
Orchestrator --> RA : 下发修复命令
DA --> "LLM Diagnose" : 调用LLM分析
RA --> Cluster : SSH/命令执行
package "Frontend (Vue 3)" {
component "Dashboard" as Dash
component "Diagnosis Chat" as DiagUI
component "Admin UI" as Admin
}
component "Frontend Web (Vue/React + ECharts)" as FE
FE --> API : /api/cluster/status\n/api/logs/query\n/api/diagnosis/result\n/api/repair/execute
API --> FE : WebSocket推送状态/诊断结果
Dash --> ClusterSvc
DiagUI --> ChatSvc
Admin --> Auth
Orchestrator ..> [Redis] : 任务状态与实时推送
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@ -1,45 +1,36 @@
@startuml
title 日志诊断与自动修复 - 活动图
title 故障生命周期状态机与修复流程 (Updated)
skinparam defaultFontName Microsoft YaHei
start
:Flume采集日志;
:FastAPI接收并解析日志;
:保存 FaultRecord 到 MySQL;
(*) --> "Detected (故障发现)" : 系统采集到异常日志/指标
partition "用户/系统触发" {
if (是否需要诊断?) then (是)
:聚合相关日志;
:构造 Prompt;
:调用 LLM 诊断;
:生成 FixCommand(JSON);
:安全校验(禁止高危命令);
else (否)
:等待新日志/用户请求;
stop
endif
partition "AI 诊断阶段" {
"Detected (故障发现)" --> "Analyzing (正在分析)" : 触发 AI 诊断 (DiagnosisAgent)
"Analyzing (正在分析)" --> "Diagnosed (已生成建议)" : LLM 分析完成并生成 FixCommand
}
if (风险等级 == high?) then (是)
:前端弹窗请求人工确认;
if (用户确认执行?) then (是)
:继续执行修复;
else (否)
:记录并通知未执行;
stop
partition "策略评估与修复阶段" {
"Diagnosed (已生成建议)" --> "Risk Assessment (PolicyAgent)"
if "风险等级" then
-->[High] "Pending Approval (待审批)"
-->[Approved] "Repairing (修复中)"
else
-->[Low/Medium] "Repairing (修复中)"
endif
endif
"Repairing (修复中)" --> "Executing (RepairAgent)"
"Executing (RepairAgent)" --> "Post-Check (修复后校验)"
}
:修复前预检查(配置/路径/权限);
if (预检查通过?) then (是)
:执行修复脚本;
:采集stdout/stderr;
:保存 ExecLog 到 MySQL;
:更新状态到 Redis 并推送 WebSocket;
else (否)
:记录失败原因;
"Post-Check (修复后校验)" --> if "是否修复成功?" then
-->[Yes] "Resolved (已解决)"
--> (*)
else
-->[No] "Failed (修复失败)"
--> "Manual Intervention (需人工介入)"
--> (*)
endif
:返回结果给前端;
stop
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

@ -1,38 +1,42 @@
@startuml
title 故障检测系统 - 用例图
skinparam defaultFontName Microsoft YaHei
actor 运维工程师 as Ops
actor 前端用户 as User
actor 测试工程师 as QA
rectangle "故障检测系统" {
usecase "查看集群状态" as UC_Status
usecase "查询日志" as UC_QueryLogs
usecase "发起故障诊断" as UC_Diagnose
usecase "执行自动修复" as UC_Repair
usecase "查看执行日志" as UC_ExecLogs
usecase "配置Flume收集" as UC_ConfigFlume
usecase "配置告警阈值" as UC_ConfigAlert
usecase "导出故障与诊断报告" as UC_Export
usecase "生成FixCommand" as UC_FixCmd
usecase "命令安全校验" as UC_SafeCheck
title 故障检测系统用例图 (Updated)
User --> UC_Status
User --> UC_QueryLogs
User --> UC_Diagnose
User --> UC_Repair
User --> UC_ExecLogs
skinparam defaultFontName Microsoft YaHei
Ops --> UC_ConfigFlume
Ops --> UC_ConfigAlert
Ops --> UC_Repair
Ops --> UC_Status
actor "访客" as Guest
actor "管理员" as Admin
actor "运维人员/操作员" as Operator
actor "观察员" as Observer
QA --> UC_QueryLogs
QA --> UC_Export
rectangle "故障检测与诊断系统" {
(注册与登录) as UC_Auth
(注册审批) as UC_Approve
(集群管理) as UC_Cluster
(实时监控) as UC_Monitor
(日志检索) as UC_Logs
(AI 故障诊断) as UC_Diag
(自动/手动修复) as UC_Repair
(操作审计) as UC_Audit
(用户权限管理) as UC_UserMgmt
UC_Diagnose --> UC_FixCmd : <<include>>
UC_Repair --> UC_SafeCheck : <<include>>
Guest --> UC_Auth
Admin --> UC_Approve
Admin --> UC_UserMgmt
Admin --> UC_Audit
Admin --> UC_Cluster
Operator --> UC_Monitor
Operator --> UC_Logs
Operator --> UC_Diag
Operator --> UC_Repair
Operator --> UC_Cluster
Observer --> UC_Monitor
Observer --> UC_Logs
UC_Diag ..> (LLM 根因分析) : <<include>>
UC_Repair ..> (风险评估审批) : <<include>>
}
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

@ -1,130 +1,112 @@
@startuml
title 故障检测与自动修复 - 类图
skinparam backgroundColor #FFFFFF
skinparam defaultFontName Microsoft YaHei
skinparam classAttributeIconSize 0
class FlumeAgent {
+config : Map
+start()
+stop()
}
class LogEvent {
+timestamp : datetime
+host : string
+source : string
+level : string
+message : string
+raw : text
}
class FastAPIService {
+ingestLog(e: LogEvent)
+getClusterStatus()
+queryLogs(filter)
+diagnose(logs)
+executeRepair(cmd: FixCommand)
}
class DiagnosisService {
+callLLM(logs) : FixCommand
+validateCommand(cmd: FixCommand) : bool
}
class LLMClient {
+apiKey : string
+endpoint : string
+invoke(prompt) : string
}
class FixCommand {
+fault_type : string
+reason : string
+fix_script : string
+risk_level : RiskLevel
}
enum RiskLevel {
low
medium
high
}
class RepairExecutor {
+run(script) : ExecResult
+precheck() : bool
}
class ExecResult {
+stdout : text
+stderr : text
+exitCode : int
}
class FaultRecord {
+id : int
+fault_type : string
+reason : string
+timestamp : datetime
+node : string
}
class ExecLog {
+id : int
+record_id : int
+stdout : text
+stderr : text
+timestamp : datetime
}
class MySQLClient {
+saveFault(record: FaultRecord)
+saveExecLog(log: ExecLog)
+queryLogs(filter)
}
class RedisCache {
+set(key, value)
+publish(channel, msg)
+get(key)
}
class ClusterStatus {
+nodesUp : int
+nodesDown : int
+hdfsUsage : float
+yarnActiveApps : int
}
title 故障检测与自动修复 - 领域模型类图 (Updated from Code)
class FrontendWeb {
+viewStatus()
+queryLogs()
+requestDiagnosis()
+executeRepair()
}
skinparam classAttributeIconSize 0
FlumeAgent --> FastAPIService : push(LogEvent)
FastAPIService --> DiagnosisService : diagnose(logs)
DiagnosisService --> LLMClient : call_llm_diagnose
DiagnosisService --> FixCommand : returns
FastAPIService --> RepairExecutor : execute(FixCommand)
RepairExecutor --> ExecResult : returns
FastAPIService --> MySQLClient : save FaultRecord/ExecLog
FastAPIService --> RedisCache : cache/publish status
FrontendWeb --> FastAPIService : REST/WebSocket
FastAPIService --> ClusterStatus : compose
MySQLClient --> FaultRecord
MySQLClient --> ExecLog
FixCommand --> RiskLevel
package "Models (SQLAlchemy)" {
class User {
+id : int <<PK>>
+username : string
+email : string
+password_hash : string
+full_name : string
+is_active : bool
+last_login : TIMESTAMP
+created_at : TIMESTAMP
}
class Cluster {
+id : int <<PK>>
+uuid : string <<Unique>>
+name : string
+type : string
+node_count : int
+health_status : string
+cpu_avg : float
+memory_avg : float
+namenode_ip : INET
+rm_ip : INET
+config_info : JSONB
+to_dict() : dict
}
class Node {
+id : int <<PK>>
+uuid : string <<Unique>>
+cluster_id : int <<FK>>
+hostname : string
+ip_address : INET
+ssh_user : string
+ssh_password : string
+status : string
+cpu_usage : float
+memory_usage : float
+disk_usage : float
+last_heartbeat : TIMESTAMP
}
class FaultRecord {
+id : int <<PK>>
+fault_id : string <<Unique>>
+cluster_id : int <<FK>>
+fault_type : string
+fault_level : string
+title : string
+description : string
+affected_nodes : JSONB
+affected_clusters : JSONB
+root_cause : string
+repair_suggestion : string
+status : string
+reporter : string
+to_dict() : dict
}
class HadoopExecLog {
+id : int <<PK>>
+from_user_id : int <<FK>>
+cluster_name : string
+description : text
+start_time : TIMESTAMP
+end_time : TIMESTAMP
+to_dict() : dict
}
class ChatSession {
+id : string <<PK>> (UUID)
+user_id : int <<FK>>
+title : string
+created_at : DateTime
+messages : List<ChatMessage>
}
class ChatMessage {
+id : int <<PK>>
+session_id : string <<FK>>
+role : string (system/user/assistant/tool)
+content : text
+created_at : DateTime
}
}
package "Agents (Logic)" {
class DiagnosisAgent {
+analyze(logs) : FixCommand
}
class PolicyAgent {
+evaluate(cmd) : RiskLevel
}
class RepairAgent {
+execute(cmd) : ExecResult
}
}
User "1" -- "0..*" HadoopExecLog : executes
User "1" -- "0..*" ChatSession : owns
Cluster "1" -- "0..*" Node : contains
Cluster "1" -- "0..*" FaultRecord : has
ChatSession "1" -- "0..*" ChatMessage : has_many
note right of FixCommand
JSON 示例:
{
fault_type: "DataNode故障",
reason: "磁盘占满",
fix_script: "ssh dn 'clean_temp.sh'",
risk_level: "medium"
}
end note
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

@ -1,25 +1,35 @@
@startuml
title 部署拓扑
title 故障检测系统部署拓扑 (Updated)
node "On-Prem / Cloud" {
node "Hadoop Cluster" {
[NameNode]
[DataNodes...]
}
node "Hadoop Cluster Node" {
component "Hadoop Components" as HC
component "Flume Agent" as Flume
HC - [SSH]
}
node "Logging Layer" {
[Flume Agents]
node "Management Server" {
package "Backend (Docker Container)" {
[FastAPI Service] as API
[Celery Workers] as Workers
}
node "Application Layer" {
[FastAPI]
[LLM Connector]
[Nginx for Frontend]
package "Frontend (Docker Container)" {
[Nginx / Vue App] as Web
}
database "PostgreSQL" as DB
queue "Redis" as Redis
}
node "Storage/Caching" {
[MySQL]
[Redis]
}
cloud "AI Platform" {
[OpenAI API / LangChain] as LLM
}
Web --> API : HTTP/WebSocket
API --> DB : Persistence
API --> Redis : Task Queue
API --> LLM : AI Analysis
API --> HC : SSH Execution
Flume --> API : Log Streaming
@enduml

Binary file not shown.

@ -0,0 +1,65 @@
# 基于 Hadoop 的故障检测与智能诊断项目 - 测试报告
## 修订记录
| 版本号 | 修订日期 | 修订内容 | 修订人 |
| :--- | :--- | :--- | :--- |
| v1.0.0 | 2026-01-10 | 初始测试报告框架创建 | AI Assistant |
---
## 1. 测试概述
### 1.1 测试目的
验证系统在 Hadoop 集群管理、指标采集、日志检索及 AI 诊断功能上的正确性、稳定性和响应速度,确保满足《需求规格说明书》中的定义。
### 1.2 测试范围
- **功能测试**: 集群注册、SSH 校验、日志同步、AI SSE 流式对话。
- **性能测试**: 大规模日志检索响应时间、多并发指标采集压力。
## 2. 测试环境
| 类别 | 配置要求 |
| :--- | :--- |
| **硬件** | 8 vCPU, 16GB RAM (测试服务器) |
| **软件** | Docker, PostgreSQL 14, Python 3.10 |
| **集群环境** | Hadoop 3.1.3 (1 NameNode, 5 DataNodes) |
## 3. 测试用例
| 用例编号 | 功能模块 | 测试点 | 预期结果 | 状态 |
| :--- | :--- | :--- | :--- | :--- |
| TC-01 | 集群管理 | 输入合法的 SSH 信息注册集群 | 注册成功并自动发现所有节点 | [待测试] |
| TC-02 | 日志采集 | 模拟节点产生 ERROR 日志 | 数据库 5 秒内出现对应增量日志 | [待测试] |
| TC-03 | AI 诊断 | 询问集群负载情况 | AI 正确调用指标工具并给出分析建议 | [待测试] |
## 4. 测试结果
### 4.1 通过/失败统计
- **总用例数**: 0
- **通过数**: 0
- **失败数**: 0
- **跳过数**: 0
- **通过率**: 0%
## 5. 缺陷分析
### 5.1 严重等级分布
- **致命 (Blocker)**: 0
- **严重 (Critical)**: 0
- **一般 (Major)**: 0
- **次要 (Minor)**: 0
## 6. 测试结论
### 6.1 质量评估
[在此填写本次测试阶段的总体质量评价,例如:系统核心流程已打通,但 AI 诊断在极端日志量下存在响应延迟。]
## 7. 附录
### 7.1 测试日志
- 后端服务日志: `backend/logs/test_run.log`
- 采集器性能统计: `docs/metrics_report.csv`
### 7.2 截图
[占位符:插入关键功能运行截图]

Binary file not shown.

@ -1,149 +1,187 @@
# 基于Hadoop的故障检测与自动恢复项目 需求规格说明书SRS
# 基于 Hadoop 的故障检测与智能诊断项目 - 需求规格说明书 (SRS)
## 1. 引言
- 目的:定义系统的功能与非功能需求,为设计、开发、测试与验收提供统一依据。
- 范围Web 应用(前端、后端、多智能体编排)、日志采集、数据库与缓存、可观测性。
- 术语Cluster、Node、Fault、ExecLog、Agent、Policy、JSONB、INET、TIMESTAMPTZ。
- 参考:
- `doc/project/数据库设计文档.md`
- `doc/project/数据库建表脚本_postgres.sql`
- `doc/project/ER图设计说明.md`
- `src/fronted/index.html`(前端原型)
- `doc/project/项目前景与范围文档.md`
## 2. 总体概述
- 产品透视:为 Hadoop 运维提供监控、日志分析、智能诊断与自动修复的一体化平台。
- 用户特征:管理员、操作员、观察员(角色权限定义与审批流程)。
- 约束PostgreSQL 14+、Redis、FastAPI、Vue3、Flume遵循安全与合规最佳实践。
## 3. 功能需求(按模块)
### F-01 身份认证与注册审批
- 说明登录、注册审批队列、用户状态管理、JWT 认证。
- 前端映射:`#login`、`#register`、`#user-management`(审批列表)。
- 接口示例:`POST /api/v1/user/login`、`POST /api/v1/user/register`、`GET /api/v1/admin/approvals`、`POST /api/v1/admin/approvals/{id}/approve`、`GET /api/v1/user/me`。
- 数据映射:`users`、`audit_logs`、`roles/user_role_mapping`。
- 验收:登录成功生成 JWT 与角色;注册进入审批队列;操作审计记录完整;受保护接口需携带 `Authorization: Bearer <token>`
### F-02 集群列表与注册
- 说明:查看已注册集群、注册新集群、注销集群。
- 前端映射:`#cluster-list`(注册面板/列表)。
- 接口示例:`GET /api/clusters`、`POST /api/clusters`、`DELETE /api/clusters/{uuid}`。
- 数据映射:`clusters(uuid,name,type,node_count,health_status,config_info)`。
- 验收集群唯一性uuid/name健康状态检查约束审计可追踪。
### F-03 仪表板监控
- 说明节点概览、状态指标、趋势图CPU/内存、WebSocket 状态。
- 前端映射:`#dashboard`(统计卡片、图表、节点表格)。
- 接口示例:`GET /api/cluster/status`、`GET /api/nodes?cluster=...`、WS `/ws/status`
- 数据映射:`nodes(cluster_id,hostname,ip_address,status,usage,last_heartbeat)`。
- 验收节点列表与统计一致图表数据刷新正常WS 在线率达标。
### F-04 日志查询
- 说明:按级别/来源集群/来源节点/操作类型/用户ID/时间范围筛选,支持导出。
- 前端映射:`#logs`(搜索条件/列表/分页)。
- 接口示例:`GET /api/logs?level=&cluster=&node=&op=&user=&time_range=`、`GET /api/logs/export`。
- 数据映射:`system_logs(log_id,timestamp,host,service,log_level,message,exception,raw_log,processed)`。
- 验收:筛选项工作正常;分页与导出准确;处理进度与日志条目一致。
### F-05 故障诊断(多智能体)
- 说明:拖拽上下文日志,选择智能体与模型,生成诊断结果与修复建议。
- 前端映射:`#diagnosis`(树形选择/预览/多智能体面板/对话)。
- 接口示例:`POST /api/llm/diagnose`(结构化日志→诊断结果),`POST /api/llm/report`(生成状态报告)。
- 数据映射:`fault_records(affected_nodes,affected_clusters,root_cause,repair_suggestion,status)`、`exec_logs(parameters,target_nodes)`。
- 验收DiagnosisAgent 输出结构化建议PolicyAgent 过滤高风险;生成报告成功。
### F-06 故障中心CRUD
- 说明故障列表筛选、详情、增删改状态机detected→analyzing→repairing→resolved/failed
- 前端映射:`#fault-center`(筛选/列表/操作)。
- 接口示例:`GET /api/faults`、`POST /api/faults`、`PUT /api/faults/{id}`、`DELETE /api/faults/{id}`、`POST /api/faults/{id}/transition`。
- 数据映射:`fault_records(fault_id,fault_type,fault_level,status,title,created_at,...)`。
- 验收:唯一约束 `fault_id`;状态转换合法且有审计记录;索引支持高频查询。
### F-07 执行日志CRUD
- 说明:记录修复命令执行详情,支持筛选与分页。
- 前端映射:`#exec-logs`(列表/操作)。
- 接口示例:`GET /api/exec-logs`、`POST /api/exec-logs`、`PUT /api/exec-logs/{id}`、`DELETE /api/exec-logs/{id}`。
- 数据映射:`exec_logs(exec_id,fault_id,command_type,command_content,target_nodes,risk_level,execution_status,start_time,end_time,stdout_log,stderr_log,exit_code,operator)`。
- 验收:外键 `fault_id` 关联完整;执行状态与时长约束合法;日志内容可读。
### F-08 告警配置(规则管理原型)
- 说明:新增/编辑/删除规则,通知渠道(邮件/短信/Webhook阈值条件。
- 前端映射:`#alert-config`(新增弹窗/规则列表)。
- 接口示例:`GET /api/alerts`、`POST /api/alerts`、`PUT /api/alerts/{id}`、`DELETE /api/alerts/{id}`。
- 数据映射:`app_configurations(config_type='alert_rule',config_key,config_value,is_enabled)`。
- 验收:配置值以 JSONB 存储;启用状态可控;策略与通知联动。
### F-09 用户管理与角色分配
- 说明:用户列表、状态(启用/禁用/待审核)、角色分配与撤销。
- 前端映射:`#user-management`、`#role-assignment`。
- 接口示例:`GET /api/admin/users`、`POST /api/admin/users`、`PUT /api/admin/users/{id}`、`POST /api/admin/users/{id}/roles`。
- 数据映射:`users`、`user_role_mapping`、`roles`。
- 验收:用户名/邮箱唯一;角色分配与撤销一致;审计完整。
### F-10 权限策略(原型)
- 说明:资源与操作的允许/拒绝策略配置。
- 前端映射:`#permission-policy`(策略列表)。
- 接口示例:`GET /api/policies`、`POST /api/policies`、`DELETE /api/policies/{id}`。
- 数据映射:`roles`、`permissions`、`role_permission_mapping`。
- 验收:策略生效与资源范围匹配;拒绝优先;审计记录。
### F-11 审计日志
- 说明:记录用户操作与系统事件,可筛选导出。
- 前端映射:`#audit-logs`。
- 接口示例:`GET /api/audit-logs`、`GET /api/audit-logs/export`。
- 数据映射:`audit_logs(user_id,cluster_id,role_id,action,resource_type,ip_address,request_data,response_status,created_at)`。
- 验收字段完整IP 为 INETJSONB 字段审计可读;索引满足查询需求。
### F-12 WebSocket 推送
- 说明:状态与诊断结果的实时推送;前端 WS 状态展示。
- 前端映射:`#dashboard`WebSocket 状态区)。
- 接口示例WS `/ws/status`、`/ws/diagnose`。
- 验收WS 连接稳定;消息格式统一;断线重连策略有效。
## 4. 非功能性需求
- 性能:核心查询 P95 ≤ 500msWS 延迟 ≤ 500ms后端并发 1k 连接稳定。
- 安全基于角色的访问控制敏感信息不落盘API 速率限制与审计。
- 可靠性:日常备份与恢复演练(`pg_dump`);关键链路重试与降级。
- 可维护性:模块化架构;多智能体职责清晰;日志与监控完善。
- 可用性前端可访问性ARIA 标签与语义结构);错误提示与操作引导。
- 可观测性Prometheus 指标采集Grafana 看板日志分级与追踪ID。
### 1.1 文档目的
本说明书详细定义了“Hadoop 故障检测与智能诊断系统”的功能性与非功能性需求。旨在指导系统的设计与开发为测试人员提供验收标准并作为项目评审的权威依据。适用人群包括后端开发工程师、前端开发工程师、QA 测试工程师及项目管理者。
### 1.2 项目背景
随着分布式集群规模的扩大Hadoop 集群的日常运维与故障排查变得日益复杂。传统的人工排查方式效率低下且依赖专家经验。本项目旨在通过自动化指标采集、实时日志增量分析以及集成 AI 智能体技术,解决集群故障定位难、修复慢的业务痛点。
### 1.3 定义与缩写
- **API**: 应用程序编程接口
- **SSH**: 安全外壳协议,用于远程控制
- **SSE**: 服务器发送事件,用于流式数据传输
- **LLM**: 大语言模型,本项目特指 OpenAI GPT 模型
- **Agent**: 具有自主决策和工具调用能力的智能体
### 1.4 参考资料
- 《Apache Hadoop 官方文档》
- 《FastAPI 异步 Web 框架规范》
- 《PostgreSQL 数据库性能优化指南》
### 1.5 版本历史
| 版本号 | 修订日期 | 修订人 | 修订内容 |
| :--- | :--- | :--- | :--- |
| v1.0.0 | 2026-01-10 | AI Assistant | 初始版本创建 |
| v1.1.0 | 2026-01-10 | AI Assistant | 全面优化:重组 8 大核心模块,量化非功能需求,完善接口与数据规范 |
---
## 2. 总体描述
### 2.1 产品愿景
打造一个集监控、预警、诊断、修复于一体的智能化 Hadoop 运维平台。通过 AI 赋能,实现从“被动告警”到“主动诊断”的跨越
### 2.2 用户特征
| 角色 | 技能水平 | 使用场景 |
| :--- | :--- | :--- |
| **管理员** | 高 | 系统全局配置、用户权限分配、集群接入审核 |
| **运维人员** | 中 | 执行日常诊断任务、查看性能趋势、下发修复指令 |
| **审计员** | 低 | 查看系统操作日志、导出合规报表 |
### 2.3 运行环境
#### 硬件环境
- **服务器**: CPU 2核+, 内存 4GB+, 磁盘 20GB+ (SSD 推荐)
- **网络**: 后端服务器需具备访问 Hadoop 集群所有节点的 SSH 权限
#### 软件环境
- **操作系统**: Linux (Ubuntu 20.04+ / CentOS 7.9+)
- **数据库**: PostgreSQL 13.0+
- **后端技术栈**: Python 3.9+, FastAPI, SQLAlchemy, LangChain
- **前端技术栈**: Node.js 18+, Vue 3.4+, Element Plus
- **浏览器**: Chrome 90+, Firefox 88+, Edge 91+
### 2.4 设计与实现约束
- **技术栈约束**: 必须使用异步驱动Asyncio以支持高并发采集。
- **安全性约束**: 敏感配置(如 SSH 密码、API Key必须加密存储符合数据隐私规范。
- **扩展性约束**: 采集引擎必须支持多集群并行接入。
---
## 3. 功能需求
### 3.1 功能模块划分
系统划分为五个核心模块认证授权、集群管理、自动化采集、AI 智能诊断、运维审计。
### 3.2 单个功能详细说明
#### 3.2.1 集群注册 (F-01-01)
- **前置条件**: 用户具有管理员或运维权限。
- **操作流程**:
1. 输入集群名称及 NameNode IP 地址。
2. 提供 SSH 认证凭据(用户名/密码或私钥)。
3. 系统触发自动校验逻辑。
- **输入**: 集群元数据 JSON。
- **输出**: 注册成功/失败状态及校验报告。
- **异常处理**: 若 SSH 连接超时(默认 10s提示用户检查防火墙或凭据。
#### 3.2.2 AI 流式诊断 (F-04-01)
- **前置条件**: 已接入至少一个健康的 Hadoop 集群。
- **操作流程**:
1. 用户在聊天框输入故障现象如“HDFS 写入速度慢”)。
2. 后端建立 SSE 连接。
3. AI 自动调用工具获取节点指标和日志。
- **输入**: 用户自然语言指令。
- **输出**: Markdown 格式的流式分析结果。
### 3.3 用例图与流程图
```mermaid
graph LR
User((运维人员))
User -->|注册| Cluster[集群管理]
User -->|查询| Log[日志检索]
User -->|咨询| AI[AI 智能诊断]
AI -->|调用工具| SSH[远程 SSH 执行]
Log -->|读取| DB[(PostgreSQL)]
```
---
## 4. 非功能需求
### 4.1 性能需求
- **响应时间**: 基础数据查询 API 响应时间 ≤ 500msAI 首字输出延迟 ≤ 2s。
- **并发量**: 支持 100 个并发采集任务同时进行。
- **吞吐量**: 日志增量写入速度支持 5000 条/秒。
### 4.2 可靠性需求
- **MTBF**: 平均无故障运行时间 ≥ 2000 小时。
- **恢复时间**: 系统进程崩溃后,由 Supervisor 或 Docker 自动拉起,恢复时间 ≤ 30s。
- **数据备份**: PostgreSQL 每日凌晨 3:00 执行增量备份。
### 4.3 易用性需求
- **操作复杂度**: 运维人员通过 3 次点击即可完成一次深度故障诊断。
- **界面语言**: 全中文界面,支持后续多语言扩展。
### 4.4 安全性需求
- **认证**: 全站采用 JWT 动态令牌,有效期 24 小时。
- **加密**: 用户密码采用 Bcrypt 强哈希算法;传输过程支持 HTTPS。
### 4.5 兼容性需求
- **Hadoop 版本**: 兼容 Apache Hadoop 2.7.x 至 3.3.x 版本。
- **终端适配**: 支持 1920x1080 及以上分辨率的桌面端访问。
---
## 5. 数据需求
- 数据库PostgreSQLJSONB/UUID/INET/TIMESTAMPTZ参见建表脚本与数据字典。
- 关键实体:`clusters`、`nodes`、`system_logs`、`fault_records`、`exec_logs`、`app_configurations`、`users`、`audit_logs`、`roles`、`permissions`、`user_role_mapping`、`role_permission_mapping`、`user_cluster_mapping`。
- 约束:唯一键与外键完整;检查约束覆盖状态与枚举值;索引优化高频查询。
## 6. 外部接口
- 日志采集Flume → `POST /api/log/auto-upload`
- 集群状态:`GET /api/cluster/status`(可缓存 Redis
- 诊断:`POST /api/llm/diagnose`;修复报告:`POST /api/llm/report`。
- 故障与执行:`/api/faults/*`、`/api/exec-logs/*`。
- 告警与配置:`/api/alerts/*`、`/api/configs/*`。
- 审计与用户:`/api/audit-logs/*`、`/api/admin/*`。
## 7. 状态机定义
- 故障状态:`detected → analyzing → repairing → {resolved | failed}`;事件驱动与审批联动(高风险需审批)。
- 执行状态:`pending → running → {success | failed | timeout}`;时长与退出码记录完整。
## 8. 用例与原型映射
- 集群列表/注册 → `#cluster-list`、`clusters`、`/api/clusters`。
- 仪表板监控 → `#dashboard`、`nodes`、`/api/cluster/status`、WS `/ws/status`
- 日志查询 → `#logs`、`system_logs`、`/api/logs`。
- 故障诊断 → `#diagnosis`、`fault_records/exec_logs`、`/api/llm/diagnose`。
- 故障中心 → `#fault-center`、`fault_records`、`/api/faults/*`。
- 执行日志 → `#exec-logs`、`exec_logs`、`/api/exec-logs/*`。
- 告警配置 → `#alert-config`、`app_configurations`、`/api/alerts/*`。
- 用户管理/角色 → `#user-management/#role-assignment`、`users/roles/user_role_mapping`、`/api/admin/*`。
- 权限策略 → `#permission-policy`、`roles/permissions/role_permission_mapping`。
- 审计日志 → `#audit-logs`、`audit_logs`、`/api/audit-logs/*`。
## 9. 验收标准
- 端到端闭环:日志→诊断→修复→审计→报表。
- 指标达标:准确率/时效性/复发率/KPI 满足“前景与范围文档”定义。
- 安全合规:权限与审计完整,敏感信息管理符合最佳实践。
- 文档齐备API、数据字典、ER 与部署说明一致。
## 10. 需求追踪矩阵(摘要)
- 功能模块 ↔ 前端页面 ↔ 后端接口 ↔ 数据表 ↔ 指标/验证用例。
- 用于测试与验收阶段交叉核对,确保每项需求均有实现与验证。
### 5.1 数据结构 (核心表)
- **clusters**: id (PK), uuid, name, namenode_ip, ssh_user, ssh_password_encrypted.
- **hadoop_logs**: log_id (PK), cluster_id (FK), node_host, level, info, log_time.
- **node_metrics**: id (PK), node_id, cpu_usage, memory_usage, created_at.
### 5.2 数据字典
| 字段名 | 类型 | 取值范围 | 说明 |
| :--- | :--- | :--- | :--- |
| `health_status` | varchar | {healthy, warning, error, unknown} | 集群健康状态 |
| `level` | varchar | {INFO, WARN, ERROR, FATAL} | 日志级别 |
### 5.3 数据流转流程
1. **采集阶段**: `SSH 采集器` -> `内存缓冲区` -> `PostgreSQL`
2. **诊断阶段**: `用户提问` -> `AI Agent` -> `调用 SQL 检索` -> `返回前端`
---
## 6. 接口需求
### 6.1 用户接口
- **主界面**: 采用侧边导航栏架构,左侧为功能菜单,右侧为数据展示区。
- **AI 对话窗**: 浮动于页面右下角,支持代码块高亮显示。
### 6.2 内部接口
- **采集引擎接口**: `InternalWorker.start_collection(cluster_id)`
- **诊断服务接口**: `AIDiagnostic.run(context_json)`
### 6.3 外部接口
- **RESTful API**: 遵循 OpenAPI 3.0 标准。
- **认证方式**: Header 携带 `Authorization: Bearer <token>`
---
## 7. 验收标准
### 7.1 功能验收
- **用例**: 注册一个不存在的 IP。
- **预期结果**: 系统在 15s 内返回 `Connection Timeout` 错误,且不写入数据库。
### 7.2 性能验收
- **压测**: 使用 JMeter 模拟 50 个并发用户请求 `/api/v1/logs`
- **预期结果**: 95% 的请求响应时间小于 800ms系统无 OOM 报错。
---
## 8. 附录
### 8.1 术语表
- **Bcrypt**: 一种跨平台的自适应哈希算法,用于存储密码。
- **asyncpg**: 高性能的异步 PostgreSQL 驱动。
### 8.2 图表集
- 系统架构图、ER 实体关系图(详见项目源码 `doc/diagrams/`)。
### 8.3 需求变更记录
| 变更日期 | 变更项 | 变更原因 | 状态 |
| :--- | :--- | :--- | :--- |
| 2026-01-10 | 增加 SSE 支持 | 提升 AI 交互体验 | 已完成 |

@ -1,57 +1,56 @@
# 基于Hadoop的故障检测与自动恢复项目 前景与范围文档
# 基于 Hadoop 的故障检测与智能诊断项目 - 前景与范围文档
## 1. 项目愿景
- 构建“采集→处理→诊断→修复→评估”的自动化闭环,降低运维成本、提升稳定性与响应速度。
- 面向多集群、复杂日志场景,提供可视化监控、智能诊断与安全可控的自动修复能力。
- 引入多智能体架构,分别承担日志解析、诊断、修复与风险策略,提升扩展性与可维护性。
本项目旨在构建一个集“实时监控、日志采集、智能诊断、自动化运维”于一体的 Hadoop 集群治理平台。通过引入大语言模型LLM智能体将复杂的 Hadoop 日志与运行指标转化为直观的诊断报告与操作建议,降低运维门槛,提升集群稳定性。
## 2. 业务目标
- 实时感知 Hadoop 集群运行状态并发现异常。
- 将结构化日志与历史数据驱动的诊断结果转化为可执行修复指令
- 在风险可控与审计可追的前提下自动闭环修复
- 为运维人员提供一站式操作入口与报表能力
- **实时感知**: 自动化采集集群节点 CPU、内存等核心指标秒级感知异常。
- **智能分析**: 利用 AI 智能体自动解析 Hadoop 远程日志,准确定位 NameNode、DataNode 等组件故障
- **高效采集**: 建立基于 SSH 的增量日志采集链路,支持多集群、多节点并发处理
- **闭环管理**: 提供从故障发现、AI 诊断、工具修复到执行审计的完整闭环流程
## 3. 目标用户与角色
- 管理员admin系统配置、用户与角色、策略管理、审批。
- 操作员operator查看监控、执行修复、管理故障与执行日志。
- 观察员observer/viewer只读查看监控、日志与报表。
## 4. 使用场景
- 日常巡检:在“仪表板”查看节点健康、趋势与异常指示。
- 故障处理:在“故障中心”查看故障详情,触发诊断与修复,跟踪执行记录。
- 日志分析:在“日志查询”检索多维度日志并提交智能分析。
- 安全合规:针对关键操作记录审计日志,支持导出留存。
- 配置治理:在“告警配置”设置阈值与通知渠道,联动规则执行。
## 5. 项目范围In/Out
- In Scope
- 前端页面(参考 `src/fronted/index.html`
- 集群列表/注册、仪表板监控、日志查询、故障诊断多智能体原型、故障中心CRUD、执行日志CRUD、告警配置规则管理原型、用户管理、角色分配、权限策略、审计日志、登录/注册/审批。
- 后端服务FastAPI日志接收与结构化、集群状态查询、诊断接口、大模型调用、修复执行编排、审计与权限登录与认证JWT
- 多智能体编排DiagnosisAgent、RepairAgent、PolicyAgent、LogParserAgent。
- 数据存储PostgreSQLJSONB/UUID/INET/TIMESTAMPTZRedis 缓存与限流。
- 可观测性Prometheus 指标采集、Grafana 展示。
- Out of Scope
- 跨租户计费与合同管理、第三方 CMDB 深度集成、复杂工单系统。
- 非 Hadoop 生态的深度治理功能(如 Kubernetes 全面管控)。
## 6. 依赖与约束
- 技术栈FastAPI + SQLAlchemy + asyncpgPostgreSQL 14+RedisApache FlumeVue3/Vite/Element Plus/EChartsWebSocketPrometheus/Grafana。
- 安全合规:严格的角色/权限/审计与敏感信息管理;禁止在代码与配置中明文保存秘钥。
- 性能约束:常用页面查询 P95 ≤ 500ms诊断与修复链路端到端 ≤ 5 分钟。
- **系统管理员 (Admin)**: 负责集群注册、用户权限分配、全局系统配置。
- **运维工程师 (Operator)**: 负责日常监控、触发 AI 诊断、执行远程修复命令、查看执行日志。
- **观察员 (Observer)**: 仅限查看监控报表、日志信息及诊断历史,无操作权限。
## 4. 关键使用场景
- **集群健康监控**: 在仪表板实时查看各节点负载趋势,及时发现性能瓶颈。
- **自动化日志巡检**: 系统自动增量采集 Hadoop 关键组件日志,运维人员可随时检索历史记录。
- **AI 辅助故障诊断**: 针对特定异常,调用诊断智能体,由其自动收集日志并生成详细的根因分析报告。
- **远程指令执行**: 无需登录服务器,直接通过 Web 端向指定节点发送运维指令,并自动记录执行过程。
## 5. 项目范围 (In/Out)
### 5.1 包含范围 (In Scope)
- **后端服务 (FastAPI)**:
- 基于 JWT 的用户认证与权限控制。
- 基于 SSH 的远程命令执行、文件读取及增量日志采集 (log_collector)。
- 周期性的集群指标采集与存储 (metrics_worker)。
- 集成 LangChain 与 OpenAI 的诊断智能体 (diagnosis_agent)。
- **数据管理**:
- PostgreSQL 持久化存储用户、集群、节点、日志及指标数据。
- 动态指标表结构保障机制。
- **AI 能力**:
- 故障根因分析、修复建议生成、远程工具链自动调用。
### 5.2 不包含范围 (Out of Scope)
- 跨租户的复杂计费系统。
- 深度集成第三方 CMDB 或企业级 OA 流程。
- 非 Hadoop 生态(如 K8s 内部治理)的深度管控。
## 6. 技术约束与依赖
- **后端**: Python 3.10+ / FastAPI / SQLAlchemy (Async) / Paramiko (SSH)。
- **数据库**: PostgreSQL 14+。
- **AI 服务**: OpenAI API / LangChain。
- **部署**: 支持 Linux 环境一键脚本启动,支持 SOCKS5 代理通信。
## 7. 风险与应对
- 大模型稳定性双供应商与重试PolicyAgent 风险过滤与审批策略。
- 修复脚本风险分级管控low/medium/high高风险需人工审批与备份。
- 日志采集质量Flume 异常监控与补偿,数据丢失报警与追溯。
- 数据一致性:关键事件事务化与审计留痕;定期备份与恢复演练。
## 8. 里程碑与交付物
- M1 基础环境:集群与存储、前后端骨架、日志采集链路联通。
- M2 核心功能:仪表板、日志查询、故障中心与执行日志 CRUD诊断接口闭环。
- M3 多智能体:诊断/修复/策略编排,上线审批流与风控策略。
- M4 保障与上线:测试报告、部署与监控面板、运行评估与优化计划。
## 9. 成功度量KPI
- 诊断准确率 ≥ 85%;故障闭环时效 ≤ 5 分钟;修复复发率 ≤ 5%。
- 关键页面 P95 响应 ≤ 500ms错误率 ≤ 1%WebSocket 在线率 ≥ 99%。
- **SSH 稳定性**: 通过连接池管理与超时重试机制应对网络波动。
- **AI 幻觉风险**: 引入诊断报告人工审核机制,关键修复指令需二次确认。
- **性能挑战**: 针对大规模日志采集,采用线程化并发处理与批量入库策略。
- **安全性**: 严格管理 SSH 密钥与 JWT 令牌,所有敏感操作强制审计留痕。
## 8. 成功度量 (KPI)
- **诊断准确率**: AI 提供的故障根因与实际匹配度 ≥ 85%。
- **响应时效**: 节点异常感知延迟 ≤ 30 秒AI 诊断报告生成时间 ≤ 2 分钟。
- **系统可用性**: 后端 API 可用率 ≥ 99.9%。

@ -1,87 +1,60 @@
# 项目需求分析基于Hadoop的故障检测与自动恢复
## 项目概述
- 目标:为 Hadoop 运维提供监控、日志分析、智能诊断与自动修复的一体化平台。
- 范围Web 应用(前端、后端、多智能体编排)、日志采集、数据库与缓存、可观测性。
- 技术栈FastAPI + SQLAlchemy异步`asyncpg`、PostgreSQL 14+`JSONB/UUID/INET/TIMESTAMPTZ`、Flume、前端静态站点原型。
## 背景与问题陈述
- Hadoop 集群在生产中存在多源日志、跨节点事件关联困难、故障定位成本高、修复操作规范性不足等问题。
- 需要一个统一的故障中心:能从日志线索到诊断建议、审批把关与执行记录形成可审计闭环,并提供指标、报表与可视化。
## 目标与成功标准
- 核心闭环:日志→诊断→修复→审计→报表;支持状态机与高风险审批。
- 成功标准:接口与前端原型连通、关键场景可演示、性能与安全指标达基线、文档与数据模型一致。
## 用户角色与场景
- 管理员admin配置与审批、规则管理、用户与权限、全局审计与报表。
- 操作员operator诊断与修复执行、故障中心操作、仪表板监控。
- 观察员observer只读查看集群、日志、执行记录、报表
- 角色可在前端原型中映射,路由控制参考 `src/fronted/utils/auth.js`
## 关键业务流程
- 日志采集Flume 推送结构化日志 → 后端预处理与入库 → 前端查询分页展示。
- 故障诊断:选择上下文日志 → LLM 诊断DiagnosisAgent→ 风险评估PolicyAgent→ 建议与报告生成。
- 修复执行:审批通过 → 执行脚本命令 → 标准输出与错误输出入库 → 结果推送与审计。
- WS 推送:仪表板状态与诊断结果实时更新,断线重连策略。
- 时序参考:`doc/project/diagrams/时序图.puml`。
## 功能需求分解(与前端原型/后端接口/数据表映射)
- 身份认证与注册审批F-01`#login/#register/#user-management``POST /api/v1/user/login`、`POST /api/v1/user/register`、`GET /api/v1/user/me`;数据 `users/audit_logs/roles/user_role_mapping`
- 集群列表与注册F-02`#cluster-list``/api/clusters`;数据 `clusters(uuid,name,type,node_count,health_status,config_info)`
- 仪表板监控F-03`#dashboard``/api/cluster/status`、WS `/ws/status`;数据 `nodes(...)`
- 日志查询F-04`#logs``/api/logs?...`;数据 `system_logs(log_id,timestamp,host,service,log_level,message,...)`
- 故障诊断F-05`#diagnosis``POST /api/llm/diagnose`、`POST /api/llm/report`;数据 `fault_records/exec_logs`
- 故障中心F-06`#fault-center``/api/faults/*`、`POST /api/faults/{id}/transition`;数据 `fault_records(...)`
- 执行日志F-07`#exec-logs``/api/exec-logs/*`;数据 `exec_logs(...)`
- 告警配置F-08`#alert-config``/api/alerts/*`;数据 `app_configurations(config_type='alert_rule',...)`
- 用户管理与角色分配F-09`#user-management/#role-assignment``/api/admin/*`;数据 `users/roles/user_role_mapping`
- 权限策略F-10`#permission-policy``/api/policies/*`;数据 `roles/permissions/role_permission_mapping`
- 审计日志F-11`#audit-logs``/api/audit-logs/*`;数据 `audit_logs(...)`
- WebSocket 推送F-12`#dashboard`、`/ws/status`、`/ws/diagnose`;消息格式统一与重连策略。
- 详细 SRS`doc/project/需求规格说明书.md:19-103`
## 接口约定与版本策略
- API 前缀:`/api/v1`(见 `src/backend/app/main.py:15-18` 路由挂载)。
- 返回结构:列表 `{ total, list }`;错误包络 `{ code, message, detail, traceId }`(见 `src/backend/README.md:47-55`)。
- 统一状态码与业务码映射:参考团队约定(见周报 `doc/process/weekly/week-9/...`)。
- 时间与类型规范:`TIMESTAMPTZ`/`JSONB` 对齐 PostgreSQL 原生类型。
## 非功能需求与指标
- 性能:核心查询 P95 ≤ 500msWS 延迟 ≤ 500ms后端并发 ≥ 1k 连接稳定(见 `doc/project/前后端启动前交流确认清单.md:125`)。
- 安全JWT、CORS 白名单、RBAC、速率限制、审计敏感信息通过环境变量管理`DATABASE_URL/JWT_SECRET`)。
- 可靠性:数据库备份与恢复演练;关键链路重试与降级。
- 可观测性Prometheus 指标、Grafana 看板、日志分级与 TraceID。
- 可维护性与可用性模块化、组件化、ARIA 可访问性与清晰交互反馈。
## 数据模型与约束摘要
- 关键实体:`clusters`、`nodes`、`system_logs`、`fault_records`、`exec_logs`、`app_configurations`、`users`、`audit_logs`、`roles`、`permissions`、`user_role_mapping`、`role_permission_mapping`、`user_cluster_mapping`。
- 约束:唯一键与外键完整;检查约束覆盖状态与枚举值;高频查询索引覆盖。
- 参考:`doc/project/数据库设计文档.md`、`doc/project/数据库建表脚本_postgres.sql`、`doc/project/数据字典.md`。
## 当前实现基线(便于联调)
- 后端入口:`src/backend/app/main.py:1-18`CORS 允许所有来源(开发阶段)。
- 基础路由:`/api/v1/health`、`/api/v1/clusters`、`/api/v1/faults`、`/api/v1/logs`(见路由目录)。
- 环境变量加载:`src/backend/app/config.py:6-9`;数据库会话:`src/backend/app/db.py:1-10`。
- 前端原型:`src/fronted/index.html`;导航与权限:`src/fronted/utils/navigation.js`、`src/fronted/utils/auth.js`。
## 里程碑与交付
- M1接口与数据模型最小可用列表与健康检查可演示
- M2登录/注册与 JWT 完成RBAC 初版;审计入库。
- M3诊断与修复闭环含审批与执行日志报表初版。
- M4性能与监控基线达标安全策略落地文档齐备。
## 验收标准
- 端到端闭环可演示;接口与页面一致;关键指标达基线;审计与安全策略有效。
- 文档一致性SRS、数据字典、建表脚本与接口文档一致代码路径与接口前缀清晰可查。
## 风险与应对
- 并发一致性:采用乐观/幂等策略,后续引入锁与事务细化;测试覆盖关键状态转换。
- 安全复杂度JWT 与角色权限细化,接口白名单与速率控制;日志审计与告警联动。
- 集成复杂度Flume/Hadoop 环节逐步引入,保持后端与前端最小闭环可演示。
## 开放问题与下一步
- 诊断与审批策略边界需与业务方细化;高风险分类与联动规则待完善。
- 报表与指标体系细化准确率、时效性、复发率、KPI 定义)。
- WebSocket 与队列/缓存(如 Redis集成方案与参数调优连接池、超时、重试
# 基于 Hadoop 的故障检测与智能诊断项目 - 需求分析
## 1. 业务流程分析
### 1.1 指标采集流程 (Metrics Collection)
1. **调度**: `metrics_worker.py` 周期性触发采集任务。
2. **连接**: 通过 `ssh_utils.py` 获取对应节点的 SSH 会话(支持 SOCKS5 代理)。
3. **执行**: 远程执行系统命令(如 `top`, `free`)获取 CPU 和内存使用率。
4. **持久化**: 数据经过处理后存入 `node_metrics``cluster_metrics` 表,并支持动态 Schema 维护。
### 1.2 日志采集与读取流程 (Log Collection)
1. **实时读取**: 用户通过 `/hadoop/logs/{node}/{type}` 接口请求日志,系统通过 SSH 实时 `cat``tail` 远程文件。
2. **自动采集**: `log_collector.py` 维护多个任务线程,利用 `tail -F` 模式监控远程 Hadoop 日志文件的增量更新。
3. **入库**: 采集到的原始日志流经解析后,批量存入 `hadoop_logs` 表,供后续 AI 诊断和历史查询使用。
### 1.3 AI 智能诊断流程 (AI Diagnosis)
1. **触发**: 用户在 UI 或通过 API 发起对话,描述故障现象。
2. **编排**: `diagnosis_agent.py` 接收请求,利用 OpenAI Tool Calling 协议决定下一步行动。
3. **工具执行**: 智能体根据需要调用后端定义的工具,如:
- `get_cluster_info`: 获取集群节点列表。
- `read_node_logs`: 读取特定节点的实时日志。
- `execute_remote_command`: 在节点上执行诊断指令。
4. **总结**: 智能体整合工具返回的上下文,生成结构化的根因分析报告及修复建议。
## 2. 功能需求分解
### 2.1 基础设施与管理 (F-01)
- **集群注册**: 记录 NameNode/ResourceManager IP 及 SSH 凭据,支持连通性校验。
- **节点自动发现**: 获取集群内的所有主机信息及其角色。
### 2.2 监控与告警 (F-02)
- **实时看板**: 展示集群整体及单个节点的 CPU/内存 负载曲线。
- **状态监控**: 自动识别节点在线/离线状态。
### 2.3 日志管理 (F-03)
- **多节点检索**: 支持按集群、节点、日志类型NameNode/DataNode/Audit 等)进行分页查询。
- **文件管理**: 自动探测远程 Hadoop 日志目录下的文件列表。
### 2.4 智能运维 (F-04)
- **AI 对话**: 提供 SSE 流式对话接口,支持长上下文故障分析。
- **任务审计**: 记录所有通过平台执行的远程命令及其输出结果 (Exec Logs)。
## 3. 非功能需求
### 3.1 性能要求
- **并发采集**: 日志采集器需支持至少 50 个节点并发 tail 而不阻塞主服务。
- **查询响应**: 数据库百万级日志量下,常用过滤查询响应时间应在 1s 以内。
### 3.2 安全性要求
- **凭据加密**: 数据库存储的 SSH 密码应加密处理。
- **权限隔离**: 不同角色的用户仅能访问其所属集群的数据。
### 3.3 可扩展性
- **工具扩展**: AI 智能体应能通过简单的接口定义轻松接入新的运维工具。
- **Schema 动态性**: 指标表应能根据新采集的维度自动扩展列。
## 4. 接口协议约定
- **RESTful API**: 遵循 `/api/v1` 前缀。
- **SSE (Server-Sent Events)**: AI 对话采用流式输出,确保前端实时展示诊断进度。
- **WebSocket (可选)**: 用于实时指标推送。

@ -0,0 +1,226 @@
# Frontend Vue Project
> **项目负责人**: 邢远鑫
> **技术栈**: Vue.js 3.x + TypeScript + Vite + Element Plus
> **状态**: 🚀 Active Development
## 1. 项目概述 (Project Overview)
**Frontend Vue** 是一个基于现代化前端技术栈构建的企业级集群管理与诊断平台控制台。该项目旨在为大数据运维团队提供高效、直观的图形化界面,用于监控集群状态、分析执行日志以及进行故障自动化诊断。
### 核心价值
- **可视化监控**: 实时展示集群节点状态、资源利用率及关键性能指标。
- **智能诊断**: 集成自动化诊断工具,快速定位 Hadoop/Spark 等组件的运行异常。
- **日志分析**: 提供强大的日志检索与分析界面,支持多维度过滤。
- **安全可控**: 完善的 RBAC 权限体系,确保操作安全。
---
## 2. 项目结构说明 (Project Structure)
本项目采用模块化的目录结构,核心逻辑收敛于 `src/app`,确保关注点分离。
```text
frontend-vue/
├── public/ # 静态资源 (favicon, robots.txt)
├── src/
│ └── app/ # 应用核心代码
│ ├── api/ # API 接口定义与服务封装
│ ├── components/ # 全局公共组件
│ ├── composables/ # Vue Composables (组合式函数)
│ ├── constants/ # 常量定义 (枚举, 配置)
│ ├── lib/ # 核心工具库 (Axios 封装, 遥测, 工具函数)
│ ├── locales/ # i18n 国际化资源
│ ├── router/ # 路由配置与权限守卫
│ ├── stores/ # Pinia 状态管理仓库
│ ├── styles/ # 全局样式 (SASS/CSS)
│ ├── types/ # TypeScript 类型定义
│ ├── views/ # 页面视图 (按业务模块划分)
│ ├── App.vue # 根组件
│ └── main.ts # 应用入口
├── tests/ # 测试文件目录
├── e2e/ # E2E 测试用例 (Playwright)
├── scripts/ # 构建与辅助脚本
├── .eslintrc.cjs # ESLint 配置
├── index.html # 入口 HTML
├── package.json # 项目依赖与脚本
├── pnpm-lock.yaml # 依赖锁定文件
├── tsconfig.json # TypeScript 配置
├── vite.config.ts # Vite 构建配置
└── vitest.config.ts # Vitest 测试配置
```
### 核心配置文件
- **`vite.config.ts`**: 配置了路径别名 (`@/`), API 代理, 生产环境分包策略 (Manual Chunks) 及 CSS 预处理。
- **`tsconfig.json`**: TypeScript 严格模式配置,目标版本 ES2020。
- **`playwright.config.ts`**: 端到端测试的浏览器与运行环境配置。
---
## 3. 开发环境配置 (Development Setup)
### 前置要求
- **Node.js**: `>=18.12.0` (推荐 LTS 版本)
- **包管理器**: `pnpm` (本项目强制使用 pnpm 以确保依赖一致性)
- **操作系统**: macOS / Linux / Windows (WSL2 推荐)
### 环境变量
项目使用 `.env` 文件体系管理环境变量。请在根目录创建 `.env.local`用于本地开发覆盖:
```properties
# .env (默认配置)
VITE_API_TARGET=http://localhost:8000
VITE_DEV_HOST=0.0.0.0
VITE_TELEMETRY_ENABLED=true
VITE_AUTH_REFRESH_ENABLED=true
```
### IDE 推荐配置 (VS Code)
建议安装以下插件以获得最佳开发体验:
- **Vue - Official (Volar)**: 必须安装,提供 Vue 3 语法支持。
- **ESLint**: 代码质量检查。
- **Prettier - Code formatter**: 代码格式化。
- **Tailwind CSS IntelliSense**: 如果项目中引入了 Tailwind。
- **EditorConfig for VS Code**: 保持跨编辑器风格一致。
---
## 4. 开发指南 (Development Guide)
### 4.1 初始化项目
```bash
# 安装依赖
pnpm install
# 检查环境健康度
pnpm run typecheck
```
### 4.2 启动开发服务器
```bash
pnpm dev
# 默认运行在 http://localhost:5173
```
### 4.3 代码规范与质量
项目集成了严格的代码规范检查:
- **Lint**: `pnpm run lint` (检查代码质量)
- **Fix**: `pnpm run lint:fix` (自动修复简单错误)
- **Type Check**: `pnpm run typecheck` (TypeScript 类型检查)
### 4.4 Git 提交规范
建议遵循 [Conventional Commits](https://www.conventionalcommits.org/) 规范:
- `feat`: 新功能
- `fix`: 修复 Bug
- `docs`: 文档变更
- `style`: 格式调整 (不影响逻辑)
- `refactor`: 重构
- `perf`: 性能优化
- `test`: 测试相关
---
## 5. 构建与部署 (Build & Deploy)
### 5.1 生产环境构建
```bash
pnpm build
```
构建产物将输出到 `dist/` 目录。
### 5.2 Docker 部署
项目支持容器化部署。在根目录创建 `Dockerfile`
```dockerfile
# Build Stage
FROM node:18-alpine as builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
# Production Stage
FROM nginx:stable-alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```
### 5.3 CI/CD 流程建议
推荐使用 GitHub Actions 或 GitLab CI 实现自动化:
1. **Push 触发**: 运行 `pnpm lint``pnpm run test`
2. **Merge 触发**: 运行构建 `pnpm build` 并推送 Docker 镜像。
3. **Release 触发**: 部署到生产环境 Kubernetes 集群。
---
## 6. 技术亮点 (Highlights)
- **🚀 极速构建**: 基于 **Vite 5**,实现毫秒级冷启动与 HMR 热更新。
- **🛡️ 企业级鉴权**:
- 实现了基于 **JWT** 的双 Token (Access + Refresh) 认证机制。
- Axios 拦截器自动处理 401 过期与静默刷新。
- 细粒度的 **RBAC** 路由守卫与按钮级权限控制。
- **📊 深度可观测性**:
- 集成 ECharts 实现复杂的数据可视化。
- 封装 Telemetry 模块,自动采集 API 耗时与前端错误日志。
- **📦 工程化实践**:
- 完整的 TypeScript 类型定义。
- 统一的 API 错误处理层,将后端异常转化为友好的 UI 提示。
---
## 7. 测试方案 (Testing Strategy)
### 7.1 单元测试 (Unit Test)
使用 **Vitest** 进行组件与逻辑测试。
```bash
# 运行单元测试
pnpm test
# 监听模式
pnpm run test:watch
```
### 7.2 端到端测试 (E2E Test)
使用 **Playwright** 进行全链路测试,覆盖登录、核心业务流程。
```bash
# 运行 E2E 测试
pnpm run e2e
# 带 UI 界面运行 (调试用)
pnpm run e2e:ui
```
### 7.3 测试覆盖率
```bash
pnpm run test --coverage
```
---
_Generated for Frontend Vue Project_

@ -12,7 +12,7 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/app/main.ts"></script>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

@ -36,7 +36,7 @@
</el-tooltip>
<el-tooltip :content="isFullscreen ? '退出全屏' : '全屏显示'" placement="bottom">
<el-button link @click="toggleFullscreen" class="u-hidden-mobile">
<el-button link @click="toggleFullscreen">
<el-icon :size="20">
<FullScreen v-if="!isFullscreen" />
<Aim v-else />

@ -1,5 +1,5 @@
<template>
<div class="resizer-bar" :class="barClass" @mousedown="start">
<div class="resizer-bar" :class="barClass" @pointerdown="start">
<div class="resizer-handle"></div>
</div>
</template>
@ -26,7 +26,7 @@ const emit = defineEmits<{
let isDragging = false;
function computePercent(e: MouseEvent) {
function computePercent(e: PointerEvent) {
const containerRect = props.container?.getBoundingClientRect();
if (!containerRect) return null;
if (props.isMobile) {
@ -35,7 +35,7 @@ function computePercent(e: MouseEvent) {
return ((e.clientX - containerRect.left) / containerRect.width) * 100;
}
function onMove(e: MouseEvent) {
function onMove(e: PointerEvent) {
if (!isDragging) return;
const next = computePercent(e);
if (next == null) return;
@ -52,19 +52,23 @@ function stop() {
if (!isDragging) return;
isDragging = false;
emit("dragging", false);
document.removeEventListener("mousemove", onMove);
document.removeEventListener("mouseup", stop);
document.removeEventListener("pointermove", onMove);
document.removeEventListener("pointerup", stop);
document.removeEventListener("pointercancel", stop);
document.body.style.cursor = "";
document.body.style.userSelect = "";
}
function start(e: MouseEvent) {
function start(e: PointerEvent) {
if (!props.container) return;
//
(e.target as HTMLElement).setPointerCapture(e.pointerId);
e.preventDefault();
isDragging = true;
emit("dragging", true);
document.addEventListener("mousemove", onMove);
document.addEventListener("mouseup", stop);
document.addEventListener("pointermove", onMove);
document.addEventListener("pointerup", stop);
document.addEventListener("pointercancel", stop);
document.body.style.cursor = props.isMobile ? "row-resize" : "col-resize";
document.body.style.userSelect = "none";
}
@ -83,6 +87,8 @@ onBeforeUnmount(() => stop());
transition: background 0.2s;
z-index: 10;
flex-shrink: 0;
/* 禁止触摸默认行为(如滚动),确保 pointer 事件正常工作 */
touch-action: none;
}
.resizer-bar:hover {

@ -140,6 +140,14 @@ api.interceptors.response.use(
if (status === 401) {
const auth = useAuthStore()
const url = error.config?.url || ''
// 如果是演示 Token或者是一些基础检查接口不触发自动登出
if (auth.token?.startsWith('demo.') || url.includes('/v1/health') || url.includes('/v1/auth/me')) {
return Promise.reject({
...error,
friendlyMessage: '鉴权失效 (演示模式或基础接口)'
})
}
const current = window.location.hash.startsWith('#') ? window.location.hash.slice(1) : window.location.hash
auth.logout()
if (!window.location.hash.includes('login')) {

@ -58,6 +58,16 @@ export const useAuthStore = defineStore('auth', {
},
async login(username: string, password: string) {
try {
// 特例处理演示账号:账号密码均为 123 时,直接以管理员身份登录
if (username === '123' && password === '123') {
const token = makeDemoToken()
this.user = { id: 888, username: 'demo-admin', role: 'admin' }
this.token = token
this.refreshToken = 'demo-refresh-token'
this.persist()
return { ok: true, role: 'admin' }
}
const r: any = await AuthService.login({ username, password })
const token = r?.token
const refreshToken = r?.refreshToken || r?.refresh_token || r?.tokens?.refresh || null
@ -95,6 +105,15 @@ export const useAuthStore = defineStore('auth', {
return { ok: false, message: e.friendlyMessage || '注册失败' }
}
},
logout() { this.user = null; this.token = null; this.refreshToken = null; this.persist() }
logout() {
// 如果是演示账号,忽略来自 API 拦截器的登出请求,防止在后端异常时被强制踢出
if (this.token?.startsWith('demo.')) {
return
}
this.user = null;
this.token = null;
this.refreshToken = null;
this.persist()
}
}
})

@ -56,6 +56,11 @@
还没有账号
<el-link type="primary" @click="router.push('/register')"></el-link>
</div>
<div class="demo-hint">
<el-icon class="hint-icon"><CircleCheck /></el-icon>
演示账号: <span class="hint-value">123</span> / 密码: <span class="hint-value">123</span>
</div>
</el-form>
<div class="health-status">
@ -76,7 +81,7 @@ import { useUIStore } from "../stores/ui";
import { AuthService } from "../api/auth.service";
import { ElMessage } from "element-plus";
import type { FormInstance, FormRules } from "element-plus";
import { Monitor, User, Lock, Moon, Sunny } from '@element-plus/icons-vue'
import { Monitor, User, Lock, Moon, Sunny, CircleCheck } from '@element-plus/icons-vue'
const router = useRouter();
const route = useRoute();
@ -234,6 +239,29 @@ async function onSubmit() {
margin-top: 8px;
}
.demo-hint {
text-align: center;
font-size: 13px;
color: var(--el-color-info);
margin-top: 16px;
padding: 8px;
border-radius: 6px;
background-color: var(--el-fill-color-light);
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.hint-icon {
color: var(--el-color-success);
}
.hint-value {
color: var(--el-color-primary);
font-weight: 600;
}
.health-status {
text-align: center;
margin-top: 20px;

@ -29,8 +29,8 @@ export default defineConfig(({ mode }) => {
host: devHost,
strictPort: true,
port: devPort,
// 完全关闭 HMR 以屏蔽 HMR 客户端的探测报错
hmr: false,
// HMR 默认开启
// hmr: false,
cors: true,
allowedHosts: allowedHostsEnv.length ? allowedHostsEnv : true,
proxy: {

@ -1,68 +0,0 @@
# Git 隐藏历史 (Reflog)
| 日期 | 版本 (Hash) | 操作/消息 |
| :--- | :--- | :--- |
| 2025-12-29 14:48:30 +0000 | `22e4772` | pull --rebase origin develop (finish): returning to refs/heads/develop |
| 2025-12-29 14:48:30 +0000 | `22e4772` | pull --rebase origin develop (pick): 集群注册_容器ssh连接问题修复 |
| 2025-12-29 14:48:30 +0000 | `f0fccd5` | pull --rebase origin develop (start): checkout f0fccd5c6083cd4dd5a433f4322b318874d3e02b |
| 2025-12-29 14:46:10 +0000 | `8bbf7bb` | commit: 集群注册_容器ssh连接问题修复 |
| 2025-12-29 13:32:14 +0000 | `742b1d0` | pull --rebase origin develop (finish): returning to refs/heads/develop |
| 2025-12-29 13:32:14 +0000 | `742b1d0` | pull --rebase origin develop (pick): 流式输出优化 |
| 2025-12-29 13:32:14 +0000 | `a570f82` | pull --rebase origin develop (start): checkout a570f82e9785853c862ed22bf7f6389d666865af |
| 2025-12-29 13:31:41 +0000 | `c6a821d` | commit: 流式输出优化 |
| 2025-12-29 13:13:50 +0000 | `d4c7cf8` | pull --rebase origin develop (finish): returning to refs/heads/develop |
| 2025-12-29 13:13:50 +0000 | `d4c7cf8` | pull --rebase origin develop (pick): ai聊天流式输出_后端 |
| 2025-12-29 13:13:50 +0000 | `630f637` | pull --rebase origin develop (start): checkout 630f6375f7967824dae3b1bd25b9148f83d79d5c |
| 2025-12-29 13:11:31 +0000 | `47be97e` | commit: ai聊天流式输出_后端 |
| 2025-12-29 11:40:41 +0000 | `a48ae19` | commit: ai联网搜索功能修复 |
| 2025-12-29 11:40:36 +0000 | `28381d4` | commit: ai联网搜索功能修复 |
| 2025-12-29 11:27:20 +0000 | `e3d18fa` | pull origin develop --rebase (finish): returning to refs/heads/develop |
| 2025-12-29 11:27:20 +0000 | `e3d18fa` | pull origin develop --rebase (pick): feat: add description field to cluster registration and fix 500 error |
| 2025-12-29 11:27:20 +0000 | `d52b431` | pull origin develop --rebase (start): checkout d52b431e259798a202afac720292fd4a60fc4e65 |
| 2025-12-29 11:27:19 +0000 | `ddacc09` | commit: feat: add description field to cluster registration and fix 500 error |
| 2025-12-29 11:25:01 +0000 | `b2524d6` | pull origin develop (finish): returning to refs/heads/develop |
| 2025-12-29 11:25:01 +0000 | `b2524d6` | pull origin develop (start): checkout b2524d6ce332061456112fe2e2c7dd57cc61aac6 |
| 2025-12-29 11:21:28 +0000 | `7e74e4d` | commit: 注册集群后端(无连接判断) |
| 2025-12-29 10:14:34 +0000 | `f62455b` | merge test_ai: Fast-forward |
| 2025-12-29 10:13:09 +0000 | `b49b2f7` | checkout: moving from test_ai to develop |
| 2025-12-29 10:10:02 +0000 | `f62455b` | pull origin develop (finish): returning to refs/heads/test_ai |
| 2025-12-29 10:10:02 +0000 | `f62455b` | pull origin develop (pick): ai功能修复_联网搜索工具 |
| 2025-12-29 10:10:02 +0000 | `3ae20a5` | pull origin develop (start): checkout 3ae20a5f67c847e6e3b497b95a09916d7472f946 |
| 2025-12-29 10:03:59 +0000 | `b688b37` | commit: ai功能修复_联网搜索工具 |
| 2025-12-29 09:19:26 +0000 | `b49b2f7` | reset: moving to b49b2f72de |
| 2025-12-29 09:04:27 +0000 | `b49b2f7` | reset: moving to b49b2f72de |
| 2025-12-29 09:03:35 +0000 | `7d7405f` | reset: moving to HEAD |
| 2025-12-29 08:40:31 +0000 | `7d7405f` | reset: moving to origin/develop |
| 2025-12-29 08:23:15 +0000 | `7d7405f` | pull origin develop: Fast-forward |
| 2025-12-29 07:48:15 +0000 | `90eaf53` | checkout: moving from develop to test_ai |
| 2025-12-29 07:46:18 +0000 | `b49b2f7` | commit: ai优化 |
| 2025-12-29 07:45:20 +0000 | `90eaf53` | checkout: moving from test_ai to develop |
| 2025-12-29 07:44:20 +0000 | `90eaf53` | checkout: moving from test_ai to test_ai |
| 2025-12-29 07:43:46 +0000 | `90eaf53` | checkout: moving from develop to test_ai |
| 2025-12-25 17:14:06 +0000 | `90eaf53` | checkout: moving from develop-backup to develop |
| 2025-12-25 17:13:44 +0000 | `90eaf53` | checkout: moving from develop to develop-backup |
| 2025-12-25 17:10:28 +0000 | `90eaf53` | reset: moving to 90eaf5395b |
| 2025-12-25 16:55:43 +0000 | `54393af` | reset: moving to origin/develop |
| 2025-12-25 16:37:03 +0000 | `54393af` | reset: moving to origin/develop |
| 2025-12-21 15:01:46 +0000 | `504a471` | commit: 小组周文档补 |
| 2025-12-21 14:06:56 +0000 | `cbc73bd` | commit: 李涛周文档补 |
| 2025-12-21 13:55:30 +0000 | `5d5b0e8` | pull origin develop (finish): returning to refs/heads/develop |
| 2025-12-21 13:55:30 +0000 | `5d5b0e8` | pull origin develop (pick): 沈永佳周文档 |
| 2025-12-21 13:55:30 +0000 | `33c7d27` | pull origin develop (start): checkout 33c7d27437f902238712c84d09c1c2fb94f9f419 |
| 2025-12-21 13:50:20 +0000 | `ef5314c` | commit: 沈永佳周文档 |
| 2025-12-19 08:37:11 +0000 | `f12e23e` | pull origin develop (finish): returning to refs/heads/develop |
| 2025-12-19 08:37:11 +0000 | `f12e23e` | pull origin develop (pick): users/me |
| 2025-12-19 08:37:11 +0000 | `19cca60` | pull origin develop (start): checkout 19cca60642d7ca9e8ae71081c27066940f2ab5fc |
| 2025-12-19 08:37:06 +0000 | `620afee` | commit: users/me |
| 2025-12-18 12:23:03 +0000 | `0842169` | commit: ai聊天架构优化 |
| 2025-12-18 07:45:08 +0000 | `eb935fa` | commit: 用户-角色映射优化 |
| 2025-12-18 07:08:52 +0000 | `2eb858a` | commit: chat前端联调指南 |
| 2025-12-18 05:26:53 +0000 | `2bda5cc` | pull origin develop: Fast-forward |
| 2025-12-14 15:54:36 +0000 | `bc65fec` | pull origin develop (finish): returning to refs/heads/develop |
| 2025-12-14 15:54:36 +0000 | `bc65fec` | pull origin develop (pick): 后端模型对话V1 |
| 2025-12-14 15:54:36 +0000 | `b6cb7a5` | pull origin develop (start): checkout b6cb7a58d8fbc92e26f6c69d441bbc6fba0880f7 |
| 2025-12-14 15:47:02 +0000 | `4796411` | commit: 后端模型对话V1 |
| 2025-12-14 08:02:42 +0000 | `15be5bb` | pull origin develop: Fast-forward |
| 2025-12-14 07:31:11 +0000 | `2f6fe59` | pull origin develop: Fast-forward |
| 2025-12-12 01:59:32 +0000 | `a7cdecc` | pull origin develop: Fast-forward |
| 2025-12-08 11:07:29 +0000 | `1533785` | clone: from https://bdgit.educoder.net/hnu202326010101/ErrorDetecting.git |

@ -1,2 +0,0 @@
<marquee>阿米诺斯</marquee>
<marquee>666</marquee>

@ -1,37 +0,0 @@
<!DOCTYPE html> <!-- 文档类型声明告诉浏览器这是一个HTML文档 -->
<html lang="zh-CN"> <!-- html是根标签lang属性指定文档语言 -->
<head> <!-- head标签包含文档的元数据如标题、字符集等 -->
<meta charset="UTF-8"> <!-- 指定文档字符编码为UTF-8支持中文等各种语言 -->
<title>HTML标签学习</title> <!-- 网页标题,会显示在浏览器标签页上 -->
</head>
<body> <!-- body标签包含网页的主要内容用户可见的部分 -->
<!-- marquee标签创建滚动文本HTML5中已不推荐使用但仍可工作 -->
<marquee direction="left" behavior="scroll" scrollamount="5">
<!-- direction属性滚动方向可选值有left、right、up、down -->
<!-- behavior属性滚动行为可选值有scroll(持续滚动)、slide(滑动一次)、alternate(来回滚动) -->
<!-- scrollamount属性滚动速度数值越大滚动越快 -->
666
<input/> <!-- 在marquee中嵌套的input标签会随文字一起滚动 -->
</marquee>
<!-- HTML标签的基本语法结构 -->
<!-- <标签名(起始标签)>标签体</标签名(结束标签)> -->
<!-- input标签表单输入元素用于收集用户输入 -->
<!-- type属性指定输入类型如text(文本)、password(密码)、checkbox(复选框)等 -->
<!-- placeholder属性输入框的提示文本当用户未输入内容时显示 -->
<input type="text" placeholder="请输入">
<!-- input标签的两种写法以下两种都是正确的 -->
<input> <!-- 不带结束标记的写法 -->
<input/> <!-- 自闭合标签的写法,推荐使用这种更规范的写法 -->
<!--
HTML标签分类
1. 双标签:有开始和结束标签,如<p></p><div></div>
2. 单标签:只有一个标签,通常以/>结尾,如<input/><img/><br/>
-->
</body>
</html>

@ -1,18 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML标签属性学习</title>
</head>
<body>
<h1>HTML标签属性学习</h1>
<marquee loop="10" bgcolor="green" id="m1">
阿米诺斯
<input type="password" placeholder="请输入">
</marquee>
<br><br>
<input/>
<input disabled>
</body>
</html>

@ -1,15 +0,0 @@
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML基本结构学习</title>
</head>
<body>
<h1>HTML基本结构</h1>
<marquee>
阿米诺斯
<input type="password" placeholder="请输入">
<button>提交</button>
</marquee>
</body>
</html>

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML注释学习</title>
</head>
<body>
<h1>HTML注释学习</h1>
<!-- 这是一个注释 -->
<p>这是一个段落</p>
<marquee>
阿米诺斯
<input type="password" placeholder="请输入">
</marquee>
<input type="text" placeholder="请输入">
<!--
这是一段注释,
用于描述代码的功能或作用。
-->
</body>
</html>

@ -1,12 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML文档声明学习</title>
</head>
<body>
<h1>HTML文档声明学习</h1>
<p>这是一个段落</p>
</body>
</html>

@ -1,12 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML字符编码学习</title>
</head>
<body>
<h1>HTML字符编码学习</h1>
<p>这是一个段落</p>
</body>
</html>

@ -1,18 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML设置语言学习</title>
</head>
<body>
<h1>HTML设置语言学习</h1>
<p>这是一个段落</p>
<marquee>
我爱你
</marquee>
<marquee>
I love you
</marquee>
</body>
</html>

@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML标准结构学习</title>
</head>
<body>
</body>
</html>

@ -1,24 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML排版标签学习</title>
</head>
<body>
<h1>我是一级标题</h1>
<h2>我是二级标题</h2>
<h3>我是三级标题</h3>
<h4>我是四级标题</h4>
<h5>我是五级标题</h5>
<h6>我是六级标题</h6>
<p>我是一个段落</p>
<div>
我是一个div
</div>
<div>
<p>我是一个段落</p>
<p>我是另一个段落</p>
</div>
</body>
</html>

@ -1,83 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML语义化标签学习</title>
</head>
<body>
<!-- 标签默认效果不重要,语义最重要 -->
<!-- 代码的可读性强清晰 -->
<!-- 有利于SEO搜索引擎优化 -->
<!-- 方便设备解析(如屏幕阅读器、盲人阅读器等) -->
<!-- 新闻报道示例展示HTML语义化标签的正确使用 -->
<div class="news-container">
<!-- h1标签表示页面或区块的主标题具有最高的语义重要性 -->
<h1>人工智能技术在教育领域取得重大突破</h1>
<!-- div标签作为内容区块容器用于组织和分组相关内容 -->
<div class="news-meta">
<p>发布时间2024年1月15日 | 来源:科技日报 | 记者:张明</p>
</div>
<!-- div标签新闻正文内容区块 -->
<div class="news-content">
<!-- p标签表示段落用于组织文本内容具有明确的语义含义 -->
<p>近日国内多所知名高校联合发布了一项关于人工智能在教育领域应用的重要研究成果。该研究表明AI技术在个性化学习、智能辅导和教学评估等方面展现出巨大潜力。</p>
<p>据研究团队负责人介绍新开发的AI教学系统能够根据学生的学习习惯和能力水平自动调整教学内容和进度。系统通过分析学生的学习数据为每位学生制定个性化的学习方案有效提高了学习效率。</p>
<p>在为期一年的试点应用中参与测试的学生在各科目成绩上平均提升了25%。特别是在数学和科学类科目中AI辅导系统帮助学生更好地理解复杂概念解决学习难点。</p>
</div>
<!-- div标签相关链接区块 -->
<div class="related-links">
<h2>相关报道</h2>
<p>• 教育部发布AI教育应用指导意见</p>
<p>• 智能教育平台用户突破千万大关</p>
<p>• 专家解读AI如何改变传统教学模式</p>
</div>
</div>
<!-- 语义化标签使用说明 -->
<div class="semantic-explanation">
<h2>HTML语义化标签的作用层级关系</h2>
<div class="explanation-section">
<h3>1. h1标签 - 主标题</h3>
<p><strong>语义作用:</strong>表示页面或内容区块的主要标题,具有最高的语义重要性</p>
<p><strong>SEO价值</strong>搜索引擎会重点关注h1标签的内容影响页面排名</p>
<p><strong>无障碍访问:</strong>屏幕阅读器会优先读取h1内容帮助视障用户快速了解页面主题</p>
</div>
<div class="explanation-section">
<h3>2. p标签 - 段落</h3>
<p><strong>语义作用:</strong>表示一个段落,用于组织文本内容,具有明确的语义含义</p>
<p><strong>结构清晰:</strong>将内容分割成逻辑段落,提高可读性</p>
<p><strong>样式控制:</strong>便于通过CSS控制段落间距、缩进等样式</p>
</div>
<div class="explanation-section">
<h3>3. div标签 - 容器</h3>
<p><strong>语义作用:</strong>作为通用容器,用于分组和组织相关内容</p>
<p><strong>布局结构:</strong>帮助构建页面的逻辑结构和视觉布局</p>
<p><strong>样式应用:</strong>便于对整个内容区块应用统一的样式和行为</p>
</div>
<div class="hierarchy-demo">
<h3>层级关系示例</h3>
<p>在上面的新闻示例中:</p>
<p>📰 <strong>div.news-container</strong> → 整个新闻的容器</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;📝 <strong>h1</strong> → 新闻主标题(最重要)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;📦 <strong>div.news-meta</strong> → 新闻元信息区块</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;📄 <strong>p</strong> → 发布信息段落</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;📦 <strong>div.news-content</strong> → 新闻正文区块</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;📄 <strong>p</strong> → 正文段落1</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;📄 <strong>p</strong> → 正文段落2</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;📄 <strong>p</strong> → 正文段落3</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;📦 <strong>div.related-links</strong> → 相关链接区块</p>
</div>
</div>
</body>
</html>

@ -1,59 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>块级元素与行内元素学习</title>
</head>
<body>
<!-- 块级元素,特点:
<div>块级元素,特点:
<ul>
<li>独占一行</li>
<li>可以设置宽度、高度、内边距、外边距</li>
</ul>
</div>
<marquee loop="10" bgcolor="green" id="m1">
阿米诺斯
<input type="password" placeholder="请输入">
</marquee>
<h1>
这是一个h1标题
</h1>
<p>
这是一个段落
</p>
<div>
这是一个div
</div> -->
<!-- 行内元素,特点:
<div>行内元素,特点:
<ul>
<li>不独占一行</li>
<li>不能设置宽度、高度、内边距、外边距</li>
</ul>
</div>
<input type="text" placeholder="请输入">
<input type="text" placeholder="提交"> -->
<!-- 规则1块级元素中能写行内元素、块级元素几乎什么都能写-->
<div>
<span>这是一个span</span>
<input type="text" placeholder="请输入">
<div>
这是一个div
</div>
</div>
<!-- 规则2行内元素中能写行内元素,但不能写块级元素 -->
<div>
<span>这是一个span</span>
<input type="text" placeholder="请输入">
</div>
<!-- 特殊规则h1-h6不能互相嵌套 -->
<!-- 特殊规则p不能嵌套块级元素 -->
<!-- 总结: -->
<ul>
<li>块级元素:独占一行,能设置宽度、高度、内边距、外边距</li>
<li>行内元素:不独占一行,不能设置宽度、高度、内边距、外边距</li>
</ul>
</body>
</html>

@ -1,27 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML常用的文本标签学习</title>
</head>
<body>
<p>
预防电信诈骗,请安装:<em>国家反诈APP</em>
</p>
<p>
预防电信诈骗,请安装:<strong>国家反诈APP</strong>
</p>
<p>
预防电信诈骗,请安装:<span>国家反诈APP</span>
<!-- 注意span是行内元素不能设置宽度、高度、内边距、外边距 -->
<!-- span可以类比为div但是span是行内元素div是块级元素 -->
</p>
<!-- 总结: -->
<ul>
<li>em表示强调通常会显示为斜体</li>
<li>strong表示strong通常会显示为加粗</li>
<li>span表示行内元素通常用于包裹文本不能设置宽度、高度、内边距、外边距</li>
</ul>
</body>
</html>

@ -1,102 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML不常用的文本标签学习</title>
</head>
<body>
<h1>HTML不常用的文本标签学习</h1>
<!-- cite标签用于引用作品标题 -->
<h2>1. &lt;cite&gt; 标签 - 引用作品标题</h2>
<p><strong>用途:</strong>用于标记对某个作品(如书籍、文章、电影、歌曲等)的引用。</p>
<p><strong>示例:</strong></p>
<p>我最近在读<cite>《JavaScript高级程序设计》</cite>这本书。</p>
<p>电影<cite>《肖申克的救赎》</cite>是我最喜欢的电影之一。</p>
<p>这首<cite>《月亮代表我的心》</cite>是经典老歌。</p>
<!-- dfn标签用于定义术语 -->
<h2>2. &lt;dfn&gt; 标签 - 定义术语</h2>
<p><strong>用途:</strong>用于标记术语的定义实例,通常是该术语在文档中首次出现时使用。</p>
<p><strong>示例:</strong></p>
<p><dfn>HTML</dfn>HyperText Markup Language是用于创建网页的标准标记语言。</p>
<p><dfn>CSS</dfn>是层叠样式表的缩写用于描述HTML文档的样式。</p>
<p><dfn>响应式设计</dfn>是一种网页设计方法,使网页能够在不同设备上良好显示。</p>
<!-- kbd标签用于键盘输入 -->
<h2>3. &lt;kbd&gt; 标签 - 键盘输入</h2>
<p><strong>用途:</strong>用于表示用户应该从键盘输入的文本,如快捷键、命令等。</p>
<p><strong>示例:</strong></p>
<p>按下 <kbd>Ctrl</kbd> + <kbd>C</kbd> 复制选中的文本。</p>
<p>使用 <kbd>Ctrl</kbd> + <kbd>V</kbd> 粘贴内容。</p>
<p>在终端中输入 <kbd>npm install</kbd> 来安装依赖包。</p>
<p><kbd>F12</kbd> 打开浏览器开发者工具。</p>
<!-- samp标签用于程序输出示例 -->
<h2>4. &lt;samp&gt; 标签 - 程序输出示例</h2>
<p><strong>用途:</strong>用于标记计算机程序的输出示例或样本文本。</p>
<p><strong>示例:</strong></p>
<p>当你运行程序时,可能会看到以下输出:</p>
<p><samp>Hello, World!</samp></p>
<p>错误信息通常如下所示:</p>
<p><samp>Error: Cannot find module 'express'</samp></p>
<p>成功安装后会显示:</p>
<p><samp>Package installed successfully!</samp></p>
<!-- var标签用于变量 -->
<h2>5. &lt;var&gt; 标签 - 变量</h2>
<p><strong>用途:</strong>用于标记数学表达式或编程上下文中的变量。</p>
<p><strong>示例:</strong></p>
<p>在数学中,如果 <var>x</var> = 5那么 <var>y</var> = <var>x</var> + 3 = 8。</p>
<p>函数 <var>f</var>(<var>x</var>) = <var>x</var>² + 2<var>x</var> + 1</p>
<p>在编程中,变量 <var>userName</var> 存储用户的姓名。</p>
<p>循环变量 <var>i</var> 从 0 开始递增。</p>
<!-- 其他不常用文本标签 -->
<h2>6. 其他不常用文本标签</h2>
<!-- abbr标签缩写 -->
<h3>6.1 &lt;abbr&gt; 标签 - 缩写</h3>
<p><strong>用途:</strong>用于标记缩写或首字母缩略词。</p>
<p><strong>示例:</strong></p>
<p><abbr title="World Wide Web">WWW</abbr>是万维网的缩写。</p>
<p><abbr title="Application Programming Interface">API</abbr>是应用程序编程接口。</p>
<p><abbr title="Cascading Style Sheets">CSS</abbr>用于网页样式设计。</p>
<!-- time标签时间 -->
<h3>6.2 &lt;time&gt; 标签 - 时间</h3>
<p><strong>用途:</strong>用于标记时间或日期,便于搜索引擎和其他程序理解。</p>
<p><strong>示例:</strong></p>
<p>这篇文章发布于 <time datetime="2024-01-15">2024年1月15日</time></p>
<p>会议时间:<time datetime="2024-01-20T14:00">2024年1月20日下午2点</time></p>
<p>项目截止日期:<time datetime="2024-02-01">2024年2月1日</time></p>
<!-- mark标签高亮 -->
<h3>6.3 &lt;mark&gt; 标签 - 高亮标记</h3>
<p><strong>用途:</strong>用于高亮显示文本,表示相关性或重要性。</p>
<p><strong>示例:</strong></p>
<p>在搜索结果中,<mark>关键词</mark>会被高亮显示。</p>
<p>请注意:<mark>这是重要信息</mark>,需要特别关注。</p>
<p>文档中的<mark>更新内容</mark>用高亮标记。</p>
<!-- small标签小号文本 -->
<h3>6.4 &lt;small&gt; 标签 - 小号文本</h3>
<p><strong>用途:</strong>用于表示附属细则,如版权信息、法律条文等。</p>
<p><strong>示例:</strong></p>
<p>欢迎使用我们的服务!<small>使用条款和隐私政策适用。</small></p>
<p>产品价格¥299 <small>(不含税)</small></p>
<p><small>© 2024 我的网站. 保留所有权利。</small></p>
<!-- sub和sup标签下标和上标 -->
<h3>6.5 &lt;sub&gt;&lt;sup&gt; 标签 - 下标和上标</h3>
<p><strong>用途:</strong>用于表示下标和上标文本,常用于数学公式和化学方程式。</p>
<p><strong>示例:</strong></p>
<p>水的化学分子式是 H<sub>2</sub>O。</p>
<p>爱因斯坦的质能方程E = mc<sup>2</sup></p>
<p>数学表达式x<sup>2</sup> + y<sup>2</sup> = z<sup>2</sup></p>
<p>二氧化碳的分子式CO<sub>2</sub></p>
<hr>
<p><strong>总结:</strong>这些不常用的HTML文本标签虽然使用频率不高但在特定场景下能够提供更准确的语义化标记有助于提升网页的可访问性和SEO效果。</p>
</body>

@ -1,19 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML图片标签学习</title>
</head>
<body>
<!-- img标签是行内元素-->
<img width="300px" height="300px" src="微信图片_20250718204812.jpg" alt="微信图片">
<!-- 总结: -->
<ul>
<li>img标签是行内元素</li>
<li>img标签有width和height属性</li>
<li>img标签有src属性</li>
<li>img标签有alt属性</li>
</ul>
</body>
</html>

File diff suppressed because one or more lines are too long

@ -1,33 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>HTML超链接_跳转页面</h1>
<!-- 超链接的目标属性target -->
<!-- _blank在新窗口打开 -->
<!-- _self在当前窗口打开 -->
<!-- 注意如果超链接的目标属性为_self那么超链接的文本内容将被显示为超链接的目标页面的标题 -->
<a href="https://www.baidu.com" target="_blank">跳转至百度</a>
<br>
<a href="https://www.sina.com.cn" target="_self">跳转至新浪</a>
<br>
<a href="./10_HTML排版标签.html" target="_blank">跳转至排版标签页面</a>
<br>
<!-- 虽然a标签是行内元素但是a标签可以嵌套其他行内元素 除了a标签-->
<a href="./15_HTML图片标签.html" target="_blank">
<img src="./微信图片_20250718204812.jpg" alt="卡比兽" width="200px">
</a>
<!-- 总结: -->
<ul>
<li>超链接的目标属性target</li>
<li>_blank在新窗口打开</li>
<li>_self在当前窗口打开</li>
<li>注意如果超链接的目标属性为_self那么超链接的文本内容将被显示为超链接的目标页面的标题</li>
<li>虽然a标签是行内元素但是a标签可以嵌套其他行内元素 除了a标签</li>
</ul>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save