HydroOJ部署指南
引言
废话不多说,我要毕业了,但是给学校部署的 OJ 需要有交接文档,本文目的就是概括本 OJ 部署的全流程以及部分技术细节,便于后人维护。
基础篇 1:基本系统安装
基本系统安装的话大致三个思路:1.一个基本系统+虚拟机/2.一个基本系统上直接跑/3.虚拟化容器(ESXi,PXE 等)。但是根据我个人的经验以及客观状态,前者是比较合适的,原因有二:1.我希望我的基本系统本身能够处理一部分高并发业务,故能排除 3;2.我希望能够便于无人值守时仍然能够对系统拥有全部的控制权,从而排除 2(这个是由惨痛经验证明,本人之前部署了一个 Minecraft 服务器,然后端在一次 Unexpected 的终止后就变成了一个占用 20GB 的 zombie 进程,极大拖慢了系统速度,最终导致死机/Kernel Panic,导致无法线上进行继续维护。而虚拟机方式,由于虚拟机本身的隔离机制以及 watchdog 机制,如果出现了死机或者 Kernel Panic,可以在宿主机中进行强制重启,从而最快恢复服务。而宿主机本身使用系统较为稳定,基本不太会崩溃。同时,这样的机制允许我虚拟机使用较新的软件)
基本系统选择的话有三种选择:Microsoft Windows,Linux,其它 UNIX 系统。Windows 由于其虚拟化服务性能不加,部署不便,且有一个我并不需要的 GUI,首先排除。其它 UNIX 系统(如 Oracle Solaris,OpenIndiana,FreeBSD)等,其教程较少,也不考虑。于是唯一的选择就是 Linux。而在 Linux 选择上,我首先排除的是最热门的 Ubuntu,无他,我之前使用 Ubuntu Desktop20.04,动不动内存泄露死机,我对它的稳定性表示怀疑;另外,我对 Canonical 强推 snap 的政策表示非常不满,该公司的其它行为也很让人不得不怀疑其专业性。然后我曾经很长一段时间使用了 Debian,因为其较为稳定的更新速度,以及系统本身很小,消耗资源极低;但是实际应用当中,其驱动支持完整度不够,而且还是太新,较容易 Kernel Panic,最终放弃。于是我转向了红帽系系统,CentOS 被 Red Hat 收回用作中端,Rocky 之类的太分散,没有原来 CentOS 的支持度了;同时,由于红帽开发者计划允许个人开发者在 15 个节点内使用其 Red Hat Enterprise Linux 服务,所以我选择了文档支持较好的 RHEL。
其开发人员计划细节以及系统安装此处略过,值得注意的是,建议给系统分配 20GB+的 Swap 空间,基本系统用默认的 xfs 即可,如果对安全性等有要求的,可以局部使用 ext4。不建议在实际的任何需要有稳定性安全性的服务上使用 btrfs 或 zfs 之类文件系统,这些文件系统本身实现太过复杂,出现问题很难找到数据恢复人员。
基础篇 2:虚拟机安装
RHEL 默认可以使用他的网络控制面板 Cockpit。但是需要注意,必须要安装上cockpit-machine包才能对虚拟机进行管理,这个简单:
$ sudo dnf install cockpit-machine接着从清华源上下载虚拟机使用的镜像,按照官方教程的建议,我选择了Debian12
Debian 的安装较为无脑,此处略过不提。安装好系统后,将基本的工具安装上,并且将自己的用户改为管理员:
# usermod -aG sudo xxx
# apt install openssh-server基础篇 3:Hydro 安装
Hydro 默认自带反代工具 Caddy,但是由于个人常年使用 NginX,而且最后其实也没用到 NginX,所以我们不需要安装 Caddy。
在虚拟机中直接执行官方的安装指令即可:
$ LANG=zh . <(curl https://hydro.ac/setup.sh) --no-caddy安装后,重启,Hydro 安装就完毕了。
基础篇 4:反代部署
刚刚你部署的 OJ,由于是部署在虚拟机内网的,无法通过外部直接访问,所以要配置反代。我使用的反代服务是FRP,配置较为方便。
在你的服务器/usr/local/frp/(如果没有新建一个)下存放 frps 文件,并且在虚拟机的/usr/local/frp/下存放 frpc 和 frpc.toml,frpc.toml 中按照如下格式填写:
serverAddr = "192.168.122.1"
serverPort = 7000
[[proxies]]
name = "HydroOJ"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8888
remotePort = 8888然后在宿主机中打开防火墙:
$ sudo firewall-cmd --zone=libvirt --add-port=7000/tcp --permanent
$ sudo firewall-cmd --zone=public --add-port=8888/tcp --permanent
$ sudo firewall-cmd --reload接着运行 frpc:frpc -c frpc.toml,你就能从外部访问 OJ 了。
为了方便,建议配置成服务:
待补
基础部分:终章
接着,注册一个账户,然后设置为 Super User:
$ hydrooj cli user setSuperAdmin 2然后你可以加入官方用户群,下载一些基本题库,并且导入 OJ。
注意:有部分题目是远端评测题,使用方法见压缩包内说明。
然后你就能够愉快的享受你的 OJ 了。
提高篇 1:简单廉价的公网服务
公网服务有很多种方案,不过都是内网穿透方案,依速度有两个方案:NATAPP(快),Cloudflare Zero Trust(慢)。但是我选择了后面这个方案,原因有多个:1.公网上怕被 DDoS,Cloudflare 的 CDN 很完备,且使用了 Onion 路由,无法被轻易溯源,是在不用过度操心网络安全的情况下一种较为切实可行的方案。2.后者只需要一个域名就能够使用,价格很低(一个域名(非 com 等常用域名)购买大概 50 块钱 3 年,续订 20 一年)。3.Cloudflare 默认会代你签发 Google Trust Service 证书,可以实现从源到客户端的完全端到端加密,避免被篡改或窃听。
提高篇 2:每日快照与异地容灾
提高篇 3:HydroOJ 评测集群
终极篇 1:HydroOJ 集群
前言
该篇内容与提高篇 3 不同,提高篇 3 只是评测集群,可以使用多台机器同时进行测评,自动负载均衡,在高峰时段分担服务器压力。本篇内容可以允许你在两个服务器上分别部署独立的 HydroOJ,并且共享所有评测数据,图片等内容。可以允许在任何一个机房停电后在最快的内立刻启用 backup 并且开启备用服务,避免出现长时间的服务不可用。
数据库共享
对象数据共享
终极篇 2:实时异地容灾
前言
该篇内容与提高篇 2 不同,提高篇 2 是单纯的 rsync 快照,只能保证 24 小时内的数据保留,如果在紧急状态下启用了 backup,那么当天的大量数据就会丢失,这是不可接受的。本篇和终极篇 1 亦不同,终极篇 1 仍然是启用 backup 的方式,问题如前所述。因此我们希望数据库和对象数据都能实时同步,两个节点互相同步但互不统属,任何一个节点崩溃对另外一个不会产生任何影响,能够独立提供服务。