ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Hydro 在线评测系统全景指南:从一键安装到插件化评测架构

Hydro 在线评测系统全景指南:从一键安装到插件化评测架构
  • 后端
  • 教育
  • 前端
  • 评测

【免费下载链接】Hydro

Hydro - Next generation high performance online-judge platform - 新一代高效强大的信息学在线测评系统 (a.k.a. vj5)

项目地址:https://gitcode.com/gh_mirrors/hy/Hydro
点击查看免费下载

Hydro(a.k.a. vj5)是新一代高效信息学在线测评系统(Online Judge),也是 HydroOJ 的开源核心。它以"易安装、跨平台、多功能、可扩展、有题库"为设计目标,面向学校、机构与个人搭建 OJ 平台,支持从单人部署到上千用户并发评测的规模化场景。本文基于仓库根目录 README.md 与对应源码,系统梳理 Hydro 的核心能力、安装方式、数据管理、域(Domain)隔离、权限模型、评测架构与赛制实现,帮助读者快速上手部署,并理解其底层设计原理。

一键安装:从零到可用

Hydro 为不熟悉 Linux 或不想手动运维的用户提供了两条路径:

  1. 免费在线版本:官方提供开通即用的在线版本,适合直接试用。
  2. 自建部署:将安装命令粘贴到控制台即可一键安装,安装后注册的第一个用户自动获得超级管理员权限。

官方推荐的一键安装命令为:

