# Nexus 技术栈完整清单

> 整理日期: 2026-05-22（v2 更新）
> 来源: 9部门审查报告 + config.py + requirements.txt + 部署配置
> 变更说明: v2 全面更新，修正 v1 中大量过时描述

---

## 一、后端技术栈

### 1.1 编程语言与运行时

| 技术 | 版本 | 用途 | 状态 |
|------|------|------|------|
| **Python** | 3.12 | 后端运行时 | ✅ |
| **uvicorn** | 0.34.0 | ASGI服务器 | ✅ 单 worker，足够 2000 台规模 |

### 1.2 Web框架

| 技术 | 版本 | 用途 | 状态 |
|------|------|------|------|
| **FastAPI** | 0.115.6 | Web框架 | ✅ |
| **pydantic** | 2.10.3 | 数据验证 | ✅ |
| **pydantic-settings** | 2.7.0 | 配置管理 (NEXUS_ 前缀) | ✅ |
| **python-multipart** | 0.0.19 | 文件上传 | ✅ |

### 1.3 数据库

| 技术 | 版本 | 用途 | 状态 |
|------|------|------|------|
| **MySQL** | 8.4 | 主数据库 (14 张表) | ✅ |
| **SQLAlchemy** | 2.0.36 (asyncio) | ORM | ✅ |
| **aiomysql** | 0.2.0 | 异步MySQL驱动 | ✅ 长期可评估 asyncmy |

### 1.4 缓存与消息

| 技术 | 版本 | 用途 | 状态 |
|------|------|------|------|
| **Redis** | 7.x | 心跳/告警/Pub/Sub | ✅ ADR-007/008/009 已落地 |
| **redis-py[hiredis]** | 5.2.1 | Redis客户端 | ✅ BlockingConnectionPool + 启动强校验 |

### 1.5 认证与安全

| 技术 | 版本 | 用途 | 状态 |
|------|------|------|------|
| **PyJWT** | 2.10.1 | JWT令牌 | ✅ **已全面使用** — 所有 API 路由 + WebSocket |
| **bcrypt** | 4.2.1 | 密码哈希 | ✅ |
| **CORS middleware** | FastAPI内置 | 跨域 | ✅ `NEXUS_CORS_ORIGINS` 可配置白名单 |

> **v1 勘误**: v1 标注"JWT中间件已写好但零路由使用"是**错误的**。JWT 已覆盖所有 API 路由 (`Depends(get_current_admin)`)。
> **v1 勘误**: v1 标注"`allow_origins=['*']`"是**过时的**。已改为 `settings.CORS_ORIGINS.split(",")` 从环境变量读取。

### 1.6 SSH与远程执行

| 技术 | 版本 | 用途 | 状态 |
|------|------|------|------|
| **asyncssh** | 2.17.0 | SSH连接池 (异步) | ✅ **已全面使用** — 连接池/WebSSH/SyncService |
| **paramiko** | ~~3.5.0~~ | ~~SSH连接 (同步)~~ | ❌ **已移除** — pool.py 已删除，requirements.txt 已移除 paramiko |

> **v1 勘误**: v1 标注"paramiko 当前在用"、"asyncssh 已安装但未使用"是**完全过时的**。asyncssh 已替代 paramiko。

### 1.7 HTTP客户端

| 技术 | 版本 | 用途 | 状态 |
|------|------|------|------|
| **httpx** | 0.28.1 | HTTP客户端 | ✅ Telegram 共享客户端 (复用) |

### 1.8 后台任务

| 技术 | 用途 | 状态 |
|------|------|------|
| **asyncio.create_task** | 4个后台协程 | ✅ |
| **asyncio.Semaphore** | 并发控制 | ✅ |

> **v1 勘误**: v1 评估了 APScheduler/jinja2/aiofiles/Rich — 全部已从 requirements.txt **移除**。

---

## 二、前端技术栈

### 2.1 当前前端（Tailwind CSS v4 + Alpine.js）— 已落地

| 技术 | 用途 | 状态 |
|------|------|------|
| **Tailwind CSS v4** | CSS框架 (CDN) | ✅ 11+ 页面 |
| **Alpine.js 3.14.8** | 前端交互 (CDN) | ✅ |
| **api.js** | JWT共享认证模块 | ✅ 自动刷新、apiFetch 封装 |
| **WebSocket** | 实时告警推送 | ✅ Dashboard |

### 2.2 已弃用

| 技术 | 状态 |
|------|------|
| **PHP AdminLTE** | ❌ 已全面弃用 (ADR-006) |
| **jQuery** | ❌ 随 AdminLTE 弃用 |
| **ACE Editor** | ❌ 未集成到新前端 |
| **Bootstrap 4** | ❌ 随 AdminLTE 弃用 |

