判题服务器开发

判题服务器非常的简单,几乎无需做任何修改。采用TCP技术来通知判题机。

架构详解

测评模块仅提供了安全稳定的程序运行稳定,但是并不能判断程序是否通过,因此还要自己完成许多的逻辑工作。本系统的测评模块分为两部分,一部分是测评服务器,负责分发测评任务,另一部分是测评机,负责运行程序和提交测评结果。程序在运行过程中难免会消耗系统资源,如果只有一个判题程序在判题,如果判题时间较长,会导致后面的题目无法得到及时的反馈,但是如果太多判题程序同时运行,会导致系统资源消耗过大,导致前端和后台系统可能无法正确运行,所以要设计一个能够在多个机器上运行的判题程序,实现均衡负载功能,因此本OJ测评模块示意图如下:

测评模块示意图

利用了数据库的事务管理,可使得高并发得以实现。用户相当于生产者,不断地向数据库提交待测评列表,测评服务器相当于一个消费者,不断的从数据库中获取未判提交列表,然后将这些题目分发到准备就绪的判题机,判题机收到判题任务后会进入忙状态,此时判题服务器不再向该判题机发送判题任务。当判题机判题完毕,会告诉服务器,可以继续判题。服务器再将该判题机纳入空闲列表。这样我们就能实现多个判题机同时运行,且这些判题机可以在任意的机器上运行,只需要通过TCP协议,链接到服务器上即可。同时服务器被设计成多线程的形式,在通过资源锁去控制并发的资源访问,使得多个判题程序能同时判题。 测评服务器,测评服务器使用Python开发,运行时会循环监听9906端口,一旦有测评机连上服务器,会新建一个线程,专门处理该测评机的消息。该线程首先会向测评机发送getstatus信息,测评机收到消息后会向服务器发送ok信号,代表已准备好判题。此时服务器会将该测评机纳入空闲列表。然后不断地循环发送getstatus信号,如果是not ok,代表非空闲状态,会将该测评机纳入非空闲列表。同时会有一个线程专门负责向数据库获取未判题列表,然后将未判题发放给空闲的判题机进行判题。

额外功能

由于历史原因和出于安全性的考虑,需要通过额外的程序来实现将比赛中的题目的权限设置为可访问,即将比赛中的题目访问权限设置为私密,这里将这个功能集成到了判题服务器的代码里。实际上这一部分可以独立出来运行。

源码解析

大概原理是这样的,这个判题服务器充当一个网关的功能,由他来拉取需要判题的列表,然后发送给各个服务器。这个判题服务器直接跟数据库进行通讯(直接把数据库当做中间件来用,比较方便)。用轮训的方式,不断地从数据库获取未判题列表,然后发送给各个判题机。当有判题机连入时,自动起一个线程来处理判题机的消息。判题机会不断地发送心跳包给判题服务器。

我真的写不动注释了!!!

main.py

HDUVjudge.py