LANG=zh . <(curl https://hydro.ac/setup.sh)

该命令兼容主流 Linux 发行版,官方推荐使用 Debian 12,并支持 arm64 设备(如树莓派、Apple M1/M2)。仓库内的安装脚本入口为 install/install.sh,它检测 root 权限、创建/data/db、/data/file等数据目录,并调用 install/install.ts 完成依赖安装(Node.js、MongoDB、评测沙箱等)与系统初始化。安装脚本会根据系统内存自动调整缓存参数(如wtCacheSize),默认设置vm.swappiness=1以提升性能。

此外,仓库还提供了多种部署编排方案:

  • Docker / docker-compose:见 install/docker/docker-compose.yml,其中 backend 与 judge 各有独立镜像构建文件;
  • Kubernetes / Helm:见 install/helm-single 的完整模板(backend、judge、mongo 的 deployment 与 service 等);
  • Nix:见 install/nix 的 flake 配置,Nix 用户可直接通过 nix profile 安装 hydro-plugin 系列插件。

从源码结构看,packages/hydrooj(npm 包名hydrooj)是系统核心,packages/hydrojudge是评测核心,二者通过 MongoDB 中的任务集合解耦协作。

模块化插件系统:功能热插拔的架构基石

插件机制与热更新

Hydro 的核心亮点之一是模块化插件系统:系统主体(core)与各功能模块(插件)分离,可以在修改功能后仍然保证系统的可升级性,所有历史版本均可平滑升级到最新版本。从源码结构看,这一设计体现在两个层面:

  • 核心进程:packages/hydrooj/src/loader.ts 中的Loader服务负责插件的加载、解析与重载。它通过resolvePlugin按名称解析插件路径,支持从 npm 包与 Nix 存储路径(/nix/store)加载插件;reloadPlugin在插件配置变更时执行"更新或应用"操作,并监听system/setting事件实现配置热重载。启动时load()会遍历所有 addon,将插件版本写入global.Hydro.version。
  • 插件 API:packages/hydrooj/src/plugin-api.ts 集中导出了插件开发所需的全部能力,包括Context、Fiber、Service生命周期模型,Handler/ConnectionHandler服务端处理框架,以及UserModel、ProblemModel、RecordModel、DomainModel等数据模型。从该文件可以看出,插件可以访问系统几乎全部的服务与模型,从而实现"修改功能而不动主代码"。

仓库packages/目录下的大量独立包即是插件化的直接体现:博客(blog)、一键安装工具包(onsite-toolkit)、计分板(scoreboard-xcpcio)、Telegram 登录(telegram)、弹性搜索(elastic)、性能指标(prom-client)、题单导入(import-hoj、import-qduoj、fps-importer、migrate)等均以独立 npm 包形式存在,可按需装载或卸载。

插件安装与卸载

从 packages/hydrooj/src/commands/install.ts 及更新日志可知,Hydro 提供命令行快速管理插件:

hydrooj install <插件包名或路径> hydrooj uninstall <插件名>

插件既可以从 npmjs 自动安装,也可以从本地 addons 目录或 Nix profile 加载(loader.ts 中通过NIX_PROFILES环境变量读取 nix profile 中的hydro-plugin-*派生)。核心进程通过getAddons()读取 addon 配置,并在加载失败时向管理员推送系统通知。

跨平台兼容与数据一键备份/恢复

跨平台与架构支持

Hydro 支持所有主流 Linux 发行版,兼容 x86_64 与 arm64 架构设备,可一键安装运行于树莓派、Apple M1/M2 等设备。评测沙箱实现(由 packages/hydrojudge 承担)在多种架构上均提供一致的隔离执行环境。

hydrooj backup / restore

Hydro 提供了全自动的数据备份与恢复命令,无需手工干预:

hydrooj backup # 备份系统全部数据 hydrooj restore <备份文件名> # 从备份恢复

从 packages/hydrooj/src/commands/db.ts 的实现可以看出备份机制的完整细节:

  • 备份过程:使用mongodump导出数据库(默认排除opcount、event集合,未指定--withLogs时也排除oplog),再将测试数据文件(/data/file)一并打包为backup-<时间戳>.zip,输出到当前工作目录。
  • 可选参数:
    • --dbOnly:仅导出数据库,不含测试数据文件;
    • --withAddons:同时打包addons目录与addon.json插件配置;
    • --withLogs:附带/data/access.log访问日志;
    • -r <repo>/-p <password>:将备份推送至 restic 仓库(支持增量备份)。
  • 恢复过程:restore接受 zip 文件、已解压目录或 restic 仓库,执行前默认要求交互确认(-y可跳过确认),使用mongorestore --drop覆盖恢复数据库,并将文件数据恢复至/data/file,可选恢复 addons 配置。

备份的目标是"整个过程无需手工干预",同时--withAddons保证插件配置与数据一并迁移,实现整站迁移。

另外,CLI 还提供了hydrooj db命令直接进入 MongoDB 交互终端(自动优先探测mongosh,失败则回退旧版mongo),以及hydrooj cli交互模式(entry/cli.ts),支持在交互式提示符中逐条执行模型方法,便于运维调试。

单系统多空间(Domain):班级/院校分开管理

Hydro 提供单系统多空间支持:一个部署实例可以创建多个独立"域"(Domain),为不同的班级、年级、院校等组织分别建立空间。

从 packages/hydrooj/src/model/domain.ts 可以看出,域是一个包含_id(域 ID)、owner(域主)、name、bulletin(公告)、roles(角色表)等字段的独立实体;域的创建、编辑均通过DomainModel完成,并触发domain/create等事件钩子。

多空间机制的核心特性:

  • 数据默认隔离:不同域内除用户外,题目、评测记录、讨论、比赛等数据默认互相隔离。这一点从各数据模型的查询方式可以得到印证——例如 packages/hydrooj/src/model/record.ts 中getMulti(domainId, query)强制以domainId作为查询前缀。
  • 独立管理员:每个域可分配独立的管理员,互不干扰。
  • 跨域题目复制:题目可以跨域复制,系统内仅占用一份空间。从 packages/hydrooj/src/model/problem.ts 的ProblemModel.copy可以看出,复制时目标题目会写入reference: { domainId, pid }字段作为引用标记,评测时 record.ts 的judge方法会解析pdoc.reference追溯到源域的题目数据(source = ${pdoc.domainId}/${pdoc.docId}),从而做到多域共享同一份题目与测试数据。

粒度精细的权限系统

Hydro 的权限模型支持"按比赛/作业分配给用户"与"按用户分组(班级)分配"两种方式,权限节点覆盖从查看、提交、评测管理到系统设置的全层级。

从源码层面看,权限常量定义于 packages/hydrooj/src/model/builtin.ts,包括:

  • PERM_VIEW_PROBLEM_HIDDEN、PERM_VIEW_RECORD、PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD、PERM_VIEW_HIDDEN_CONTEST、PERM_VIEW_HIDDEN_HOMEWORK、PERM_VIEW_USER_PRIVATE_INFO等查看类权限;
  • 用户分组(小组/班级)机制支持按组批量授予权限,也支持批量导入导出小组成员(见更新日志中"用户小组:支持批量导入导出")。

从更新日志与 handler/contest.ts 的实现看,权限的精细度延伸到了比赛场景:例如封榜期间仅持有PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD的管理员能查看实时榜单;PERM_VIEW_DISPLAYNAME已更名为PERM_VIEW_USER_PRIVATE_INFO,控制实名信息(姓名/学号)的可见性。

规模化支持:无状态架构与自动伸缩

Hydro 系统本身是无状态的,因此可以随意增删服务节点而不影响系统运行。评测任务通过 MongoDB 中的任务集合分发,评测机上线即自动消费任务、下线即暂停消费,天然支持弹性伸缩。

这一设计的底层依据可以从两个源码文件得到印证:

  • 任务生产:packages/hydrooj/src/model/record.ts 的RecordModel.judge将评测任务批量写入任务集合(task.addMany),任务携带priority优先级、type(judge/remotejudge/generate)、config、source等字段。其中submissionPriority会根据用户近 30 分钟的提交频率与排队数动态计算优先级,实现公平调度。
  • 任务消费:packages/hydrooj/src/model/task.ts 的Consumer类按{ priority: -1 }排序取出任务(findOneAndDelete),支持并发数控制(setConcurrency)与失败自动恢复(destroyOnError),并在数据库层面建立{ type, subType, priority: -1 }复合索引保证调度性能。

在此基础上:

  • 评测队列均衡分配:多个评测机(judge)同时在线时,任务被各评测机竞争消费,从而在所有在线评测机之间自然均衡分布;
  • 接入弹性伸缩组:可根据服务器负载自动增删评测机,配合无状态架构实现秒级扩展;
  • 按需缓存测试数据:与多数 OJ 不同,Hydro 会统一管理各服务器间的测试数据缓存,按需拉取,评测机"上线即用",无需手动同步数据。从 packages/hydrojudge/src/hosts 的hydro.ts(评测机与核心服务交互的主机实现)可以看到,评测机通过 WebSocket 连接核心服务并周期性发送心跳,任务完成后将评测结果回传。

全题型支持

Hydro 支持所有常见题型,包括:

  • 传统题型(标准输入输出比较)
  • Special Judge(SPJ,特判)
  • 文件输入输出(文件 IO)
  • 提交答案题
  • IO 交互题
  • 函数交互题
  • 客观题(选择/填空,支持多选题与下拉菜单等,见更新日志中"客观题:支持下拉菜单""客观题:允许多行答案")

评测端 packages/hydrojudge/src/judge 目录下按题型拆分了实现模块:default.ts(传统)、communication.ts(通信/交互)、interactive.ts(交互)、submit_answer.ts(提交答案)、objective.ts(客观题)、generate.ts(生成数据)、hack.ts(Hack)等。更新日志还显示新版本新增了 multi-pass 题型支持。

安装相关运行环境后,Hydro 甚至可以实现两类高级评测场景:

  • 绘图比对:调用小海龟(turtle)画图,将输出与标准图片比对;
  • 机器学习评测:调用 GPU 运行机器学习模型并评测其结果。

更多样例可参考仓库 examples/testdata 中的测试数据(如 Special Judge 的 chk.cc 与 config.yaml),了解题目配置文件的书写方式。

丰富的题库与多平台导入

Hydro 支持导入常见格式的题库文件:

  • Hydro 通用 zip 格式:包含题目配置、测试数据、题面(Markdown)与标程;
  • HUSTOJ 导出的 FPS(xml)格式:由 packages/fps-importer 插件负责解析导入;
  • QDUOJ 导出的压缩包:由 packages/import-qduoj 插件处理;
  • 旧系统迁移:packages/migrate 提供了 HUSTOJ、JNOJ、POJ、SYZOJ、UniversalOJ、Vijos、UOJ 等多套历史系统的迁移脚本;
  • ICPC 题目包:支持标准 ICPC package 格式导入(更新日志中多次出现"icpc package format"相关优化)。

同时,Hydro 内置VJudge 虚拟评测能力(packages/vjudge),可以直接在系统内接入其他 OJ 平台,导入题目后修改题面、编入自己的作业或比赛,快速搭建题库体系。当前支持的平台(对应 packages/vjudge/src/providers 下的实现)包括:

平台说明
UOJ国内知名 OJ,国家集训队常用
Codeforces国外大型竞赛平台,大量高质量题目
洛谷使用此功能需要向洛谷购买授权
HDUOJ杭州电子科技大学在线评测系统,含多校训练题
CSGOJ广东省赛与湖南省赛赛题评测平台
SPOJ国内连接很不稳定,不推荐
POJ较为古董,服务器稳定性差
YACS上海市计算机学会竞赛平台,单账号每日提交有限制
HUSTOJ理论上支持所有 HUSTOJ 驱动的系统,但各系统 UI 有差异,通常需手动适配

除 VJudge 外,官方还提供可直接导入的免费题库资源(如"一本通编程启蒙""深入浅出程序设计竞赛"配套题库),可参照压缩包内导入说明使用。

多赛制支持

Hydro 支持多种赛制,其核心实现在 packages/hydrooj/src/model/contest.ts,文件末尾的RULES注册表统一管理了所有赛制规则:

export const RULES: ContestRules = { acm, oi, homework, ioi, ledo, strictioi, };

各赛制特点如下:

  • ACM/ICPC 赛制(acm):按 AC 数降序、用时升序排名(statusSort: { accept: -1, time: 1 }),支持封榜(lockAt)——封榜后的提交会计入 Pending(npending),榜单冻结;管理员可通过PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD查看实时分数。罚时按 20 分钟/次错误提交累加(penalty = 20 * 60 * naccept)。
  • OI 赛制(oi):按总分排名,支持赛后订正。
  • IOI 赛制(ioi)与IOI-strict(strictioi):在 IOI 与 OI 赛制下,支持订正题目功能——学生赛后可在题库中提交对应题目,订正分数显示在榜单旁边;同时支持灵活时间功能——学生可在设定时间范围内自选 X 小时参赛(tdoc.duration与tsdoc.startAt参与判定)。
  • 乐多赛制(ledo):基于 OI 规则扩展,特点是"多次提交、多题得分"式积分,且对同一题允许重复提交计分(submitAfterAccept: false)。
  • 作业(homework):作为隐藏规则(hidden: true)提供作业布置与提交管理能力。

从isLocked(contest.ts 第 78-81 行)可以看到封榜判定逻辑:当lockAt < now且未显式解锁(unlocked)时视为封榜。新版还支持"比赛结束后不公开榜单"(keepScoreboardHidden)、"比赛前移除参赛者""提前退出比赛"等精细化赛程控制。

轻松添加其他编程语言

Hydro 的语言设置并非硬编码于系统中,而是使用配置文件——只要能写出对应语言的编译命令与运行命令,Hydro 就可以进行判题。

评测机侧的语言预设位于 packages/hydrojudge/langs.yaml,其配置结构如下(节选):

c: compile: /usr/bin/gcc -O2 -Wall -std=c99 -o foo foo.c -lm cc: compile: /usr/bin/g++ -O2 -Wall -std=c++11 -o foo foo.cc -lm pas: compile: /usr/bin/fpc -O2 -ofoo foo.pas java: compile: /usr/bin/bash -c "javac -d /w -encoding utf8 ./Main.java && jar cvf Main.jar *.class >/dev/null" code_file: Main.java target: Main.jar execute: /usr/bin/java -Dfile.encoding="UTF-8" -cp Main.jar Main time_limit_rate: 2 compile_time_limit: 30000 compile_memory_limit: 1024 py3: compile: /usr/bin/python3 -c "import py_compile; py_compile.compile('/w/foo.py', '/w/foo', doraise=True)" code_file: foo.py execute: /usr/bin/python3 foo rs: compile: /usr/bin/rustc -O -o /w/foo /w/foo.rs compile_time_limit: 30000

配置项说明:

  • compile:编译命令,其中foo代表编译产物,/w为评测沙箱内的工作目录;
  • execute:运行命令,foo代表可执行文件;
  • code_file:选手提交代码在沙箱内写入的文件名(如 Java 要求Main.java);
  • target:编译目标产物(如Main.jar);
  • time_limit_rate/memory_limit_rate:该语言相对基准时空限制的倍率(如 Java 时限倍率 2);
  • compile_time_limit/compile_memory_limit:编译阶段独立的时限与内存限制。

评测机启动时通过 packages/hydrojudge/src/hosts/vj4.ts 等宿主实现读取并解析该配置文件(parseLang(fs.readFileSync(...langs.yaml))),因此管理员只需编辑此 YAML 即可为系统添加任意语言。系统还预置了 C/C++、Pascal、Java、Python3、PHP、Rust、Haskell、JavaScript、Go、Ruby、C#(Mono)、Kotlin、PyPy3、R 语言、Bash、C++20 等常用语言,并支持按题目设置语言时空限制倍率、validAs语言别名、以及langs.domain等域级覆盖。

更新日志亮点与版本演进

README 附带了完整的更新日志(Hydro 5.x / UI 4.5x 系列),从中可以观察到项目的演进脉络:

  • 5.0 系列:升级到 React 19 与 MongoDB Driver 7;新增 CLI 交互模式(hydrooj cli)、OIDC 模块、multi-pass 题型、pipe_proxy、比赛结束后不公开榜单、比赛补题模式等;重构了插件注入(强制inject声明依赖)、移除了旧版 bus 调用与setting.yaml,最低要求 Node 22。
  • 架构持续解耦:framework 从 core 解离为独立包(framework);API 模块移入 service;UI 端逐步将缓存迁移至 IndexedDB。
  • 运维能力增强:hydrooj diag快速诊断工具、基于 restic 的增量备份、fixStorage修复脚本、--disable-worker启动选项、加载器多 profile 切换等。

开源许可与贡献

仓库采用混合许可策略:

  • framework、examples、install 目录下的内容采用MIT 协议,可自由使用;
  • packages/ui-default 下的内容仅采用AGPL-3.0授权;
  • 项目其余部分采用双重许可:可在遵守 AGPL-3.0 许可证及附加条款的前提下免费使用,也可联系作者购买闭源授权。

附加条款(基于 AGPL-3.0 第七条)要求:不可移除版权声明与作者/来源署名;重分发修改版时需在软件名或版本号中注明修改;不得未经许可以宣传为目的使用作者姓名。具体到部署场景:部署 Hydro 时需保留页面底部Powered by Hydro字样,其中Hydro需指向官方仓库或其 fork 的链接;若对源码做出修改/扩展,同样需以 AGPL-3.0-or-later 开源,可按照Powered by Hydro, Modified by xxx格式在页脚注明。详细条款见 LICENSE。

欢迎通过提交 Pull Request 完善文档、在 Issues 中反馈 bug 与功能建议;贡献规范见 CONTRIBUTING.md。

  • 后端
  • 教育
  • 前端
  • 评测

【免费下载链接】Hydro

Hydro - Next generation high performance online-judge platform - 新一代高效强大的信息学在线测评系统 (a.k.a. vj5)

项目地址:https://gitcode.com/gh_mirrors/hy/Hydro
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进