项目简介
在企业内网、校园网络或小型机房中,管理员经常需要知道服务器、网关、交换机、数据库主机等设备是否在线,延迟是否异常,故障是否已经被处理。本文实现一个"基于 Python 的网络监控工具"全栈项目:后端提供用户认证、设备管理、网络探测、指标记录和告警接口;前端提供注册登录、设备列表、仪表盘和告警处理页面。
项目不是单纯演示 Ping 命令,而是一个具备完整前后端结构、数据库持久化和鉴权保护的全栈应用,可作为运维监控平台、资产管理系统或机房巡检系统的基础版本。
技术栈
- 后端:FastAPI、SQLAlchemy、Pydantic、SQLite
- 前端:Vue 3、Vite、Fetch API、组件化单文件组件
- 认证:PBKDF2 密码哈希、Bearer Token、数据库 Token 吊销
- 数据库:SQLite,本地文件自动创建
- 部署运行:Uvicorn 提供后端服务,Vite 提供前端开发服务
系统架构
text
浏览器 / Vue 3 前端
│
│ HTTP JSON + Bearer Token
▼
FastAPI API 服务
│
├── Auth 模块:注册、登录、退出、当前用户
├── Device 模块:监控设备 CRUD
├── Probe 模块:ICMP Ping / TCP 探测
├── Metric 模块:检测结果与延迟记录
└── Alert 模块:离线告警与处理
│
▼
SQLite 数据库
前端负责展示和交互,后端负责业务规则和数据安全。除注册、登录、健康检查外,设备、指标、告警和仪表盘接口都必须携带 Token。
功能模块
- 用户模块
- 用户注册
- 用户登录
- Token 保存和退出登录
- 获取当前用户信息
- 网络设备模块
- 新增设备名称、IP/主机名、描述、检测间隔
- 查询当前用户设备
- 删除设备及其历史指标
- 网络检测模块
- 优先执行 ICMP Ping
- 失败时尝试 TCP 80 端口连通性探测
- 保存在线/离线、延迟、检测时间和消息
- 告警模块
- 设备离线自动生成 critical 告警
- 查询告警列表
- 标记告警已处理
- 仪表盘模块
- 设备总数
- 在线设备数
- 离线设备数
- 平均延迟
- 未处理告警数
数据库/数据模型设计
本项目使用 SQLite,核心表如下:
| 表名 | 说明 | 关键字段 |
|---|---|---|
| users | 用户表 | username、email、hashed_password |
| access_tokens | 登录令牌表 | token、user_id、revoked |
| devices | 监控设备表 | name、ip_address、last_status、owner_id |
| metrics | 检测指标表 | device_id、status、latency_ms、checked_at |
| alerts | 告警表 | device_id、level、message、resolved |
User 与 Device 是一对多关系;Device 与 Metric、Alert 也是一对多关系。这样每个用户只能看到自己的设备和告警,满足多用户隔离需求。
核心模型示例:
python
class Device(Base):
__tablename__ = "devices"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(80), nullable=False)
ip_address = Column(String(64), nullable=False)
description = Column(Text, default="")
check_interval = Column(Integer, default=60)
is_active = Column(Boolean, default=True)
last_status = Column(String(20), default="unknown")
last_latency_ms = Column(Float, nullable=True)
last_checked_at = Column(DateTime, nullable=True)
owner_id = Column(Integer, ForeignKey("users.id"), nullable=False)
后端接口设计
后端 API 统一以 /api 开头:
| 方法 | 地址 | 说明 | 是否需要登录 |
|---|---|---|---|
| GET | /api/health |
健康检查 | 否 |
| POST | /api/auth/register |
注册 | 否 |
| POST | /api/auth/login |
登录 | 否 |
| POST | /api/auth/logout |
退出登录 | 是 |
| GET | /api/users/me |
当前用户 | 是 |
| GET | /api/dashboard |
仪表盘统计 | 是 |
| GET | /api/devices |
设备列表 | 是 |
| POST | /api/devices |
新建设备 | 是 |
| PUT | /api/devices/{device_id} |
更新设备 | 是 |
| DELETE | /api/devices/{device_id} |
删除设备 | 是 |
| POST | /api/devices/{device_id}/check |
立即检测 | 是 |
| GET | /api/devices/{device_id}/metrics |
检测历史 | 是 |
| GET | /api/alerts |
告警列表 | 是 |
| POST | /api/alerts/{alert_id}/resolve |
处理告警 | 是 |
鉴权依赖会解析请求头:
http
Authorization: Bearer <token>
如果 Token 不存在、无效或已吊销,接口返回 401。
前端页面设计
前端采用 Vue 3 + Vite,主要页面集中在 App.vue 中,适合教学和二次拆分:
- 登录/注册区域:通过标签切换登录和注册表单
- 顶部 Banner:展示项目名称和技术栈
- 仪表盘卡片:展示设备数量、在线数、离线数、平均延迟和告警数
- 设备表单:新增监控设备
- 设备列表:显示状态、延迟、最近检测时间,并提供立即检测和删除按钮
- 告警中心:显示离线告警并支持标记处理
API 请求统一封装在 src/api.js 中,自动读取本地保存的 Token,并加到请求头中。
核心代码讲解
1. 密码哈希与登录 Token
后端没有明文保存密码,而是使用标准库 PBKDF2 生成哈希:
python
def hash_password(password: str) -> str:
salt = os.urandom(16).hex()
digest = hashlib.pbkdf2_hmac("sha256", password.encode(), salt.encode(), 120_000).hex()
return f"pbkdf2_sha256$120000${salt}${digest}"
登录成功后生成随机 Token,并写入 access_tokens 表。退出登录时将 Token 标记为 revoked=True。
2. 受保护接口
FastAPI 通过依赖注入实现认证:
python
def get_current_user(token: str = Depends(extract_token), db: Session = Depends(get_db)):
user = crud.get_user_by_token(db, token)
if not user:
raise HTTPException(status_code=401, detail="Token 无效或已过期")
return user
之后只要在接口参数中加入 current_user: models.User = Depends(get_current_user),该接口就受到鉴权保护。
3. 网络检测逻辑
检测设备时,系统先尝试 ICMP Ping。如果环境不支持 Ping 或 Ping 失败,再尝试 TCP 80 端口探测:
python
def probe_device(ip_address: str):
result = subprocess.run(["ping", "-c", "1", "-W", "2", ip_address], capture_output=True, timeout=3)
if result.returncode == 0:
return "online", latency, "ICMP Ping 成功"
ok, latency, message = _tcp_probe(ip_address)
return ("online", latency, message) if ok else ("offline", None, message)
检测完成后会更新设备最新状态,并写入 metrics 表;如果离线,则生成告警。
4. 前端鉴权请求
src/api.js 封装了统一请求方法:
javascript
async function request(path, options = {}) {
const headers = { 'Content-Type': 'application/json', ...(options.headers || {}) }
const token = getToken()
if (token) headers.Authorization = `Bearer ${token}`
const response = await fetch(`${API_BASE}${path}`, { ...options, headers })
if (!response.ok) throw new Error('请求失败')
return response.json()
}
这样所有业务接口自动携带 Token,前端页面不需要重复处理认证细节。
部署与运行步骤
项目源码位于 project/ 目录。
1. 启动后端
bash
cd backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
后端默认地址:http://127.0.0.1:8000。
2. 启动前端
bash
cd frontend
npm install
npm run dev
前端默认地址通常是:http://127.0.0.1:5173。
3. 使用流程
- 打开前端页面。
- 注册新用户并登录。
- 添加设备,例如
8.8.8.8、127.0.0.1或内网服务器 IP。 - 点击"立即检测"查看在线状态和延迟。
- 在告警中心处理离线告警。
项目总结
本文完成了一个完整的 Python 全栈网络监控工具,涵盖后端 API、数据库模型、用户认证、设备管理、网络探测、指标记录、告警处理和 Vue 3 前端页面。项目结构清晰,适合继续扩展定时巡检、邮件通知、企业微信告警、SNMP 采集、Prometheus 指标导出和 Grafana 可视化等功能。
对于想学习 Python 全栈开发、FastAPI 接口设计、Vue 3 前端交互以及运维监控系统原型设计的同学,这个项目可以作为一个完整的实战模板。