Repository navigation
Distributed Judging.zh CN
English | 简体中文
推荐的 AI 完整结构:网页节点使用 --role all,保留本机评测和 AI 沙盒 worker;另加远程 judge 分担普通提交评测。纯网页结构:网页节点使用 --role web,普通提交全部由远程 judge 执行,本机不构建 rootfs。
flowchart LR
Browser[浏览器] --> Nginx[Nginx]
Nginx --> Frontend[前端资源]
Nginx --> Backend[后端]
Backend --> DB[MariaDB]
Backend --> Redis[Redis]
Backend --> MinIO[MinIO]
Judges[本机或远程评测机] <-->|认证的 WebSocket /api/socket| Backend
Judges --> Sandbox[每台节点的 simple-sandbox 与 rootfs]
Judges -->|签名下载 /storage/| Nginx
Backend -->|all 模式:本机 UNIX socket| AIWorker[本机 AI 沙盒 worker]
judge 主动连接网页节点,不需要网页节点连接评测机的入站端口。远程 judge 不持有数据库、Redis 或 MinIO 管理凭据;它通过后端领取任务,使用短期签名 URL 下载测试文件并缓存,再回传结果。当前部署采用一个后端实例,不是后端数据库的高可用集群。
评测任务保存在数据库中(表 judge_job),不只存在于 Redis:提交、Hack 或自测与其评测任务在同一事务中保存,因此重启后端或 Redis 不会丢失排队中的任务。Redis 只负责唤醒等待中的评测机,评测机每隔几秒也会主动查找任务。
- 每个任务同一时间只交给一个评测连接,并持有租约;评测机保持连接时后端会续租。结果与任务完成一起保存,来自旧租约(例如重连之前)的结果会被忽略。
- 评测机断开时,其未完成的任务会立即重新排队。后端本身停止时,其租约在 90 秒后过期,由其他后端进程或重启后的后端重新排队。因此一个任务可能被评测不止一次,但其结果只计入一次。
- 中断 5 次,或准备失败 10 次(例如缺少测试数据)后放弃该任务:对应提交显示 系统错误 及原因,可以重测。
- 站点管理员可在 评测机 页面(
/judge-machine)底部查看队列:等待中和评测中的任务、持有任务的评测机、重试次数,以及近 7 天放弃的任务。指标libreoj_judge_jobs报告等待中和评测中的任务数。 - 每次租约及其结束方式记录在
judge_job_attempt中。已完成的任务及其记录保留 30 天后删除。
以下操作位于站点管理员的 评测机 页面,每次变更都记入审计日志(judge_client.add、delete、reset_key、drain、resume)。
- 排空(暂停图标):不再向该评测机发送新任务,它会完成手中的任务。仍在评测时状态显示 排空中,完成后显示 已排空:此时可以停止、更新或调整它,不会中断评测,其他评测机继续处理队列。重新连接或后端重启后仍保持排空,直到点击 恢复(播放图标)。排空不影响本机 AI 验证,它不经过评测队列。
- 重置密钥 与 删除 立即生效:所有后端进程都会断开使用旧密钥的连接,其未完成的任务重新排队,交给其他评测机。密钥可能泄露时请重置,然后把新密钥配置到评测机上。
- 能力声明:评测机连接时会声明协议版本、可运行的任务类型、任务线程、执行槽位、AI 验证槽位与内存预算,显示在 容量 一栏。后端只向它发送其声明的任务类型。旧版本评测机不会声明,标记为 旧版:只会收到提交,Hack 与自测会等待已更新的评测机上线。
纯网页安装示例,替换仓库与实际域名:
sudo bash /tmp/llmoj-install.zh-CN.sh --repository houyhlouis/LLMOJ \
--role web --public-url http://oj.example.com公网远程评测先按 HTTPS 配置最终 HTTPS 地址,或使用受控内网。HTTP 连接会明文传输评测密钥,不适合公网的长期评测连接。
安装器已为 /api/socket 配置 WebSocket Upgrade,并将 services.minio.forJudge.urlEndpoint 设置为最终 origin 下的 /storage/。Nginx 转发存储请求时恢复 MinIO 签名所使用的内部 Host。数据库及 MinIO 本身保持回环监听。
管理员通过 POST /api/judgeClient/addJudgeClient 注册客户端,请求体为 {"name":"judge-01","allowedHosts":[]}。
在已登录管理员的站点页面打开浏览器开发者工具 Console,执行下面的请求。它从当前页面状态取得会话,不输出或复制管理员 token:
if (!window._appState?.currentUser?.isAdmin) throw new Error('请先登录管理员');
fetch('/api/judgeClient/addJudgeClient', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + window._appState.token
},
body: JSON.stringify({name: 'judge-01', allowedHosts: []})
}).then(response => response.json()).then(result => {
console.log(result.judgeClient ? '客户端已创建;请从本次响应安全保存 key' : result);
});在 Network 面板查看该次响应中的 judgeClient.key,仅保存到该评测机的私有 key 文件。每台机器注册不同客户端,使用不同 key;同一 key 的新连接会替换旧会话,不能让多台机器共享一个 key。
当前网关根据 key 认证;虽然 API 保留 allowedHosts 字段,当前连接逻辑不执行该字段的来源 IP 校验。不要把它当作访问控制措施;需要限制来源时在反向代理、VPN 或防火墙层配置。
按 Remote-Judge 部署每台 judge,使用与网页节点相同的代码版本和 rootfs 配方。日志出现“Successfully authorized as …”后,在管理员 Console 查询状态:
fetch('/api/judgeClient/listJudgeClients', {
headers: {'Authorization': 'Bearer ' + window._appState.token}
}).then(response => response.json()).then(result => {
console.table(result.judgeClients?.map(({id, name, online}) => ({id, name, online})));
});提交一个简单 C++ 程序,确认测试文件能下载、编译、运行并得到 Accepted;再验证编译错误、超时、内存超限和取消。多台节点分别验证,重启其中一台观察任务恢复。现有队列可由多个客户端消费,但不能把任务恢复理解为恰好一次执行的保证。
模型编辑、翻译、检索等后端 AI 操作可以继续配置。AI 标程验证和测试数据生成目前使用网页服务器上的本机 UNIX socket 与私有共享目录,未实现跨机器的 AI worker 协议。新增远程评测机只分担普通提交,不会迁移这些执行功能;它们需要 all 模式保留的本机 worker,在 web 模式下不可用。不要用开放 TCP 或不受控共享目录替代本机 AI socket。
- 连接失败:检查最终 origin、TLS、
/api/socketUpgrade 和独立 key。 - 在线但下载失败:检查签名 URL 是否仍指向 127.0.0.1、19000 或不可达域名;核对
/storage/转发与签名 Host。 - 多台互相掉线:检查是否共享了 key。
- cgroup 错误:检查 systemd 委托、统一 cgroup v2 和宿主内核能力。
- 增加节点后 AI 执行仍失败:检查网页节点是否保留本机 worker,分布式普通评测不能替代它。
- Hack 或自测一直等待:确认有一台未排空的在线评测机运行当前版本(不是 旧版),且其 容量 中列出了这些任务类型。
- 评测机收不到任务:检查它是否已被排空,并恢复它。
尚未完成真实多机端到端验收;部署前应完成上述现场验证。
逐项 YAML 配置、消费者/执行槽/下载队列区别、8 CPU/8 GiB 示例和保留 key 的扩缩容/回滚流程见 评测端配置。先对一台节点维护并验收,再逐台处理;远程节点扩槽不增加网页节点本机 AI worker 的容量。不要改安装 metadata 或以不同 --judge-slots 重跑安装器来代替此流程。
简体中文
- LLMOJ Wiki
- AI 运行环境变量与固定限制
- AI 配置、权限与执行流程
- 后端配置完整参考
- 团队、题解、作废、Hack 与自测升级
- 配置总览与生效规则
- 比赛赛制
- 分布式评测与网页分离
- Docker 源
- 环境变量、构建与维护工具
- 前端与 bootstrap 配置
- HTTPS 与反向代理
- Hack
- 安装与端口配置
- 评测端完整配置与 CPU 扩缩容
- 基础服务与安装后运维配置
- 发布源码、版本与 GitHub Wiki
- 新用户注册审核
- 独立评测机安装
- Self Eval(NOI / OI 比赛预测试)
- 题解
- 评测记录 Fake
- 评测记录预览
- 团队
- 两步验证
- 保留配置与数据的一键升级
English
- LLMOJ Wiki
- AI configuration, permissions and execution
- AI runtime environment and fixed limits
- Complete backend configuration reference
- Teams, solutions, moderation, Hack and self-evaluation upgrade
- Configuration overview and activation
- Contest rules
- Distributed judging and web/judge separation
- Docker sources
- Environment, builds, and maintenance tools
- Frontend and bootstrap configuration
- HTTPS and reverse proxies
- Hacks
- Installation and ports
- Complete judge configuration and CPU resizing
- Infrastructure and post-install operations
- Source, release and GitHub Wiki publishing
- Registration approval
- Independent judge installation
- Self Eval for NOI / OI contests
- Solutions
- Fake submission moderation
- Submission previews
- Teams
- Two-factor sign-in
- Upgrading while preserving configuration and data