[关闭]
@ruanxingzhi 2017-05-17T23:37:07.000000Z 字数 1168 阅读 1163

OJ技术思考:服务鸡与评测鸡

我是rxz,我又回来了。
我准备写一个OJ玩玩……撕烤一下各种细节。

架构

整个OJ分成两块,web(服务鸡)和judger(评测鸡)。

用下面的这种方式把它们连接起来:

  1. [Web] 收到评测请求
  2. [Web] 找一只空闲的评测鸡,把任务发过去
  3. [Judger] 收到任务
  4. [Judger] 评测一番
  5. [Judger] 返回评测结果
  6. [Web] 收回评测结果

然后到底怎么实现“发任务”“返回评测结果”呢?本来准备用消息队列,但是感觉太麻烦了,于是用一个比较蛋疼的方式:HTTP API(捂脸)

就是说,服务鸡收到评测任务后,访问http://Judger/judge.php,把选手程序和题号用POST的形式发过去;评测鸡测完之后,访问http://Web/back.php,告诉服务鸡这份代码的评测结果。

好暴力啊……(捂脸)

Web发给Judger的数据应该是这样的:

  1. {
  2. id : 2333333, # 程序编号
  3. problem : 1234, # 题号
  4. code : "#include</dev/random>" # 选手程序
  5. }

但是这里就有一个安全问题。如果一个选手,提交代码之后立刻访问http://Web/back.php,然后假装自己是评测鸡,扬言他已经A题了,那服务鸡就会以为这人A题了。

这怎么办办啊?解决也很容易。我们给每个评测鸡分配一个口令,评测鸡返回评测结果的时候说一下口令,服务鸡就能知道评测鸡是不是假的了。当然,这个口令需要保密。

于是,Judger发给Web的数据应该是这样的:

  1. {
  2. id : 2333333, # 程序编号
  3. name : "HongKong_Reporter", # 评测鸡名称
  4. token : "dd9e36156587f472f876", # 认证
  5. result : "AAAAAWWWWT", # 评测结果
  6. time : "2333", # 用时(ms)
  7. memory : "233333" # 空间(KB)
  8. }

另外为了提高安全性,外网应该不能访问评测鸡。顺便也可以做一下服务鸡的验证,防止内网的黑恶势力冒充服务鸡给评测鸡发一大堆评测任务。

可能你会问了,为什么不让评测鸡连接上数据库,然后直接往数据库里面写东西?这样就不需要用HTTP API来实现通讯了。

但是这个办法有一个不好:安全性。如果评测鸡不幸被人渗透,那么黑恶势力就可以随意修改数据库(至少是记载评测情况的那个数据库),这样就能篡改之前的评测记录。另外,数据库是不推荐允许localhost以外的机器访问的。

HTTP API实现的评测鸡还有一个好。在正常的OJ里,一个服务鸡可以对应多个评测鸡,但是一个评测鸡只能为一个服务鸡服务。然而现在,我们可以用一个评测鸡来对付很多个服务鸡,相当于评测资源共享了。

虽然这件事也能用直接改数据库的办法实现,但是比HTTP API要麻烦一些。

服务鸡与评测鸡的通讯就谈到这里。下一篇我们谈谈OJ的文件结构吧。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注