> **v1 勘误**: v1 标注"AdminLTE 已宣布弃用但仍主力使用"是**过时的**。所有页面已迁移到 Tailwind+Alpine.js。

---

## 三、部署技术栈

| 技术 | 用途 | 状态 |
|------|------|------|
| **Supervisor** | 进程守护 (3层 Layer 1) | ✅ 模板化配置 |
| **Nginx** | 反向代理+静态文件 | ✅ 模板化配置 ({{PLACEHOLDER}}) |
| **Shell health_monitor.sh** | 3层守护 Layer 3 | ✅ 从 .env 读取配置 |

---

## 四、数据库现状（14 张表）

| 表名 | 状态 |
|------|------|
| servers (扩展) | ✅ 含 platform_id, node_id, protocols, extra_attrs, connectivity |
| platforms | ✅ 资产类型模板 |
| nodes | ✅ 树形分组 |
| admins (扩展) | ✅ 含 JWT 字段 |
| settings | ✅ |
| sync_logs | ✅ |
| push_schedules | ✅ |
| push_retry_jobs | ✅ |
| password_presets | ✅ |
| db_credentials | ✅ |
| scripts | ✅ |
| script_executions | ✅ |
| audit_logs | ✅ |
| login_attempts | ✅ |
| ssh_sessions | ✅ Web SSH 会话 |
| command_logs | ✅ SSH 命令日志 |

---

## 五、已修复的问题

| v1 优先级 | v1 问题描述 | 当前状态 |
|-----------|------------|---------|
| **P0** | Session连接泄漏 | ✅ 已修复 — DbSessionMiddleware 自动管理 |
| **P0** | SSH池语法错误(paramiko) | ✅ 已修复 — 迁移到 asyncssh，paramiko 已废弃 |
| **P0** | JWT中间件零路由使用 | ✅ 已修复 — 所有 API 路由使用 JWT |
| **P0** | 连接池超配(pool=400) | ✅ 已修复 — pool=160/overflow=120 (MySQL max_connections=400) + install.php 自动计算 |
| **P0** | CORS allow_origins=["*"] | ✅ 已修复 — NEXUS_CORS_ORIGINS 环境变量 |
| **P1** | WebSocket纯内存 | ✅ 已修复 — 两层架构 (内存+Redis Pub/Sub, ADR-010) |
| **P1** | Redis普通ConnectionPool | ✅ 已修复 — BlockingConnectionPool (ADR-008) |
| **P1** | 新旧认证并存 | ✅ 已修复 — 全面 JWT，PHP Session 已弃用 |
| **P2** | .env前缀不一致 | ✅ 已修复 — 统一 NEXUS_ 前缀 |
| **P2** | 未用依赖 | ✅ 已修复 — APScheduler/Jinja2/aiofiles/Rich/Alembic 已移除 |

---

## 六、连接池参数真相

**为什么会出现文档写 400/300 而代码是 160/120？**

这是因为有**三层配置源**，文档只记录了中间某次讨论的值，没有跟踪最终代码：

| 层级 | 来源 | pool_size | max_overflow | 说明 |
|------|------|-----------|-------------|------|
| 默认值 | `config.py` | 160 | 120 | `DB_POOL_SIZE: Optional[int] = 160`，基于 MySQL max_connections=400 |
| 运行时 | `.env` | 由 install.php 自动计算 | 由 install.php 自动计算 | `$poolSize = max(20, $maxConn * 0.4)` |
| 数据库覆盖 | MySQL settings 表 | 可覆盖 | 可覆盖 | `load_settings_from_db()` 启动时读取 |

**install.php 自动计算逻辑**（这才是标准）：

```php
$maxConn = MySQL SHOW VARIABLES LIKE 'max_connections';  // 例如 400
$poolSize = max(20, intval($maxConn * 0.4));    // 400*0.4 = 160
$maxOverflow = max(20, intval($maxConn * 0.3)); // 400*0.3 = 120
```

所以**正确的连接池参数不是固定值**，而是 install.php 根据目标 MySQL 的 `max_connections` 自动计算。

| MySQL max_connections | pool_size (40%) | max_overflow (30%) | 最大连接 |
|-----------------------|-----------------|-------------------|---------|
| 151 (默认) | 60 | 45 | 105 |
| 300 | 120 | 90 | 210 |
| 500 | 200 | 150 | 350 |
| 1000 | 400 | 300 | 700 |

**文档写 400/300 的来源**: 是 MySQL `max_connections=1000` 时的自动计算结果。这不是"标准值"，而是某个部署环境的实际值。**config.py 中的默认值 100/100** 是为了在没有 install.php 的开发环境中也能启动。

**结论**: 连接池参数应以 **install.php 自动计算逻辑**为准，config.py 默认值 100/100 只是 fallback。
