diff --git a/README.md b/README.md index 14b5a10..bf459c8 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,14 @@ tools/figures/ 独立 Python 项目,使用 drawsvg 编程制图 生产构建会生成文档路由;新增或修改文档后重新运行 build。开发模式按请求读取内容。 main 推送通过 CI 验证后自动部署;Pull Request 只验证,不部署。工作流也支持手动触发。 +## Endor 概念图 + +`content/docs/00-endor-concepts-draft.md` 解释全球入口、区域网关与 Runtime、分片、CDN、身份及跨区恢复的概念设计,页面为 `/docs/00-endor-concepts-draft`。 + +图形源码位于 `tools/figures/src/endor_figures/architecture.py`,由 `pnpm figures` 生成 `apps/docs/public/figures/endor-architecture.svg`。Python 负责可复现的节点、全连接和复制路径,React 查看器提供放大、滚动与 SVG 下载。无需外部图标、字体或绘图服务。图中的数量是示意,身份服务/CDN 接入属于建议,所有未实现的关系均以草案说明。 + +拓扑检查:`uv run --locked --project tools/figures python -m unittest discover -s tools/figures/tests -v`。容器检查流程会运行同一检查。 + ## CI/CD 与缓存 `.gitea/workflows/ci-deploy.yml` 使用已有 ces-control Runner,不修改共享 Runner 配置。 diff --git a/apps/docs/public/figures/endor-architecture.svg b/apps/docs/public/figures/endor-architecture.svg new file mode 100644 index 0000000..04ae775 --- /dev/null +++ b/apps/docs/public/figures/endor-architecture.svg @@ -0,0 +1,637 @@ + + + + +Endor 概念架构草案:全球入口、区域网关与运行时、分片和跨区恢复 + +ENDOR / SYSTEM ATLAS +一个全球入口,多个区域,一组可恢复的对象。 + +概念设计 · 草案 +01 全球接入 + + +动态 API / 对象访问 + + +静态资源 / 可缓存内容 + + +登录 / 换取凭证 + + + + + + +全球客户端 + + + + + + +endorphin API +全球流量入口 · 按健康与策略选区 + + + + + + +CDN +命中直接返回 + + + + +身份服务 +登录 / 签发凭证 +独立控制服务 · 建议 + +北美区域 +NA / 独立故障域 + +区域入口 + + + + + + + + + +区域负载均衡 +健康检查 / TLS 路由 + + + + +TRAEFIK +生产冗余 · 可选 + + + + + + + + +Traefik 1 + + + + + + + + +Traefik 2 + +HA 副本 + + + + + + + + + + + + + + + + + + + +Nexus Runtime 1 + + + + + + + + + + + + + + + +Aster VM +1 Nexus : 1 VM + + + + + + + + + + + +Nexus Runtime 2 + + + + + + + + + + + + + + + +Aster VM +1 Nexus : 1 VM + + + + + + + + + + + +Nexus Runtime 3 + + + + + + + + + + + + + + + +Aster VM +1 Nexus : 1 VM +K₂,₃ 全连接 +选择健康节点 + + + + +分片定位 / 对象读写 + + + +NA-01 / 数据分片 + +主 + 区域 HA + + + + + +PostgreSQL + + + + + + + + + + + + + + +Aerarium + + + + + + + + + + + + + + +S3 + + + + + + + + + + +Object data pool +区域内副本 · 跨故障域放置 + + + + +NA-02 / 数据分片 + +主 + 区域 HA + + + + + +PostgreSQL + + + + + + + + + + + + + + +Aerarium + + + + + + + + + + + + + + +S3 + + + + + + + + + + +Object data pool +区域内副本 · 跨故障域放置 + + +亚洲区域 +AS / 独立故障域 + +区域入口 + + + + + + + + + +区域负载均衡 +健康检查 / TLS 路由 + + + + +TRAEFIK +生产冗余 · 可选 + + + + + + + + +Traefik 1 + + + + + + + + +Traefik 2 + +HA 副本 + + + + + + + + + + + + + + + + + + + +Nexus Runtime 1 + + + + + + + + + + + + + + + +Aster VM +1 Nexus : 1 VM + + + + + + + + + + + +Nexus Runtime 2 + + + + + + + + + + + + + + + +Aster VM +1 Nexus : 1 VM + + + + + + + + + + + +Nexus Runtime 3 + + + + + + + + + + + + + + + +Aster VM +1 Nexus : 1 VM +K₂,₃ 全连接 +选择健康节点 + + + + +分片定位 / 对象读写 + + + +AS-01 / 数据分片 + +主 + 区域 HA + + + + + +PostgreSQL + + + + + + + + + + + + + + +Aerarium + + + + + + + + + + + + + + +S3 + + + + + + + + + + +Object data pool +区域内副本 · 跨故障域放置 + + + + +AS-02 / 数据分片 + +主 + 区域 HA + + + + + +PostgreSQL + + + + + + + + + + + + + + +Aerarium + + + + + + + + + + + + + + +S3 + + + + + + + + + + +Object data pool +区域内副本 · 跨故障域放置 + + + + +CDN +S3 回源 + + + + + + + +JWKS / 凭证验证 +Nexus 本地验证 +02 跨区域恢复层 +每个源分片都有一个异地目标;正常读取优先本区域,故障时恢复或转至已追平的副本。 + +亚洲分片的异地备份 · 位于北美 + + + + + + + + +AS-01 备份集 +PG + Aerarium + S3 +恢复点 / 清单校验 / 重试 + + + + + + + + +AS-02 备份集 +PG + Aerarium + S3 +恢复点 / 清单校验 / 重试 + +北美分片的异地备份 · 位于亚洲 + + + + + + + + +NA-01 备份集 +PG + Aerarium + S3 +恢复点 / 清单校验 / 重试 + + + + + + + + +NA-02 备份集 +PG + Aerarium + S3 +恢复点 / 清单校验 / 重试 + +异步复制 / 版本化备份 + + +请求与数据依赖 + +身份控制 / 公钥 + +缓存回源 + +跨区复制 / 备份 +示意数量:2 区域 × 2 网关 × 3 Runtime × 2 分片;数量不构成部署要求。 +可恢复性以已持久化且已校验的恢复点为边界;异步 ≠ 零 RPO。 + \ No newline at end of file diff --git a/apps/docs/src/components/ArchitectureFigure.tsx b/apps/docs/src/components/ArchitectureFigure.tsx new file mode 100644 index 0000000..bd563f1 --- /dev/null +++ b/apps/docs/src/components/ArchitectureFigure.tsx @@ -0,0 +1,105 @@ +import { useRef, useState } from "react"; + +const source = "/figures/endor-architecture.svg"; + +export function ArchitectureFigure({ alt }: { alt: string }) { + const dialog = useRef(null); + const trigger = useRef(null); + const pan = useRef(null); + const [fit, setFit] = useState(true); + const [zoom, setZoom] = useState(1); + function open() { + setFit(true); + setZoom(1); + dialog.current?.showModal(); + } + function changeZoom(delta: number) { + const current = fit + ? ((pan.current?.clientWidth ?? 1776) - 16) / 1760 + : zoom; + setFit(false); + setZoom( + Math.max(0.1, Math.min(2, Math.round((current + delta) * 100) / 100)), + ); + } + return ( +
+ + ENDOR / 概念架构草案 + + + + + 两区域拓扑 · 点击放大查看全连接与复制路径 + + trigger.current?.focus()} + > +
+ + Endor 概念架构 草案 + +
+ + + {fit ? "适应宽度" : `${Math.round(zoom * 100)}%`} + + + + + 下载 SVG + + +
+
+
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {alt} +
+

+ 实线:请求 / + 依赖 · 紫色:身份 · 蓝色点线:回源 · 金色:跨区备份。放大后可横向、纵向滚动,Esc + 关闭。 +

+
+
+ ); +} diff --git a/apps/docs/src/components/Shell.tsx b/apps/docs/src/components/Shell.tsx index 8570964..4c89b22 100644 --- a/apps/docs/src/components/Shell.tsx +++ b/apps/docs/src/components/Shell.tsx @@ -116,7 +116,7 @@ export function Shell({