mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-01 22:46:38 +08:00
init
This commit is contained in:
+576
@@ -0,0 +1,576 @@
|
||||
# ATSFlare MVP 设计文档
|
||||
|
||||
## 1. 目标
|
||||
|
||||
先做一个能用的版本,不做平台化过度设计。第一版只解决 3 件事:
|
||||
|
||||
* 配置发布与同步
|
||||
* 节点心跳检测
|
||||
* Nginx 反向代理配置下发
|
||||
|
||||
系统定位是内部自用的控制面,不是面向外部租户的 CDN SaaS。
|
||||
|
||||
---
|
||||
|
||||
## 2. 第一版范围
|
||||
|
||||
### 要做
|
||||
|
||||
* Web 管理端维护反代规则
|
||||
* 配置发布生成版本
|
||||
* Agent 定时同步并应用配置
|
||||
* Agent 控制本机 Nginx 校验与 reload
|
||||
* 节点注册、心跳、在线状态展示
|
||||
* 展示每个节点当前生效版本和最近一次应用结果
|
||||
|
||||
### 不做
|
||||
|
||||
* 多租户
|
||||
* WAF、限流、Bot、防刷
|
||||
* 灰度发布、节点分组、分批发布
|
||||
* 对象存储、消息队列、Redis、Prometheus
|
||||
* 复杂缓存策略管理
|
||||
* 证书托管与自动签发
|
||||
* Purge、中台审计、审批流
|
||||
* mid-tier / 分层缓存
|
||||
|
||||
第一版默认所有节点消费同一份全量配置,不做差异化下发。
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术约束
|
||||
|
||||
### Server
|
||||
|
||||
控制中心直接基于现有 `atsf_server` 的 `gin-template` 工程开发:
|
||||
|
||||
* Web 框架:Gin
|
||||
* ORM:GORM
|
||||
* 前端:沿用现有 web 管理端
|
||||
* 鉴权:沿用 gin-template 登录体系
|
||||
|
||||
### 数据库
|
||||
|
||||
只使用 SQLite,不引入其他中间件:
|
||||
|
||||
* 不配置 `SQL_DSN`,直接走项目现有 SQLite 初始化逻辑
|
||||
* 不配置 `REDIS_CONN_STRING`,会退化为 cookie session
|
||||
|
||||
### Agent
|
||||
|
||||
Agent 使用 Go 单体程序:
|
||||
|
||||
* 单二进制
|
||||
* systemd 管理
|
||||
* 本地调用 `nginx`
|
||||
* 管理本机 Nginx 路由配置文件和 reload
|
||||
|
||||
### Nginx 管理边界
|
||||
|
||||
第一版只管理最核心的反代映射:
|
||||
|
||||
* 重点生成独立的 Nginx 路由配置文件,例如 `/etc/nginx/conf.d/atsflare_routes.conf`
|
||||
* `nginx.conf`、TLS 证书、缓存细节、upstream 高级配置先保持节点本地静态配置
|
||||
|
||||
也就是说,MVP 先把 Nginx 当成“可集中配置的反向代理”,不是完整网关平台。
|
||||
|
||||
---
|
||||
|
||||
## 4. 总体架构
|
||||
|
||||
```text
|
||||
┌────────────────────────────┐
|
||||
│ ATSFlare Server │
|
||||
│ gin-template + SQLite │
|
||||
│ Admin UI + Admin API │
|
||||
└──────────────┬─────────────┘
|
||||
│
|
||||
HTTP API / Config Pull
|
||||
│
|
||||
┌──────────────────┴──────────────────┐
|
||||
│ │
|
||||
┌────────▼────────┐ ┌────────▼────────┐
|
||||
│ Nginx Agent 1 │ │ Nginx Agent N │
|
||||
│ heartbeat/sync │ │ heartbeat/sync │
|
||||
│ nginx reload │ │ nginx reload │
|
||||
└────────┬────────┘ └────────┬────────┘
|
||||
│ │
|
||||
┌─────▼─────┐ ┌─────▼─────┐
|
||||
│ Nginx │ │ Nginx │
|
||||
│ reverse │ │ reverse │
|
||||
│ proxy │ │ proxy │
|
||||
└─────┬─────┘ └─────┬─────┘
|
||||
│ │
|
||||
└──────────────► Origin ◄────────────┘
|
||||
```
|
||||
|
||||
设计原则只有 3 条:
|
||||
|
||||
* Server 只保存配置和节点状态,不直接 SSH 改机器
|
||||
* Agent 是唯一的落地入口
|
||||
* 所有发布都是“新版本生效”,不是在线修改当前文件
|
||||
|
||||
---
|
||||
|
||||
## 5. 核心对象
|
||||
|
||||
第一版只保留最少的数据模型。
|
||||
|
||||
### 5.1 proxy_routes
|
||||
|
||||
反代规则表,控制 `Host -> Origin` 映射。
|
||||
|
||||
建议字段:
|
||||
|
||||
* `id`
|
||||
* `domain`
|
||||
* `origin_url`
|
||||
* `enabled`
|
||||
* `remark`
|
||||
* `created_at`
|
||||
* `updated_at`
|
||||
|
||||
约束:
|
||||
|
||||
* `domain` 唯一
|
||||
* `origin_url` 必须是合法的 `http://` 或 `https://`
|
||||
* 第一版一条域名只对应一个源站,不做源站池
|
||||
|
||||
### 5.2 config_versions
|
||||
|
||||
发布版本表,保存不可变快照。
|
||||
|
||||
建议字段:
|
||||
|
||||
* `id`
|
||||
* `version`
|
||||
* `snapshot_json`
|
||||
* `rendered_config`
|
||||
* `checksum`
|
||||
* `is_active`
|
||||
* `created_by`
|
||||
* `created_at`
|
||||
|
||||
说明:
|
||||
|
||||
* `snapshot_json` 保存发布时的完整规则快照
|
||||
* `rendered_config` 保存渲染后的 Nginx 路由配置
|
||||
* 第一版直接存 SQLite,不单独上对象存储
|
||||
|
||||
### 5.3 nodes
|
||||
|
||||
节点表,保存当前状态。
|
||||
|
||||
建议字段:
|
||||
|
||||
* `id`
|
||||
* `node_id`
|
||||
* `name`
|
||||
* `ip`
|
||||
* `agent_version`
|
||||
* `nginx_version`
|
||||
* `status`
|
||||
* `current_version`
|
||||
* `last_seen_at`
|
||||
* `last_error`
|
||||
* `created_at`
|
||||
* `updated_at`
|
||||
|
||||
### 5.4 apply_logs
|
||||
|
||||
节点应用记录。
|
||||
|
||||
建议字段:
|
||||
|
||||
* `id`
|
||||
* `node_id`
|
||||
* `version`
|
||||
* `result`
|
||||
* `message`
|
||||
* `created_at`
|
||||
|
||||
---
|
||||
|
||||
## 6. 配置发布模型
|
||||
|
||||
第一版不做增量发布,也不做 bundle 文件仓库。
|
||||
|
||||
发布逻辑:
|
||||
|
||||
1. 管理员在后台修改 `proxy_routes`
|
||||
2. 点击“发布”
|
||||
3. Server 校验规则
|
||||
4. Server 根据当前全部启用规则渲染出完整 Nginx 路由配置
|
||||
5. 生成新 `config_versions` 记录
|
||||
6. 将该版本标记为当前激活版本
|
||||
7. Agent 下一次心跳或轮询时发现新版本并拉取
|
||||
|
||||
### 版本原则
|
||||
|
||||
* 一个版本就是一份完整快照
|
||||
* 版本不可变
|
||||
* 节点只拉取当前激活版本
|
||||
* 回滚本质上是重新激活旧版本
|
||||
|
||||
### 版本号建议
|
||||
|
||||
```text
|
||||
20260309-001
|
||||
20260309-002
|
||||
```
|
||||
|
||||
### 发布校验
|
||||
|
||||
发布前至少做以下检查:
|
||||
|
||||
* `domain` 不能为空
|
||||
* `origin_url` 合法
|
||||
* 不允许重复域名
|
||||
* 至少存在 1 条启用规则
|
||||
|
||||
---
|
||||
|
||||
## 7. Nginx 配置策略
|
||||
|
||||
第一版只生成独立的 Nginx 路由配置文件,这样最简单,也最容易验证。
|
||||
|
||||
### 规则映射
|
||||
|
||||
```conf
|
||||
server {
|
||||
listen 80;
|
||||
server_name www.example.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://10.0.0.10:8080;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name api.example.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://10.0.0.20:9000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### HTTPS 处理
|
||||
|
||||
第一版不在控制中心管理证书。
|
||||
|
||||
约定如下:
|
||||
|
||||
* Nginx 的监听端口、证书、TLS 相关配置由节点本地预先准备
|
||||
* 控制中心只负责反代映射
|
||||
* 如果节点已经具备 HTTPS 接入能力,后续可以扩展生成 HTTPS `server` 块
|
||||
|
||||
### 缓存处理
|
||||
|
||||
第一版不开放缓存策略配置:
|
||||
|
||||
* 是否开启缓存由节点静态配置决定
|
||||
* 控制中心不管理 TTL、Header 改写、缓存规则
|
||||
|
||||
---
|
||||
|
||||
## 8. Server 模块设计
|
||||
|
||||
控制中心仍然是单体应用,不拆服务。
|
||||
|
||||
### 8.1 管理端模块
|
||||
|
||||
* 登录鉴权
|
||||
* 反代规则 CRUD
|
||||
* 发布版本管理
|
||||
* 节点状态页面
|
||||
* 应用日志查看
|
||||
|
||||
### 8.2 Agent API 模块
|
||||
|
||||
* 节点注册
|
||||
* 心跳上报
|
||||
* 获取当前激活版本
|
||||
* 下载指定版本配置
|
||||
* 上报应用结果
|
||||
|
||||
### 8.3 渲染模块
|
||||
|
||||
职责很简单:
|
||||
|
||||
* 从 `proxy_routes` 读取全部启用规则
|
||||
* 按固定模板拼出 Nginx 路由配置
|
||||
* 计算 checksum
|
||||
* 写入 `config_versions`
|
||||
|
||||
这层不要引入复杂 DSL,第一版直接围绕 `domain -> origin_url` 即可。
|
||||
|
||||
---
|
||||
|
||||
## 9. Agent 模块设计
|
||||
|
||||
Agent 做成一个 Go 单体进程即可。
|
||||
|
||||
### 9.1 本地职责
|
||||
|
||||
* 读取本地配置
|
||||
* 定时心跳
|
||||
* 拉取新版本
|
||||
* 覆盖 Nginx 路由配置文件
|
||||
* 执行 `nginx -t` 和 `nginx -s reload`
|
||||
* 上报应用结果
|
||||
* 保存本地最近成功版本
|
||||
|
||||
### 9.2 建议的本地文件
|
||||
|
||||
* `/etc/atsf-agent/config.yaml`
|
||||
* `/var/lib/atsf-agent/state.json`
|
||||
* `/etc/nginx/conf.d/atsflare_routes.conf`
|
||||
* `/etc/nginx/conf.d/atsflare_routes.conf.bak`
|
||||
|
||||
### 9.3 最小工作流
|
||||
|
||||
```text
|
||||
1. Agent 启动
|
||||
2. 读取或生成 node_id
|
||||
3. 上报 heartbeat
|
||||
4. 获取当前激活版本元数据
|
||||
5. 若版本变更,则下载 rendered_config
|
||||
6. 备份旧路由配置文件
|
||||
7. 写入新路由配置文件
|
||||
8. 调用 `nginx -t`
|
||||
9. 校验通过后执行 `nginx -s reload`
|
||||
10. 记录结果并上报
|
||||
11. 进入下一轮
|
||||
```
|
||||
|
||||
### 9.4 失败处理
|
||||
|
||||
第一版只做最基本的容错:
|
||||
|
||||
* 拉取失败:继续使用本地旧配置
|
||||
* 配置校验或 reload 失败:恢复备份文件并再次校验后 reload
|
||||
* Server 不可用:不影响 Nginx 继续转发
|
||||
|
||||
---
|
||||
|
||||
## 10. 心跳与在线状态
|
||||
|
||||
心跳不单独搞复杂监控系统,直接走业务表。
|
||||
|
||||
### 心跳内容
|
||||
|
||||
Agent 每次上报:
|
||||
|
||||
* `node_id`
|
||||
* `name`
|
||||
* `ip`
|
||||
* `agent_version`
|
||||
* `nginx_version`
|
||||
* `current_version`
|
||||
* `last_apply_result`
|
||||
* `timestamp`
|
||||
|
||||
### 状态判定
|
||||
|
||||
建议规则:
|
||||
|
||||
* 15 秒一次心跳
|
||||
* 超过 45 秒未上报记为 `offline`
|
||||
* 最近一次应用失败但仍有心跳,记为 `warning`
|
||||
* 正常心跳且版本一致,记为 `online`
|
||||
|
||||
---
|
||||
|
||||
## 11. API 设计
|
||||
|
||||
### 11.1 管理端 API
|
||||
|
||||
* `GET /api/routes`
|
||||
* `POST /api/routes`
|
||||
* `PUT /api/routes/:id`
|
||||
* `DELETE /api/routes/:id`
|
||||
* `GET /api/versions`
|
||||
* `POST /api/versions/publish`
|
||||
* `POST /api/versions/:id/activate`
|
||||
* `GET /api/nodes`
|
||||
* `GET /api/apply-logs`
|
||||
|
||||
### 11.2 Agent API
|
||||
|
||||
* `POST /api/agent/register`
|
||||
* `POST /api/agent/heartbeat`
|
||||
* `GET /api/agent/version/active`
|
||||
* `GET /api/agent/versions/:version`
|
||||
* `POST /api/agent/apply-result`
|
||||
|
||||
### 11.3 鉴权方案
|
||||
|
||||
管理端:
|
||||
|
||||
* 直接沿用 gin-template 的登录态
|
||||
|
||||
Agent:
|
||||
|
||||
* 第一版使用预共享 Token
|
||||
* 例如请求头 `X-Agent-Token`
|
||||
* 后续再升级 mTLS
|
||||
|
||||
---
|
||||
|
||||
## 12. 页面设计
|
||||
|
||||
第一版只保留最少页面。
|
||||
|
||||
### 12.1 登录页
|
||||
|
||||
沿用 gin-template 现有登录。
|
||||
|
||||
### 12.2 反代规则页
|
||||
|
||||
展示和编辑:
|
||||
|
||||
* 域名
|
||||
* 源站地址
|
||||
* 是否启用
|
||||
* 备注
|
||||
|
||||
### 12.3 发布版本页
|
||||
|
||||
展示:
|
||||
|
||||
* 版本号
|
||||
* 发布时间
|
||||
* 发布人
|
||||
* 是否当前激活
|
||||
|
||||
动作:
|
||||
|
||||
* 立即发布
|
||||
* 激活旧版本
|
||||
|
||||
### 12.4 节点页
|
||||
|
||||
展示:
|
||||
|
||||
* 节点名
|
||||
* IP
|
||||
* 在线状态
|
||||
* 当前版本
|
||||
* 最后心跳时间
|
||||
* 最近错误
|
||||
|
||||
### 12.5 应用记录页
|
||||
|
||||
展示:
|
||||
|
||||
* 节点
|
||||
* 版本
|
||||
* 成功/失败
|
||||
* 错误信息
|
||||
* 时间
|
||||
|
||||
---
|
||||
|
||||
## 13. 代码组织建议
|
||||
|
||||
### Server
|
||||
|
||||
建议直接在现有 `atsf_server` 下新增以下内容:
|
||||
|
||||
```text
|
||||
atsf_server/
|
||||
controller/
|
||||
route.go
|
||||
version.go
|
||||
node.go
|
||||
agent.go
|
||||
model/
|
||||
proxy_route.go
|
||||
config_version.go
|
||||
node.go
|
||||
apply_log.go
|
||||
router/
|
||||
api-router.go
|
||||
service/
|
||||
publisher.go
|
||||
renderer.go
|
||||
```
|
||||
|
||||
### Agent
|
||||
|
||||
建议新建独立目录:
|
||||
|
||||
```text
|
||||
atsf_agent/
|
||||
cmd/agent/main.go
|
||||
internal/config/config.go
|
||||
internal/heartbeat/heartbeat.go
|
||||
internal/sync/sync.go
|
||||
internal/nginx/nginx.go
|
||||
internal/state/state.go
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 14. 开发顺序
|
||||
|
||||
按下面的顺序最稳。
|
||||
|
||||
### 第一阶段
|
||||
|
||||
先把 Server 跑通:
|
||||
|
||||
* 建表
|
||||
* 反代规则 CRUD
|
||||
* 发布版本表
|
||||
* 版本渲染逻辑
|
||||
|
||||
### 第二阶段
|
||||
|
||||
做 Agent 最小闭环:
|
||||
|
||||
* 注册
|
||||
* 心跳
|
||||
* 拉取激活版本
|
||||
* 写入 Nginx 路由配置
|
||||
* `nginx -t && nginx -s reload`
|
||||
* 应用结果上报
|
||||
|
||||
### 第三阶段
|
||||
|
||||
补管理端页面:
|
||||
|
||||
* 规则页
|
||||
* 版本页
|
||||
* 节点页
|
||||
* 应用日志页
|
||||
|
||||
---
|
||||
|
||||
## 15. 关键取舍
|
||||
|
||||
第一版故意做这些取舍:
|
||||
|
||||
* 不抽象 zone、origin pool、policy 这些平台概念
|
||||
* 不做复杂发布编排,所有节点统一拉当前版本
|
||||
* 不管理 Nginx 全部配置,只先管独立生成的路由配置文件
|
||||
* 不引入 Redis、MQ、对象存储,先把单机 SQLite 跑起来
|
||||
* 不为了“以后可能会用到”提前把系统拆复杂
|
||||
|
||||
只要这版能稳定完成下面这条链路,就算成功:
|
||||
|
||||
```text
|
||||
后台改规则 -> 点击发布 -> Agent 拉到新版本 -> Nginx reload -> 节点状态可见
|
||||
```
|
||||
|
||||
这就是当前阶段最需要的 MVP。
|
||||
@@ -0,0 +1,375 @@
|
||||
# ATSFlare 开发规范
|
||||
|
||||
## 1. 适用范围
|
||||
|
||||
本规范适用于 ATSFlare 当前 MVP 阶段。
|
||||
|
||||
项目当前只做以下能力:
|
||||
|
||||
* 配置发布与同步
|
||||
* 节点心跳检测
|
||||
* Nginx 反向代理配置下发
|
||||
|
||||
当前明确不做:
|
||||
|
||||
* 多租户
|
||||
* WAF、限流、Bot、防刷
|
||||
* 灰度发布、分组发布、百分比发布
|
||||
* Redis、MQ、对象存储、Prometheus
|
||||
* 复杂缓存策略、证书托管、Purge、审批流
|
||||
* mid-tier、分层缓存、复杂策略编排
|
||||
|
||||
超出以上范围的需求,必须先更新设计文档,再开始编码。
|
||||
|
||||
## 2. 技术基线
|
||||
|
||||
### 2.1 Server
|
||||
|
||||
控制中心基于现有 `atsf_server` 开发:
|
||||
|
||||
* Web 框架:Gin
|
||||
* ORM:GORM
|
||||
* 数据库:SQLite
|
||||
* 前端:现有 `atsf_server/web`
|
||||
* 登录体系:沿用 gin-template 现有能力
|
||||
|
||||
约束:
|
||||
|
||||
* 默认不配置 `SQL_DSN`
|
||||
* 默认不配置 `REDIS_CONN_STRING`
|
||||
* 不为了 MVP 引入新的基础设施依赖
|
||||
|
||||
### 2.2 Agent
|
||||
|
||||
Agent 放在 `atsf_agent`,使用 Go 单体程序开发。
|
||||
|
||||
约束:
|
||||
|
||||
* 单二进制
|
||||
* systemd 运行
|
||||
* 本地调用 `nginx`
|
||||
* 负责本机 Nginx 路由配置写入、校验、reload、状态上报
|
||||
|
||||
### 2.3 Nginx 配置边界
|
||||
|
||||
第一版控制面只管理独立生成的 Nginx 路由配置文件,例如 `/etc/nginx/conf.d/atsflare_routes.conf`。
|
||||
|
||||
以下内容先不纳入控制面:
|
||||
|
||||
* `nginx.conf`
|
||||
* TLS 证书
|
||||
* 缓存策略
|
||||
* upstream 高级配置
|
||||
|
||||
这些内容先保持节点本地静态配置。
|
||||
|
||||
## 3. 仓库职责划分
|
||||
|
||||
### 3.1 `atsf_server`
|
||||
|
||||
负责:
|
||||
|
||||
* 管理端 UI
|
||||
* 管理端 API
|
||||
* Agent API
|
||||
* 数据存储
|
||||
* 配置渲染
|
||||
* 版本发布
|
||||
* 节点状态展示
|
||||
|
||||
### 3.2 `atsf_agent`
|
||||
|
||||
负责:
|
||||
|
||||
* 节点注册
|
||||
* 心跳上报
|
||||
* 拉取激活版本
|
||||
* 写入本地 Nginx 路由配置
|
||||
* 调用 `nginx -t` 和 `nginx -s reload`
|
||||
* 失败回滚
|
||||
* 上报应用结果
|
||||
|
||||
### 3.3 `docs`
|
||||
|
||||
负责:
|
||||
|
||||
* 设计边界
|
||||
* 开发规范
|
||||
* 开发计划
|
||||
* 部署与联调说明
|
||||
|
||||
## 4. 开发原则
|
||||
|
||||
所有实现都必须遵守以下原则:
|
||||
|
||||
* 先完成闭环,再做抽象。
|
||||
* 不为了“以后可能会支持”提前引入复杂模型。
|
||||
* Server 只管状态和配置,不直接 SSH 改节点。
|
||||
* Agent 是唯一落地入口。
|
||||
* 所有发布都是“新版本激活”,不是在线覆盖编辑。
|
||||
* 所有节点默认拉同一份全量配置,不做差异化编排。
|
||||
* 能用 SQLite 解决的问题,不引入额外中间件。
|
||||
* 新功能优先复用现有 gin-template 结构,不平行造第二套框架。
|
||||
|
||||
## 5. 数据模型规范
|
||||
|
||||
第一版只允许引入以下核心实体:
|
||||
|
||||
* `proxy_routes`
|
||||
* `config_versions`
|
||||
* `nodes`
|
||||
* `apply_logs`
|
||||
|
||||
约束:
|
||||
|
||||
* 不新增 `zone`、`origin_pool`、`policy`、`deployment` 这类平台化对象
|
||||
* `proxy_routes` 一条域名只对应一个 `origin_url`
|
||||
* `config_versions` 必须保存完整快照和渲染后的 Nginx 路由配置
|
||||
* 激活版本全局只能有一个
|
||||
* 回滚通过“激活旧版本”实现,不直接修改历史记录
|
||||
|
||||
如需新增表,必须先证明它服务于 MVP 主链路。
|
||||
|
||||
## 6. Server 开发规范
|
||||
|
||||
### 6.1 分层约束
|
||||
|
||||
Server 代码按以下职责拆分:
|
||||
|
||||
* `controller/`: 参数解析、调用 service、返回 JSON
|
||||
* `service/`: 业务逻辑、校验、渲染、版本切换
|
||||
* `model/`: 数据表结构、查询和持久化
|
||||
* `router/`: 路由注册
|
||||
* `middleware/`: 认证、鉴权、限流等横切逻辑
|
||||
* `common/`: 通用工具和配置
|
||||
|
||||
禁止行为:
|
||||
|
||||
* controller 直接拼接复杂业务逻辑
|
||||
* controller 直接操作多个 model 形成事务链
|
||||
* middleware 承担业务逻辑
|
||||
* 为简单需求引入新的平台层抽象
|
||||
|
||||
### 6.2 API 约定
|
||||
|
||||
管理端和 Agent API 统一使用 JSON。
|
||||
|
||||
响应结构沿用现有模板风格:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
* 成功或失败都返回清晰 `message`
|
||||
* 列表接口返回稳定字段,不临时拼装结构
|
||||
* 新接口命名优先使用复数资源风格
|
||||
* Agent API 固定放在 `/api/agent/*`
|
||||
|
||||
### 6.3 鉴权规范
|
||||
|
||||
管理端:
|
||||
|
||||
* 继续复用 gin-template 的登录、角色和 session 体系
|
||||
|
||||
Agent:
|
||||
|
||||
* 第一版使用预共享 Token
|
||||
* 请求头统一使用 `X-Agent-Token`
|
||||
* Agent 与管理端认证逻辑必须分开
|
||||
|
||||
注意:
|
||||
|
||||
* 不要让 Agent 接口走用户登录态
|
||||
* 不要把 Nginx 命令暴露成远程管理接口
|
||||
|
||||
### 6.4 数据库规范
|
||||
|
||||
SQLite 是唯一默认数据库。
|
||||
|
||||
要求:
|
||||
|
||||
* 新增模型后必须在 `model.InitDB()` 中加入 `AutoMigrate`
|
||||
* 不写 MySQL/PostgreSQL 特有 SQL
|
||||
* 不依赖外部迁移工具作为 MVP 前提
|
||||
* 时间字段统一使用 GORM 常规时间类型
|
||||
|
||||
### 6.5 发布与渲染规范
|
||||
|
||||
发布逻辑必须满足:
|
||||
|
||||
* 发布时读取全部启用的 `proxy_routes`
|
||||
* 生成完整的 Nginx 路由配置
|
||||
* 计算 checksum
|
||||
* 保存快照到 `config_versions`
|
||||
* 通过切换 `is_active` 激活版本
|
||||
|
||||
版本号格式固定为:
|
||||
|
||||
```text
|
||||
YYYYMMDD-NNN
|
||||
```
|
||||
|
||||
例如:
|
||||
|
||||
```text
|
||||
20260309-001
|
||||
```
|
||||
|
||||
## 7. Agent 开发规范
|
||||
|
||||
### 7.1 模块边界
|
||||
|
||||
建议目录如下:
|
||||
|
||||
```text
|
||||
atsf_agent/
|
||||
cmd/agent/
|
||||
internal/config/
|
||||
internal/heartbeat/
|
||||
internal/sync/
|
||||
internal/nginx/
|
||||
internal/state/
|
||||
internal/httpclient/
|
||||
```
|
||||
|
||||
职责要求:
|
||||
|
||||
* `config`: 本地配置读取
|
||||
* `heartbeat`: 心跳请求和状态组装
|
||||
* `sync`: 检查版本、下载配置、触发应用
|
||||
* `nginx`: 封装 Nginx 校验、reload 和文件写入
|
||||
* `state`: 本地成功版本和运行状态缓存
|
||||
* `httpclient`: Server API 调用
|
||||
|
||||
### 7.2 行为规范
|
||||
|
||||
Agent 必须满足以下行为:
|
||||
|
||||
* 启动后生成或读取本地 `node_id`
|
||||
* 周期性心跳
|
||||
* 周期性检查激活版本
|
||||
* 发现新版本后先备份旧文件
|
||||
* 写入新路由配置文件
|
||||
* 先执行 `nginx -t`
|
||||
* 校验通过后执行 `nginx -s reload`
|
||||
* 失败时回滚备份并再次校验和 reload
|
||||
* 上报最终应用结果
|
||||
|
||||
### 7.3 容错规范
|
||||
|
||||
第一版最少保证:
|
||||
|
||||
* Server 不可用时,Nginx 继续使用旧配置
|
||||
* 下载失败时,不修改本地配置
|
||||
* 配置校验或 reload 失败时,自动尝试回滚
|
||||
* 本地状态文件损坏时,允许重新初始化,但不能删除正在生效的 Nginx 配置
|
||||
|
||||
### 7.4 外部命令规范
|
||||
|
||||
Agent 调用 Nginx 命令时必须:
|
||||
|
||||
* 明确记录执行命令和返回错误
|
||||
* 设置合理超时
|
||||
* 不依赖交互式输入
|
||||
* 不通过 shell 拼接不可信参数
|
||||
|
||||
## 8. 前端开发规范
|
||||
|
||||
MVP 前端只做最小管理界面,不重做整套后台。
|
||||
|
||||
要求:
|
||||
|
||||
* 继续使用现有 React 结构和 `semantic-ui-react`
|
||||
* 页面只增加 MVP 必需页面
|
||||
* 不额外引入新的大型前端框架
|
||||
* API 请求统一放在 `web/src/helpers/api.js` 或同类 helper 中
|
||||
* 页面状态优先保持简单,不提前引入复杂全局状态管理
|
||||
|
||||
第一版只需要以下页面:
|
||||
|
||||
* 反代规则页
|
||||
* 发布版本页
|
||||
* 节点状态页
|
||||
* 应用记录页
|
||||
|
||||
## 9. 代码风格规范
|
||||
|
||||
### 9.1 Go
|
||||
|
||||
* 保持 package 名称简短且小写
|
||||
* 错误必须显式处理,不允许静默吞错
|
||||
* 函数尽量只做一件事
|
||||
* 输入校验放在 controller 或 service 边界
|
||||
* 业务枚举值使用明确常量,不使用魔法字符串散落代码
|
||||
* 仅在复杂逻辑前添加简短注释,不写废话注释
|
||||
|
||||
### 9.2 命名
|
||||
|
||||
* 表名和模型名使用业务语义,不沿用模板示例语义
|
||||
* 统一使用 `route`, `version`, `node`, `apply log` 这些术语
|
||||
* 不混用 `client`、`edge`、`agent` 指代同一模块,统一叫 `agent`
|
||||
|
||||
### 9.3 日志
|
||||
|
||||
要求记录这些关键事件:
|
||||
|
||||
* 发布成功/失败
|
||||
* Agent 注册
|
||||
* 心跳异常
|
||||
* 配置下载失败
|
||||
* Nginx 校验或 reload 成功/失败
|
||||
* 回滚触发
|
||||
|
||||
日志内容要可定位问题,但不要打印敏感 Token。
|
||||
|
||||
## 10. 测试与验收规范
|
||||
|
||||
### 10.1 最低测试要求
|
||||
|
||||
Server 至少覆盖:
|
||||
|
||||
* `origin_url` 校验
|
||||
* `domain` 重复校验
|
||||
* Nginx 路由配置渲染结果
|
||||
* 激活版本切换逻辑
|
||||
* 节点在线状态判定逻辑
|
||||
|
||||
Agent 至少覆盖:
|
||||
|
||||
* 版本比较逻辑
|
||||
* 配置文件备份和回滚逻辑
|
||||
* `nginx -t` 或 `nginx -s reload` 失败分支
|
||||
* 本地状态文件读写
|
||||
|
||||
### 10.2 联调验收标准
|
||||
|
||||
MVP 完成至少要通过以下手工验证:
|
||||
|
||||
1. 管理端新增反代规则并成功发布版本
|
||||
2. Agent 能检测到新版本并拉取
|
||||
3. Agent 成功写入 Nginx 路由配置文件
|
||||
4. Agent 成功执行 `nginx -t` 和 `nginx -s reload`
|
||||
5. 节点页能看到当前版本和最后心跳
|
||||
6. 当 reload 失败时,Agent 能回滚到旧配置并上报失败
|
||||
|
||||
## 11. 文档维护规范
|
||||
|
||||
出现以下情况时必须同步更新文档:
|
||||
|
||||
* MVP 范围变化
|
||||
* API 发生破坏性变更
|
||||
* 数据模型新增或删除
|
||||
* Agent 本地文件路径变更
|
||||
* 部署方式变化
|
||||
|
||||
优先更新:
|
||||
|
||||
* `docs/design.md`
|
||||
* `docs/development-guidelines.md`
|
||||
* `docs/development-plan.md`
|
||||
@@ -0,0 +1,179 @@
|
||||
# ATSFlare 开发计划
|
||||
|
||||
## 1. 目标
|
||||
|
||||
当前开发目标是完成 ATSFlare 的 MVP 闭环:
|
||||
|
||||
```text
|
||||
后台改规则 -> 点击发布 -> Agent 拉到新版本 -> 写入 Nginx 路由配置 -> nginx 校验并 reload -> 节点状态可见
|
||||
```
|
||||
|
||||
在这个闭环完成之前,不新增高级功能。
|
||||
|
||||
## 2. 里程碑
|
||||
|
||||
### Phase 1: Server 数据层与发布闭环
|
||||
|
||||
目标:
|
||||
|
||||
* 完成 `proxy_routes`
|
||||
* 完成 `config_versions`
|
||||
* 能从规则生成 Nginx 路由配置
|
||||
* 能激活一个全局版本
|
||||
|
||||
交付:
|
||||
|
||||
* 新模型
|
||||
* AutoMigrate
|
||||
* 路由 CRUD API
|
||||
* 发布 API
|
||||
* 激活版本 API
|
||||
* 渲染 service
|
||||
|
||||
完成标准:
|
||||
|
||||
* 后台能维护规则
|
||||
* 可以生成并查看版本记录
|
||||
|
||||
### Phase 2: Agent API 与节点状态
|
||||
|
||||
目标:
|
||||
|
||||
* 建立节点注册、心跳、版本查询、应用结果上报链路
|
||||
|
||||
交付:
|
||||
|
||||
* `nodes`
|
||||
* `apply_logs`
|
||||
* Agent Token 鉴权
|
||||
* 节点在线状态计算
|
||||
* 节点与应用日志查询接口
|
||||
|
||||
完成标准:
|
||||
|
||||
* Server 能记录节点和最近状态
|
||||
|
||||
### Phase 3: Agent 本体
|
||||
|
||||
目标:
|
||||
|
||||
* 实现最小可运行 Agent
|
||||
|
||||
交付:
|
||||
|
||||
* 本地配置文件读取
|
||||
* `node_id` 持久化
|
||||
* 心跳循环
|
||||
* 版本检查
|
||||
* 下载配置
|
||||
* 写入 Nginx 路由配置
|
||||
* 配置校验、reload 与失败回滚
|
||||
* 应用结果上报
|
||||
|
||||
完成标准:
|
||||
|
||||
* 单节点可跑通“发布到 Nginx 生效”的闭环
|
||||
|
||||
### Phase 4: 管理端页面
|
||||
|
||||
目标:
|
||||
|
||||
* 提供 MVP 所需最小可视化界面
|
||||
|
||||
交付:
|
||||
|
||||
* 反代规则页
|
||||
* 版本页
|
||||
* 节点页
|
||||
* 应用记录页
|
||||
|
||||
完成标准:
|
||||
|
||||
* 不依赖直接查库即可完成日常操作和排障
|
||||
|
||||
### Phase 5: 联调与收尾
|
||||
|
||||
目标:
|
||||
|
||||
* 完成本地或测试环境联调
|
||||
* 补齐运行说明
|
||||
|
||||
交付:
|
||||
|
||||
* 手工部署说明
|
||||
* Agent 配置示例
|
||||
* 最小联调脚本或命令说明
|
||||
* 问题清单与后续迭代列表
|
||||
|
||||
完成标准:
|
||||
|
||||
* 新环境能按文档手工部署并跑通最小闭环
|
||||
|
||||
## 3. 当前建议执行顺序
|
||||
|
||||
建议严格按以下顺序开发:
|
||||
|
||||
1. Server 模型和 `AutoMigrate`
|
||||
2. 路由 CRUD 与发布逻辑
|
||||
3. Agent API 与节点状态表
|
||||
4. Agent 同步、落盘、reload、回滚
|
||||
5. 管理端页面
|
||||
6. 联调和部署文档
|
||||
|
||||
不要先做以下内容:
|
||||
|
||||
* 权限扩展
|
||||
* 缓存策略平台化
|
||||
* 证书平台化
|
||||
* 多节点分批发布
|
||||
* 高级监控接入
|
||||
|
||||
## 4. 每阶段的验收检查
|
||||
|
||||
### Phase 1 检查项
|
||||
|
||||
* 可以创建、编辑、删除反代规则
|
||||
* 可以基于当前规则生成版本
|
||||
* 可以查看哪个版本处于激活状态
|
||||
* 激活旧版本时不会修改历史快照
|
||||
|
||||
### Phase 2 检查项
|
||||
|
||||
* Agent 可以通过 Token 访问 Agent API
|
||||
* 节点可以注册并重复心跳
|
||||
* 节点超过超时时间会显示为离线
|
||||
* 可以查询节点最近一次应用状态
|
||||
|
||||
### Phase 3 检查项
|
||||
|
||||
* Agent 检测到新版本后会下载配置
|
||||
* 写入前会备份旧路由配置文件
|
||||
* `nginx -t` 或 reload 失败后会回滚
|
||||
* 回滚结果会回传给 Server
|
||||
|
||||
### Phase 4 检查项
|
||||
|
||||
* 页面可直接完成规则维护和发布
|
||||
* 页面可查看节点在线状态
|
||||
* 页面可查看应用失败原因
|
||||
|
||||
### Phase 5 检查项
|
||||
|
||||
* 按文档可完成一次从零部署
|
||||
* 至少完成一次真实联调记录
|
||||
* 已记录当前遗留问题和下一阶段候选项
|
||||
|
||||
## 5. 变更控制
|
||||
|
||||
开发中如果出现以下情况,需要先调整计划再继续编码:
|
||||
|
||||
* MVP 目标发生变化
|
||||
* 需要引入新的中间件
|
||||
* 需要新增核心数据模型
|
||||
* 需要把控制面扩展到独立生成的 Nginx 路由配置文件之外
|
||||
|
||||
计划更新时,应同步修改:
|
||||
|
||||
* `docs/design.md`
|
||||
* `docs/development-guidelines.md`
|
||||
* `docs/development-plan.md`
|
||||
Reference in New Issue
Block a user