LLAR后端设计
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 5
- Forks
- 4
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 22
Description
背景
由于LLAR设计出发点就是为了满足庞大产物构建需求,而GitHub Action无法提供如此庞大的算力资源,因此我们必须设计一套LLAR 后端。
设计目标
- 满足庞大产物构建,存储需求
- 保证集群可靠性,高并发
构建架构图
graph LR
A[用户] <--> 0
0 --> H
0 --> C
C[构建请求] --> |发布|D
H[获取/修改/删除预构建信息] --> 3.1
3.1 -.-> |返回预构建信息|0
A -.-> |下载预构建|F
subgraph 0[中间层]
B[LLAR 用户 API]
end
subgraph 1[数据应用层]
subgraph D[消息处理模块]
D.1[(消息队列)]
end
L[计算集群调度模块]
J[(镜像仓库)]
subgraph 1.1[K8S控制平面]
subgraph E[构建集群]
E1[构建节点1]
E2[构建节点2]
E3[构建节点...]
end
end
E1 --> |拉取|J
E2 --> |拉取|J
E3 --> |拉取|J
I[KubeSphere] <--> 1.1
L --> |调用K8S API|1.1
D --> |触发|L
end
E1 --> |订阅|D
E2 --> |订阅|D
E3 --> |订阅|D
E1 --> |获得配方|K
E2 --> |获得配方|K
E3 --> |获得配方|K
subgraph 2[数据管理层]
subgraph 3[数据管理中间层]
3.1[LLAR 数据管理 内网 API]
end
K[(中心化配方仓库)]
F[(云存储)]
subgraph G[MongoDB 主从复制集群]
G1[数据库节点1]
G2[数据库节点2]
G3[数据库节点...]
end
F <--> |数据保持|G
end
E --> |上传产物|3.1
3.1 -.-> |返回产物URL|E
E -.-> |产物URL|3.1
3.1 --> |构建任务信息|G
相关架构分层:
中间层:负责提供对用户接口,集成相关功能
数据应用层:负责处理构建请求,由多台机器组成构建集群
数据管理中间层:负责为数据管理层对内提供统一的接口
数据管理层:负责管理构建信息,和存放对应的构建产物,一般是对象存储(七牛云KODO)
实现细节
构建集群
管理
使用KubeSphere作为可视化面板,连接K8S控制平面,作为集群管理工具
任务调度
调度目标为:尽量塞满集群内每一台机器的CPU核心
调度单位:单台集群成员
设计
一般来说,一个任务需要开一台容器,以保证其构建安全性
构建集群容器成员应使用消息队列的 Pub-Sub 进行任务监听拉取,这样好处有:
- 拉取任务的服务器一定“空闲”,这个空闲状态可以后期由各种算法决定,单台构建服务器只需要关心自身负载状态,无需关心系统整体
- 任务完成后再发送ACK确认消费,避免任务未构建完成意外退出
构建依赖问题
一般来说,构建集群需要频繁调用依赖,而且还会产生一些顺序问题。
例如并发构建的时候,cjson 依赖 zlib,同时构建cjson和zlib。为了避免这类问题,我们一般不允许维护者提交这类请求,然而这种要求并非强制性的。
为了确保系统鲁棒性,这类构建请求被错误提交的时候应该有一定处理逻辑。
回到刚才例子,我们如何处理上述依赖并发冲突构建问题:
如果zlib构建任务先被开始执行:
- 检查是否已经存在构建任务,没有则往数据库插入构建任务信息
- 执行完成,更新数据库
如果cjson开始执行:
- 配方脚本会自动先编译zlib,检查数据库是否存在,没有就插入,有就直接使用存储中的预构建产物
- 再执行cjson构建
配方设计
由于服务端逻辑会和用户端不一样,一般来说,不能采用用户端那套逻辑。
但是本质上并不需要太多更改,我们只需要修改Root wrapper即可。
服务器Root Wrapper调用Build之前会去云存储中检查产物,而不是像用户一样从本地中去检查。
模块划分
TODO
LLAR API设计
需求
- 提交,查询构建请求任务
- 获取构建请求信息
- 获取,删除预构建产物
获取构建产物信息
GET /v1/{{PackageName}}/{{Version}}/{{Matrix}}.{{Suffix}}
URL参数:
PackageName: Package Name
Version: Package版本
Matrix: 构建矩阵
Suffix: 文件后缀
Query参数:
id: 可选,Package ID,当存在多个相同Package Name的Package时候需要指定
返回:
Body:
302: 跳转到Package预构建云存储URL
404: 查无此包
例子:
GET /v1/zlib/v1-1.2.1/x86_64-c-linux.a
提交云构建请求
PUT /v1/build/{{PackageName}}/{{Version}}/{{Matrix}}
URL参数:
PackageName: Package Name
Version: Package版本
Matrix: 构建矩阵
Suffix: 文件后缀
Query参数:
id: 可选,Package ID,当存在多个相同Package Name的Package时候需要指定
返回:
200 OK: JSON格式:
{
"taskID": "xxxx-xxxx-xxxx-xxxx"
}
taskID: 构建任务ID
获取云构建请求
GET /v1/build/{{taskID}}
URL参数:
taskID: 构建任务ID
返回:
200 OK: JSON格式:
{
"status": "DONE"
}
status: 构建状态,有以下几种:
DONE: 已完成
STARTING: 还未开始构建
BUILDING: 构建中
数据库
云存储
直接
参考资料
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
No source files or tests are named. Start by resolving the TODO module division and reviewing the proposed /v1 endpoints, Pub-Sub scheduling flow, Kubernetes control plane, and MongoDB data layer. Done means an agreed backend design covering the API, scheduling, dependency handling, storage, and module boundaries.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, kubernetes, mongodb
- Domain
- api, backend, cloud, databases, distributed-systems
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100