山东大学-创新实训-智评Code+:基于DeepSeek的AI代码纠错与优化评测平台-(3)评测机与缓存队列

评测架构设计:队列 + Worker Pool + Docker 沙箱

在开发智评 Code+ 的过程中,实现一个稳定、高效、可扩展的评测系统是核心挑战之一。这一节我想记录一下「评测机调度系统」的整体架构设计与实现思路。

问题背景:评测任务不可阻塞主线程

用户提交代码后,我们需要:

  1. 运行用户代码,对每组测试数据进行评测;

  2. 返回准确的运行结果、错误信息、输出对比等;

  3. 保证整个过程不影响主流程,支持高并发提交。

因此,最自然的架构选择就是将评测任务异步处理,即:

  • 主线程负责接收提交、写入数据库;

  • 后台 Worker 拉取任务并独立完成评测。

技术架构概览

我采用的结构如下:

用户提交代码 --> HTTP API
              |
              V
         Redis 消息队列
              |
              V
         Worker Pool (多线程评测机)
              |
              V
     使用 Docker 安全评测代码
              |
              V
   回写数据库 + 存储每组测试结果


Step 1: 提交代码后入队

用户提交代码后,我们调用 EnqueueSubmission,将提交记录 JSON 化后写入 Redis 队列中:

func EnqueueSubmission(sub models.Submission) {
	data, _ := json.Marshal(sub)
	utils.RDB.LPush(ctx, "judge_queue", data)
}

这一步非常快,基本没有阻塞,因此可以立即返回前端一个“提交成功”的响应。


Step 2: 启动 Worker Pool 出队并评测

我设计了一个 StartJudgeWorkerPool(n int) 方法启动多个 Worker,每个 Worker 会不断地:

  • 从 Redis 中阻塞式读取评测任务;

  • 执行代码评测;

  • 更新数据库结果。

res, err := utils.RDB.BRPop(ctx, 0*time.Second, redisQueueKey).Result()
EvaluateCode(sub.Code, sub.Language, sub.ProblemID)

这使得评测系统具备横向扩展能力:只需要增加 Worker 数量即可提升吞吐量。


Step 3: 代码运行环境封装在 Docker 中

用户代码的执行是潜在的高风险行为,因此我使用 Docker 隔离用户环境。每个评测任务会动态执行如下命令:

docker run --rm -v code_path:/app/code deepjudge-runner cpp /app/code "1 2 3"

这样不仅保证了安全性,还可以将运行环境标准化(如依赖版本、超时限制等)。


Step 4: 回写评测结果 + 测试点记录

评测完成后,会:

  • 将总评测结果(Accepted/Wrong Answer等)写入 submissions 表;

  • 为每个测试点写入对应的 testcase_results 记录;

  • 包含运行结果、预期结果、状态、耗时等内容。

utils.DB.Model(&models.Submission{}).
	Where("id = ?", sub.ID).
	Updates(map[string]interface{}{...})

utils.DB.Create(&models.TestcaseResult{...})

这样用户不仅可以看到整体状态,还能逐个查看测试点通过情况。


总结:为什么使用这个架构?

技术组件

作用

Redis

解耦提交逻辑和评测逻辑,实现异步消息队列

Worker Pool

支持并发评测,提高评测吞吐量

Docker

隔离用户代码执行环境,保障系统安全

数据库记录

实现完整的评测结果追踪和用户查询接口

这套系统目前在我的开发机器上已经可以稳定运行,后续如果部署到线上,我会考虑添加 超时任务回收机制、失败重试机制、任务状态监控面板 等功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值