在线代码评测服务架构的设想与设计

重新开了个系列,此文废弃。

https://www.lanrongqi.com/2020/07/online-judge-development-0/

0x00 背景

WeJudge 3.0 第一期工作已经基本上完成了,平台初步完成了题库模块、判题模块和教学系统(课程模块、作业模块)的开发并进入内测阶段。本文根据内测阶段系统工作情况的反馈,就判题模块反映出的问题,整理相关技术方案,讨论一套更加合适、高效的判题模块设计方案

0x01 判题

关于代码判题,WeJudge判题内核采用的方案为简单黑盒测试。原理是通过对目标程序输入特定的测试数据,获取运行结果并与预定数据进行比对匹配,从而判断程序的运行情况是否与题目期望一致。基于黑盒测试的代码评测模式在ACM-ICPC竞赛中最为常见,具有如下优点:

  1. 判题程序开发难度较低。
  2. 判题程序主要实现进程监控和数据直接比对,运行效率高,占用资源低。
  3. 测试数据易于构造和编辑,可以通过参考程序生成,方便出题者。
  4. 兼容多语言多平台(WeJudge暂时未实现对Windows平台的判题支持,应用户要求,后续会支持VC++)。

同时具有以下缺点:

  1. 测试数据均为静态数据,仅使用“运行结果”来判定代码正误。
  2. 无法进行代码分支预测,无法判定代码是否符合题目要求,无法检测暴力过题的情况。
  3. 系统设计初衷是面对编程初学者用户练习,黑盒测试不能直观反映代码存在一些问题,如:数组或变量未初始化、循环不能跳出和条件语句结构臃肿等等。

判题机的具体工作流程和改进方案等未来另有文章讨论,上述内容仅方便读者更好理解代码判题的大体原理。

0x02 现有技术方案

WeJudge服务端基于Python3.5下的Django2.0构建。由于判题必须异步于Web服务,使用Celery作为异步任务管理工具,并使用RabbitMQ管理异步队列。

当前WeJudge服务端和判题机的工作结构图

在实际运行过程中,发现了一些较为显著的问题:

  1. 由于评测机(Judge Client)和评测调度中转服务(Judge Service)采用socket连接方式,并且二者不在同一客户机中,如果出现网络异常或不可抗原因导致Service服务断开时,将会导致评测失败,判题反馈结果为System Error,需要等待评测机自动重启后才能正常执行判题任务,这在高并发下会引发长时间的队列等待和任务滞留。
  2. 扩展性差,需要手动启动container,未设计容器编排。
  3. service和client通讯依赖container连接上桥接网络,无法满足评测容器需要隔离网络的安全性需求(有考虑过iptables,但是新方案争取做到容器不依赖网络即可和service端进行通讯)

0x3 重新设计方案

作者正在准备考试,每晚写一点。未完待续…