Judge0 1.13.1 介绍与选型指南
Judge0 1.13.1 介绍与选型指南:REST 代码执行引擎定位、Rails+PostgreSQL+Redis+isolate 四层架构、47 种语言与同步/异步/批量/回调提交、与 Piston/OnlineJudge/HUSTOJ/CodeBox 逐维对比、适用边界(isolate 不是逃逸防护),含最小可用部署与 curl 实测回显。
Judge0 1.13.1 介绍与选型指南
目标:把 Judge0 1.13.1 这套开源自托管在线代码执行系统讲清楚,帮助你在「引入一个在线判题 / 代码运行服务」这件事上做出选型判断。本文说明它的定位、四层架构(Rails API + PostgreSQL + Redis 队列 + isolate 隔离执行)、核心特性与 API 形态,给出可复制的最小可用验证过程,并把 Judge0 与 Piston、QingdaoU OnlineJudge、HUSTOJ、CodeBox 放在同一张表里逐维对比,最后明确它「能干什么、不能干什么」——尤其是不要把 isolate 当成抵御恶意代码逃逸的安全边界。文中版本信息、仓库活跃度与快速开始回显分别采自 2026-10-27 的 GitHub API 查询与本地 1.13.1 实例实测。
一、环境信息
本篇的实证环境如下,读者复现时替换为自己的取值即可:
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS(x86_64) |
| 实测版本 | Judge0 CE 1.13.1(GitHub Release v1.13.1,2024-04-18 发布) |
| 运行时 | Ruby 2.7.0 + Rails 5.0.x + Puma 4.3.5 + Resque 2.0 |
| 数据库 | PostgreSQL 16.2(官方编排给出的配套版本) |
| 队列 | Redis 7.2.4 |
| 隔离执行 | isolate(IOI 官方沙箱,随镜像编译) |
| 服务端口 | 2358(容器内),本文实测映射到宿主机 8138 |
| 许可证 | GPL-3.0 |
💡 说明:Judge0 的版本号长期停留在 1.13.x(1.13.0 为 2021-03-10,1.13.1 为 2024-04-18),仓库 2026-10-18 仍有提交,但没有新的 release 发布。选型时要把「功能版本停滞」与「仓库仍在维护」这两件事分开看,详见第六章。
二、软件概述
2.1 定位:不是 OJ 网站,而是 OJ 背后的执行引擎
Judge0 是一个在线代码执行系统(online code execution system),对外只暴露 REST API:你提交「源码 + 语言 ID + stdin」,它返回「stdout/stderr + 退出状态 + 耗时 + 内存」。它不提供题库、比赛、排行榜、用户体系,这些属于上层 OJ 的职责。
这一定位决定了它的两个典型用法:
- 作为判题后端:上层 OJ/教学平台/面试系统自己管题目与用户,把「跑一次代码」这件事委托给 Judge0;
- 作为代码运行沙箱服务:在线 IDE、文档站的可运行示例、AI Agent 的代码执行工具,直接调用
/submissions拿运行结果。
2.2 版本与发行版
| 发行版 | 说明 | 当前版本 | 发布形态 |
|---|---|---|---|
| Judge0 CE | 社区版,本专栏对象,功能完整、开源免费 | 1.13.1 | GitHub Release v1.13.1 + Docker Hub judge0/judge0:1.13.1 |
| Judge0 Extra CE | 社区增强版,额外包含更多语言与部分商业版特性 | 1.13.1 | GitHub Release v1.13.1-extra |
| Judge0 商业版 | 官方托管的 SaaS/私有部署授权 | 以官网为准 | 需购买,本文不涉及 |
两个 CE 版本的代码同源,-extra 额外打包了一批语言运行时与编译器。本文全部实测基于 1.13.1(非 extra)。
2.3 项目活跃度(2026-10-27 实查)
| 指标 | 值 | 取数口径 |
|---|---|---|
| GitHub 仓库 | judge0/judge0 | API /repos/judge0/judge0 |
| Star / Fork | 4492 / 944 | 同上 |
| 未关闭 Issue | 200 | 同上 |
| 最近一次代码推送 | 2026-10-18 | pushed_at |
| 最近一次 Release | 2024-04-18(1.13.1) | /releases |
| 许可证 | GPL-3.0 | license.spdx_id |
解读:代码在动、发版不动。近两年半的提交以文档、依赖修补、CI 为主,功能面基本冻结。对内部平台这是可接受的稳定状态;对需要长期跟进安全补丁的对外服务,就要评估自行维护分支的成本,且 GPL-3.0 意味着二次分发有开源义务。
三、核心架构
3.1 四层组件与数据流
Judge0 是标准的「Web 层 + 关系库 + 消息队列 + 执行器」结构,四层各司其职:
| 层 | 组件 | 职责 | 关键点 |
|---|---|---|---|
| 接入层 | Rails 5 API(Puma) | 接收 HTTP、参数校验、写库、返回结果 | 单进程多线程,RAILS_MAX_THREADS 控制并发 |
| 存储层 | PostgreSQL | 存 submission 全量记录、语言表、状态表 | submission 是唯一事实来源,队列只存「待办 ID」 |
| 队列层 | Redis + Resque | 存放待执行任务、worker 心跳与队列长度 | 提交先落库再入队,服务重启不丢任务 |
| 执行层 | Resque worker + isolate | 取任务、在隔离环境里编译运行、回写状态 | 每个 worker 串行执行一个 submission |
一次异步提交的完整链路:
client ──POST /submissions──▶ Rails API
│ 1. 校验语言/参数,写入 submissions 表(status=1 In Queue)
│ 2. Resque.enqueue(submission_id) ──▶ Redis 队列
▼
Resque worker ──▶ 取出 submission_id
│ 3. 从 PostgreSQL 读源码,准备 isolate 沙箱目录
│ 4. isolate 内编译(编译型语言)+ 运行,采集 stdout/stderr/耗时/内存
│ 5. 回写 submissions 表(status=3/4/5/6/7…)
▼
client ──GET /submissions/{token}──▶ 读到最终状态;或第 5 步后由服务端回调 webhook
💡 技术拓展:在线代码执行系统的隔离手段不止一种,选型时这是最该看的一列——
隔离机制 代表实现 特点 取舍 isolate(cgroup + namespace + seccomp) Judge0、Codeforces 系 轻量、启动毫秒级、按提交限 CPU/内存/进程数 依赖宿主机内核特性,需特权/委派 cgroup Linux 容器(LXC/Docker) Piston 生态成熟、镜像即语言包 每提交起停开销大,隔离粒度受容器配置影响 gVisor / Kata 商业多租户执行平台 用户态内核或轻量 VM,隔离强 资源开销大,语言运行时兼容性要逐个验证 整机/VM 池 部分竞赛平台 最强隔离 成本高、调度复杂 Judge0 采用 isolate:单次提交在一个受限的进程组里编译运行,CPU/内存/进程/文件大小全部由 cgroup 与 rlimit 约束,启动开销低,适合高并发短任务;代价是必须让执行进程拥有足够的宿主权限(官方编排直接给
privileged: true)。
3.2 为什么必须 privileged(以及它意味着什么)
isolate 要创建 cgroup、挂载 namespace、设置 rlimit,普通容器权限不足时会直接报错。官方 docker-compose.yml 里 server 与 workers 两个服务都写了 privileged: true,这不是偷懒,而是 isolate 的工作前提。
对选型的含义很直接:Judge0 的执行节点等于「把你的内核能力交给它」。所以正确做法是把执行节点放在独立的内网主机/独立 VM,只让 API 层对外,绝不能让执行节点直接暴露公网,也不能与业务数据同机混跑。
3.3 提交状态机
Judge0 用数字状态码表达一次提交的生命周期,GET /statuses 返回全量:
| ID | 状态 | 含义 |
|---|---|---|
| 1 | In Queue | 已入库,等待 worker |
| 2 | Processing | worker 正在编译/运行 |
| 3 | Accepted | 正常退出(退出码 0) |
| 4 | Wrong Answer | 仅当配置了 expected_output 比对时出现 |
| 5 | Time Limit Exceeded | 超 CPU/墙钟限制 |
| 6 | Compilation Error | 编译失败 |
| 7 | Runtime Error (SIGSEGV) | 段错误 |
| 8 | Runtime Error (SIGXFSZ) | 超出文件大小限制 |
| 9 | Runtime Error (SIGFPE) | 算术异常 |
| 10 | Runtime Error (SIGABRT) | abort |
| 11 | Runtime Error (NZEC) | 非零退出码 |
| 12 | Runtime Error (Other) | 其他信号 |
| 13 | Internal Error | Judge0 自身异常 |
| 14 | Exec Format Error | 可执行格式错误 |
前端/上层平台只需把 1、2 当作「进行中」,3 当作通过,其余按失败分类展示即可。
四、功能特性
4.1 语言支持
GET /languages 返回当前实例可用语言清单,每条含 id(提交时用的数字)、name、version、source_file、compile_cmd、run_cmd 等字段。社区版镜像预置了主流语言(C/C++、Java、Python、Go、Rust、Node.js、PHP、Ruby、C#、Kotlin、Swift、SQL 等),实测语言条目数量见第五章快速开始的 /languages 回显。
新增语言不需要改 Judge0 代码:在 languages 表插入记录并保证执行节点里有对应运行时即可,这也是它常被用作「通用代码运行服务」的原因。
4.2 提交方式:同步、异步、批量、回调
同一套 /submissions 端点通过参数切换四种取结果方式,覆盖不同集成场景:
| 方式 | 用法 | 适用场景 | 代价 |
|---|---|---|---|
| 异步 | POST /submissions 拿 token,再轮询 GET /submissions/{token} | 默认方式,客户端可自由控制节奏 | 需要自己实现轮询 |
| 同步 | POST /submissions?wait=true | 交互式运行、简单脚本 | 请求会被占住直到出结果,受 ENABLE_WAIT_RESULT 开关约束 |
| 批量 | POST /submissions/batch + GET /submissions/batch?tokens=... | 一次跑多语言/多用例 | 单批上限 MAX_SUBMISSION_BATCH_SIZE(默认 20) |
| 回调 | 提交时带 callback_url | 无公网轮询能力的服务端 | 目标地址必须可达,有重试与超时(默认 3 次 / 5 秒) |
4.3 资源限制与限流
限制分两层:
- 单次执行限制:
CPU_TIME_LIMIT(默认 5s)、WALL_TIME_LIMIT(默认 10s)、MEMORY_LIMIT(默认 128000KB)、STACK_LIMIT(默认 64000KB)、MAX_PROCESSES_AND_OR_THREADS(默认 60)、MAX_FILE_SIZE(默认 1024KB)。客户端可在MAX_*上限内按次放宽。 - 服务容量限制:
MAX_QUEUE_SIZE(默认 100,队列满时新提交被拒绝)、COUNT(worker 数,默认 2×CPU 核数)、INTERVAL(轮询间隔,默认 0.1s)、RAILS_MAX_THREADS(API 线程数)。
⚠️ 注意:Judge0 自身没有内建「按 IP/按用户的 QPS 限流」。
AUTHN_TOKEN只解决「谁能调用」,不解决「调用多少次」。对外服务必须在前面加 Nginx/网关限流,并配合MAX_QUEUE_SIZE保护执行节点。
4.4 鉴权与访问控制
AUTHN_HEADER+AUTHN_TOKEN:请求头或查询参数携带,默认头名X-Auth-Token,令牌为空即关闭鉴权;ALLOW_ORIGIN/DISALLOW_ORIGIN/ALLOW_IP/DISALLOW_IP:CORS 与来源 IP 白名单;AUTHZ_HEADER+AUTHZ_TOKEN:保护删除提交等高危操作(默认关闭)。
4.5 其他能力
- 额外文件:
additional_files(zip/tar 的 base64),可给提交预置数据文件,解压总量受MAX_EXTRACT_SIZE(默认 10MB)约束; - 编译选项与命令行参数:
compiler_options、command_line_arguments,可用开关或语言白名单收紧; - 提交缓存:
SUBMISSION_CACHE_DURATION(默认 1s)内相同请求直接复用结果,抵御重复提交; - 维护模式:
MAINTENANCE_MODE打开后拒绝新建/删除提交,适合升级窗口; - 可观测性:
/system_info给出队列长度、worker 数、各状态提交数;/workers给出每个 worker 的心跳与作业。
五、快速开始
验证一套 Judge0 是否可用,最短路径是「起服务 → 查版本 → 查语言 → 提交一段 hello world」。以下命令与回显来自本机 1.13.1 实例(宿主机端口 8138),逐条可复现。
5.1 起一套最小服务
Judge0 官方只提供一种开箱方式:用 docker-compose.yml 编排四个服务(server、workers、db、redis),镜像 judge0/judge0:1.13.1,数据库 postgres:16.2,队列 redis:7.2.4。server 与 workers 都必须 privileged: true,否则 isolate 无法工作。
services:
server:
image: judge0/judge0:1.13.1
volumes:
- ./judge0.conf:/judge0.conf:ro
ports:
- "8138:2358"
privileged: true
restart: always
workers:
image: judge0/judge0:1.13.1
command: ["./scripts/workers"]
volumes:
- ./judge0.conf:/judge0.conf:ro
privileged: true
restart: always
db:
image: postgres:16.2
env_file: judge0.conf
volumes:
- ./data:/var/lib/postgresql/data
restart: always
redis:
image: redis:7.2.4
command: ["bash", "-c", 'docker-entrypoint.sh --appendonly no --requirepass "$$REDIS_PASSWORD"']
env_file: judge0.conf
restart: always
judge0.conf 至少要给出 REDIS_PASSWORD、POSTGRES_DB、POSTGRES_USER、POSTGRES_PASSWORD 四项,其余按默认值即可。启动后四个服务的状态:
docker compose ps
NAME IMAGE COMMAND SERVICE STATUS PORTS
judge0-1131-stack-db-1 postgres:16.2 "docker-entrypoint.s…" db Up 30 seconds 5432/tcp
judge0-1131-stack-redis-1 redis:7.2.4 "docker-entrypoint.s…" redis Up 30 seconds 6379/tcp
judge0-1131-stack-server-1 judge0/judge0:1.13.1 "/api/docker-entrypo…" server Up 30 seconds 0.0.0.0:8138->2358/tcp
judge0-1131-stack-workers-1 judge0/judge0:1.13.1 "/api/docker-entrypo…" workers Up 30 seconds 2358/tcp
四个服务全部 Up 且 API 端口可达,才算起服务成功;db、redis 没有映射宿主端口属正常现象,它们只在编排内网中被 server/workers 访问。
5.2 查版本与语言清单
curl -s http://127.0.0.1:8138/about
{"version":"1.13.1","homepage":"https://judge0.com","source_code":"https://github.com/judge0/judge0","maintainer":"Herman Zvonimir Došilović \u003chermanz.dosilovic@gmail.com\u003e"}
/about 是探活与版本核对的最轻量端点。接着看当前实例的语言总量与几个常用条目:
curl -s http://127.0.0.1:8138/languages | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d))"
curl -s http://127.0.0.1:8138/languages | python3 -c "import sys,json; d=json.load(sys.stdin); print([(x['id'],x['name']) for x in d if x['id'] in (54,62,71,76)])"
47
[(76, 'C++ (Clang 7.0.1)'), (54, 'C++ (GCC 9.2.0)'), (62, 'Java (OpenJDK 13.0.1)'), (71, 'Python (3.8.1)')]
本地 1.13.1 实例实测 47 种语言(社区版镜像的默认语言表)。提交时要传的是这里的 id(如 Python 3.8.1 为 71),不是语言名字。
5.3 提交第一段代码
wait=true 让服务端等到执行结束再返回,一条 curl 就能看到完整结果:
curl -s -X POST 'http://127.0.0.1:8138/submissions?base64_encoded=false&wait=true' \
-H 'Content-Type: application/json' \
-d '{"source_code":"print(\"hello judge0\")","language_id":71}'
{"stdout":"hello judge0\n","time":"0.01","memory":7908,"stderr":null,"token":"42078485-070b-45ac-a764-903bbb2f4906","compile_output":null,"message":null,"status":{"id":3,"description":"Accepted"}}
status.id=3 即 Accepted;time 单位为秒、memory 单位为 KB。拿到 token 后还可以随时用 GET /submissions/{token} 复查这次提交,这也是异步方式的取结果路径。
⚠️ 注意:如果你的宿主机是 cgroup v2(Ubuntu 22.04+ 默认),1.13.1 镜像内置的 isolate 1.8.1 不支持 v2,默认参数提交会返回
Internal Error与No such file or directory @ rb_sysopen - /box/script.py。本文实测环境即属此情况,处理办法是不让 worker 走--cg:把app/jobs/isolate_job.rb里@cgroups的取值改为空字符串,或在每次提交时显式传enable_per_process_and_thread_time_limit、enable_per_process_and_thread_memory_limit两个true。判断依据:docker exec <worker> isolate --cg -b 1 --init报Failed to create control group /sys/fs/cgroup/memory/box-1/: No such file or directory。
六、适用场景与限制
6.1 适用场景
| 场景 | 为什么合适 |
|---|---|
| 高校/培训机构 OJ 判题后端 | 语言覆盖全、状态码体系标准化、批量提交适合多测试点 |
| 在线 IDE / 文档站「运行示例」 | wait=true 一次请求拿到结果,集成成本极低 |
| 面试/笔试平台的代码题评测 | 支持 compiler options、additional files、回调 |
| AI Agent 的代码执行工具 | REST 接口易封装,/system_info 可做容量观测 |
| 多租户 SaaS 的「运行代码」功能 | 资源限制细到进程/文件/内存,可配队列上限 |
6.2 不适用与明确边界
- 不要把它当题库/OJ 网站:没有题目、比赛、排名、用户体系,这些要自己实现或选 OnlineJudge/HUSTOJ。
- 不要把 isolate 当作「抵御恶意代码逃逸」的安全边界:isolate 约束的是资源(CPU/内存/进程/文件/网络),它假设运行环境本身可信。执行节点以 privileged 运行,一旦语言运行时或内核存在提权漏洞,逃逸后果是宿主机级别。
- 正确姿势:执行节点独立内网主机/VM、只跑 Judge0、不存业务数据、不挂敏感目录、按需关闭
ENABLE_NETWORK、定期打内核与运行时补丁; - 面向不可信公网用户时,应叠加外层 VM/gVisor/Kata 或独立物理机隔离,而不是只依赖 isolate。
- 正确姿势:执行节点独立内网主机/VM、只跑 Judge0、不存业务数据、不挂敏感目录、按需关闭
- 不要期待高频发版:1.13.1 之后无新 release,新语言/新运行时需要自己往
languages表加并保证执行节点有对应环境。 - 不要用它做长任务:默认墙钟上限 10s,且 worker 串行执行,长任务会堵塞队列。
6.3 容量估算的粗略口径
单 worker 同一时刻只跑一个提交,吞吐 ≈ worker 数 / 平均单次执行耗时。以默认 COUNT = 2×CPU 估算,6 核机器约 12 个 worker;若平均每次编译+运行 1.5s,理论吞吐约 8 次/秒,实际还要扣除编译开销与队列轮询延迟。/system_info 的队列长度是判断要不要加 worker 的直接依据。
七、同类选型对比
7.1 五个项目同表对比(2026-10-27 实查)
| 维度 | Judge0 1.13.1 | Piston | QingdaoU OnlineJudge | HUSTOJ | CodeBox |
|---|---|---|---|---|---|
| 定位 | 通用代码执行 API | 通用代码执行 API | 完整 OJ 网站(题库/比赛/用户) | 完整 OJ 网站(ACM/NOIP 训练) | 云端/桌面 IDE(非判题) |
| 技术栈 | Ruby 2.7 + Rails 5 + PostgreSQL + Redis | Node.js | Vue + Django + PostgreSQL + Docker | PHP + C++ judge + MySQL | Node.js |
| 隔离机制 | isolate(cgroup/namespace/seccomp) | LXC 容器 | 自研 judger(容器/沙箱) | 自研 judge_client(rlimit/ptrace) | 无判题能力 |
| 语言扩展 | 改 languages 表 + 装运行时 | 安装运行时包(piston 包管理) | 需改 judger 配置 | 改 db_info/编译脚本 | 不适用 |
| 对外接口 | REST,同步/异步/批量/回调 | REST,同步为主 | REST(判题以外还有站务 API) | 以 Web 为主,API 有限 | 无判题 API |
| 许可 | GPL-3.0 | MIT | MIT | GPL-2.0 | Apache-2.0 |
| 社区规模(Star/Fork) | 4492 / 944 | 2838 / 473 | 6553 / 1539 | 3816 / 832 | 4150 / 574 |
| 最近推送 | 2026-10-18 | 2026-07-31 | 2024-10-23 | 2026-10-27 | 2023-10-17 |
| 最近发版 | 2024-04-18(1.13.1) | 以运行时包版本为准 | 以镜像 tag 为准 | 持续滚动 | — |
💡 技术拓展:这四个「能跑代码」的项目其实分属两类——执行引擎(Judge0、Piston)只提供「提交源码→拿结果」的 API;OJ 网站(OnlineJudge、HUSTOJ)自带题库/比赛/排名,判题只是内部模块。CodeBox 是 IDE,跑代码靠宿主环境,不构成判题服务。选型第一步是分清你要的是「引擎」还是「整站」。
7.2 关键差异解读
- 接口成熟度:Judge0 是四者中 API 语义最完整的(同步等待、批量、回调、状态码表、
/system_info容量观测),适合被其他系统集成;Piston 的 API 更简洁,同步为主。 - 隔离实现:Judge0 用 isolate(进程级),Piston 用 LXC(容器级),两者都需要宿主特权;容器级隔离在「语言环境隔离」上更彻底,进程级在启动开销上更优。
- 语言维护成本:Piston 把每种语言做成可安装的运行时包,升级语言版本最省事;Judge0 需要自己维护
languages表与执行节点运行时。 - 整站能力:需要「注册用户、出题、比赛、榜单」就直接选 OnlineJudge 或 HUSTOJ,用 Judge0 从零搭这些上层功能不划算。
- 许可差异:Judge0 是 GPL-3.0,对外分发二次开发版本有开源义务;Piston/OnlineJudge 是 MIT,商业集成更宽松。
7.3 选型建议
| 你的需求 | 建议 |
|---|---|
| 已有业务系统,只要「跑代码」能力 | Judge0(要回调/批量/容量观测)或 Piston(要更轻、MIT) |
| 要一个能直接开课的 OJ 网站 | QingdaoU OnlineJudge(现代化前端、Docker 部署)或 HUSTOJ(老牌、资料多) |
| 要在网页里写代码并运行(IDE 形态) | CodeBox 类 IDE + 后端接 Judge0/Piston,不要让 IDE 直接在宿主机执行 |
| 面向不可信公网多租户 | 任何单层 isolate/容器方案都不够,需外层 VM/gVisor 隔离 + 严格限流 |
八、参考链接
- Judge0 仓库:https://github.com/judge0/judge0
- Judge0 1.13.1 Release:https://github.com/judge0/judge0/releases/tag/v1.13.1
- Judge0 官方文档:https://ce.judge0.com
- Judge0 配置样例(
judge0.conf):https://github.com/judge0/judge0/blob/master/judge0.conf - isolate 文档:https://github.com/ioi/isolate
- Piston:https://github.com/engineer-man/piston
- QingdaoU OnlineJudge:https://github.com/QingdaoU/OnlineJudge
- HUSTOJ:https://github.com/zhblue/hustoj
- CodeBox:https://github.com/CodeboxIDE/codebox