SYZOJ 实现分布式评测
这篇博客的起因是学校的OJ因为高考被切断了, 但是我的公网OJ是个实现很不清真的UOJ而且上面只有1core和1GB内存. 费了一些周折部署好syzoj之后大家喜闻乐见地被卡常/卡内存了...于是需要分布式评测来将评测任务分流给新租的性能优秀一些的服务器.
然而由于现在开发组被鸽子占据所以分布式评测的wiki咕咕咕了...
自己xjb搞了搞现在实现了分布式评测(网站端和评测姬不在同一台服务器)
于是在这里记录一下方便自己以后复现, 以及希望能在一定程度上帮到想部署syzoj的大家.
SYZOJ的消息机制
这部分是问了Menci才知道的...
目前SYZOJ的结构是长这样的: web端分配评测任务给评测姬的judge-daemon, judge-daemon再把运行任务分配到各个judge-runner.
整个系统的通信是: web端内部使用本机的Redis通讯, web端到judge-daemon使用SocketIO通过HTTP(?)实现, judge-daemon和judge-runner之间的通讯是用Redis+RabbitMQ实现的.
但是web端到judge-daemon之间的通讯并不会传递测试数据. 也就是说测试数据必须在web端server和judge-daemon所在的server上同时存在且同步.
实际实现
通讯部分
根据上面的机制描述, 我们可以发现实际上只要解决web端到judge-daemon之间的通讯就可以实现分布式评测. 也就是更改 config/daemon.json
中的 ServerUrl
项为web端的URL即可. 如果有nginx反向代理的话可能需要填写域名而非IP.
所以按照Wiki安装好judger基本就完事了.
以为redis也需要和web server共享的我折腾了一段时间的外部访问redis...最后在amqp的时候自闭询问了一下Menci发现消息机制并不需要共享
测试数据的同步
因为SocketIO并不管测试数据, 我们需要自行同步 data/testdata
下的所有文件. 个人使用的策略是使用 inotify+rsync
做到实时差量同步. (用NFS没准也可以?)
inotify
是一个内核接口, 内核会在指定文件被进行指定操作后对程序发出信号.
然后剩下的工作网上有同步教程(
大致流程是在judger那头开个 rsync --daemon
, 然后在web这头写个脚本同步.
注意各种各样的token问题就好了