# 架构设计
> *“代码定义了它如何工作,架构定义了它如何活着。”*
---
## 架构总览
frpc-console 是一个**轻量级生命周期管理工具**,它的架构设计围绕着三个核心目标:
1. **低资源占用** — 在边缘设备上也能运行
2. **高可靠性** — 面板可挂,业务不能停
3. **零依赖部署** — 单一二进制,开箱即用
### 整体架构图
```mermaid
graph TB
subgraph User["用户侧"]
Browser["浏览器"]
CLI["命令行"]
end
subgraph Console["frpc-console"]
WebUI["Web UI
(Vue 3 + 深色磨砂玻璃)"]
APIServer["API Server
(Gin)"]
Lifecycle["生命周期管理器"]
ConfigMgr["配置管理器
(TOML 解析/生成)"]
ProcessMgr["进程管理器
(SetSid / PID 1 接管)"]
DB["SQLite
(用户/隧道/配置)"]
Static["静态资源
(内嵌)"]
end
subgraph FRP["被管理对象"]
FRPC["frpc 进程"]
TOML["frpc.toml"]
end
Browser --> WebUI
CLI --> APIServer
WebUI --> APIServer
APIServer --> DB
APIServer --> ConfigMgr
ConfigMgr --> TOML
APIServer --> Lifecycle
Lifecycle --> ProcessMgr
ProcessMgr --> FRPC
FRPC --> TOML
Static -.-> WebUI
```
> **说明:** `Static`(前端静态资源)在编译时通过 `embed` 直接打包进二进制,运行时无需额外加载。因此图中以虚线表示其与 WebUI 的关联,且不占用独立部署单元。
---
## 部署模型
frpc-console 支持两种部署模型,架构核心逻辑完全一致,只是运行环境不同。
### 二进制部署模型
```
┌──────────────────────────────────────────┐
│ 操作系统 (Linux/Windows) │
│ │
│ ┌────────────────────────────────────┐ │
│ │ frpc-console │ │
│ │ ┌──────────────────────────────┐ │ │
│ │ │ Web UI │ API Server │ │ │
│ │ ├──────────────────────────────┤ │ │
│ │ │ 生命周期管理 / 配置管理 │ │ │
│ │ └──────────┬───────────────────┘ │ │
│ └─────────────┼──────────────────────┘ │
│ │ SetSid + 独立会话 │
│ ▼ │
│ ┌────────────────────────────────────┐ │
│ │ frpc 子进程 │ │
│ │ (被 PID 1 接管,独立生命周期) │ │
│ └────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────┐ │
│ │ 数据目录: /opt/frpc-console/data │ │
│ │ ├── frpc-console.db │ │
│ │ ├── frpc.toml │ │
│ │ ├── frpc (二进制) │ │
│ │ ├── frpc.pid │ │
│ │ └── version.ini │ │
│ └────────────────────────────────────┘ │
└──────────────────────────────────────────┘
```
**关键机制:**
- frpc-console 启动时,通过 `SetSid` 为 frpc 创建**独立会话**
- frpc 进程完全脱离父进程的生命周期控制
- 即使 console 崩溃或被 kill,frpc 会被 init(PID 1)接管,继续运行
### Docker 部署模型
```
┌──────────────────────────────────────────┐
│ Docker Host │
│ │
│ ┌────────────────────────────────────┐ │
│ │ Container: frpc-console │ │
│ │ ┌──────────────────────────────┐ │ │
│ │ │ Web UI │ API Server │ │ │
│ │ ├──────────────────────────────┤ │ │
│ │ │ 生命周期管理 / 配置管理 │ │ │
│ │ └──────────┬───────────────────┘ │ │
│ │ │ 启动 frpc │ │
│ │ ▼ │ │
│ │ ┌──────────────────────────────┐ │ │
│ │ │ frpc 子进程 (容器内) │ │ │
│ │ └──────────────────────────────┘ │ │
│ └──────────────┬─────────────────────┘ │
│ │ Volume 挂载 │
│ ▼ │
│ ┌────────────────────────────────────┐ │
│ │ 数据卷: /opt/frpc-console/data │ │
│ │ ├── frpc-console.db │ │
│ │ ├── frpc.toml │ │
│ │ ├── frpc.pid │ │
│ │ └── version.ini │ │
│ └────────────────────────────────────┘ │
│ │
│ 重启策略: --restart=always │
└──────────────────────────────────────────┘
```
**关键机制:**
- 容器配置 `--restart=always`,console 退出时 Docker 自动重启
- 数据目录通过 Volume 挂载持久化
- 容器重启后自动重新拉起 frpc
---
## 核心模块
### 1. Web UI(前端)
- **框架:** Vue 3
- **风格:** 深色磨砂玻璃视觉
- **设计原则:** 需要时清晰易用,不需要时不打扰
- **构建产物:** 静态资源通过 Go embed 内嵌于二进制
### 2. API Server
- **框架:** Gin
- **认证:** Session / JWT
- **职责:** 提供 RESTful API,处理前端请求
### 3. 生命周期管理器
负责 frpc 进程的完整生命周期:
| 操作 | 行为 |
|---|---|
| 启动 | 根据当前 frpc.toml 启动 frpc 进程 |
| 停止 | 向 frpc 发送终止信号 |
| 重启 | 停止 → 重新加载配置 → 启动 |
| 状态检查 | 读取 PID 文件,验证进程是否存在 |
| 热加载 | 修改配置后自动重启 frpc(无需手动操作) |
### 4. 配置管理器
- 解析和生成 TOML 格式的 frp 配置文件
- 支持从现有 frpc.toml 导入
- 修改配置后自动触发重启
### 5. 进程管理器
- 通过 `SetSid` 创建独立会话(Linux)
- frpc 二进制内置在部署包中,无需额外下载
- 记录 PID 到文件,用于状态检查和进程管理
- Windows 版本使用相应的进程管理 API
### 6. SQLite 数据库
- **表结构:**
- `users` — 管理员账户
- `tunnels` — 隧道配置
- `configs` — 全局配置
- **备份机制:** 部署脚本在降级前自动备份数据库文件
- **位置:** `data/frpc-console.db`
---
## 关键交互流程
### 启动流程
```mermaid
sequenceDiagram
participant User
participant Console
participant FRPC
User->>Console: 启动 frpc-console
Console->>Console: 读取 data/frpc.toml
alt 配置文件存在
Console->>FRPC: 启动 frpc (SetSid)
FRPC-->>Console: PID 写入 frpc.pid
Console-->>User: 服务就绪
else 配置文件不存在
Console-->>User: 等待 WebUI 导入配置
User->>Console: WebUI 导入 frpc.toml
Console->>FRPC: 启动 frpc
end
```
### 配置更新流程
```mermaid
sequenceDiagram
participant User
participant WebUI
participant API
participant ConfigMgr
participant FRPC
User->>WebUI: 修改隧道配置
WebUI->>API: PUT /api/tunnels/:id
API->>ConfigMgr: 更新配置
ConfigMgr->>ConfigMgr: 写入 data/frpc.toml
ConfigMgr-->>API: 配置已更新
API-->>WebUI: 200 OK
API->>FRPC: 重启 frpc (热加载)
FRPC-->>API: 启动成功
```
---
## 资源边界
### 运行时资源
| 资源 | 典型值 | 说明 |
|---|---|---|
| CPU(idle) | ~0% | 无后台轮询 |
| 内存(idle) | < 20MB | 无额外守护进程 |
| 存储(二进制) | ~15MB | 静态编译,无依赖 |
| 存储(数据) | < 1MB | SQLite + 配置文件 |
> 真实设备实测数据见 [工程设计哲学 - 稳定性与可观测性](./engineering-philosophy.md#稳定性与可观测性)
### 文件系统布局
```
/opt/frpc-console/ # 默认部署目录
├── data/ # 数据目录(持久化)
│ ├── frpc-console.db # SQLite 数据库
│ ├── frpc.toml # 当前 frpc 配置
│ ├── frpc # FRP 二进制(内置)
│ ├── frpc.pid # frpc 进程 PID
│ ├── frpc.log # frpc 日志(可选)
│ └── version.ini # 当前版本标识
├── frpc-console # 主二进制(二进制部署)
└── .old_backup_* # 旧版本备份(迁移时生成)
```
---
## 架构演进
当前架构不是一次性设计完成的,而是经历了以下阶段:
1. **最初**:一个简单的 Web UI,通过命令行调用 frpc
2. **发现问题**:SSH 断开后 frpc 也跟着退出 → 引入 SetSid
3. **发现问题**:配置文件修改需要手动重启 → 引入热加载
4. **发现问题**:ARMHF 设备跑不动 Docker → 引入二进制部署
5. **发现问题**:边缘设备内存不足 → 优化运行时内存占用
6. **发现问题**:更新时数据丢失 → 引入事务性部署脚本
7. **持续演化中**:每次真实部署都可能带来新的架构调整
---
## 相关文档
- [工程设计哲学](./engineering-philosophy.md) — 架构决策背后的设计原则
- [设计决策记录](./design-decisions.md) — 每个“为什么”的详细记录
- [边缘节点部署](./edge-node.md) — 在受限环境中的架构适配
- [更新策略](./update-strategy.md) — 版本管理和升级机制
- [部署指南](./INSTALL_DOCKER.md) — Docker 部署详细步骤
- [二进制安装指南](./INSTALL_BINARY.md) — 二进制部署详细步骤