论维护学校OJ有多生草(1)

我们学校的OJ系统是我们学校程序设计基础这门课期末考试的考试平台。我大概是大一的时候,被老师拉去看着它,从此我就与学校的这个系统结下了不解之缘。
简单记录一下我维护它都发生过啥事。

下面分享一下我自己的所见所闻所感。

这是个系列文章,想到哪儿更到哪儿
你会在这个系列文章里发现许多傻逼操作,求轻喷(逃

技术架构

我们之前的OJ系统部署在一台阿里云服务器上。由于它配置低,经常卡死,处理起来也比较难受,因此我们上一届毕业的学长在他的毕业论文里选择了这个课题,为我们学校开发了一个OJ系统。
这个系统总体看上去是基于开源的各个系统拼出来的。后端是学长用Python自己做的一部分。在我接手时只支持内网访问。我们学校校内没有公共wifi,光开发内网就有这些问题:

  1. 学生自己在宿舍里使用这套系统就很难,操作繁琐
  2. 老师上课时无法引导学生操作
  3. 即使是在连入内网的机房里,让自己带笔记本来上课的学生访问也困难

因此,有必要去实现一个外网访问的方式。
我们最终正在用一个自己改的frp,在学校实验室内开了一台服务器做frp,外网用了若干台带宽较大的腾讯云轻量来实现了外网访问。

新实验楼奇特的IP分配机制

这件事可以说是一场持久战,如果仔细说的话,那就要大说特说了。

注意:
以下内容是建立在我们学校奇特的网络环境之下发生的,我们学校的实验楼的网不能跟别人家的不一样。当然,我能这么干,多多少少其中也有我自己傻逼的成分。

第一战

学校今年正式投入使用了新实验楼。我们的机器搬进了新实验楼内。但是随即我们便遇到了IP分配的各种问题。我们的机器一开始老师没去申请固定IP,加上学校新实验楼的奇特的IP分配机制,把我看傻了。
学校的新实验楼,我们所在的楼自己拥有211.60.100.***这个段(这里只是为了说明问题,实际IP不是这个)。那么我们可以很轻易就能算出,我们这个楼其实只能分到不到256个IP(因为***的取值范围是0到255,实际上是不到256个的)
那么我们一个楼我粗略计算。假设一层楼有26个房间,每个房间有2台电脑。如果这个楼的人最近很忙,大家都来加班了,这就需要312个IP才能让大家都上网,更别说在这个楼里的实验室一个屋子可能有30台电脑了。
显然学校给一个楼分的IP太少,根本没法满足让整个楼都能上网。这直接导致了有的时候练老师办公室都没法正常上网。我们的服务器也显然并不能保证一直可以拿到我们需要的那个IP。

所以我是咋解决这个问题的呢?
那么机智的我就有了个很傻逼的想法。经过一定的实验发现这样好像真靠谱。究竟是什么方法呢?
直接抢!你不抢走,别人就会拿来用。

处理方式简单粗暴,我直接用了一台机器开了10台虚拟机,其中9台每个虚拟机都长期占用一个固定的IP,另外一台在上面跑了一个脚本在网段内一直扫能用的IP,发现了就直接创建一个虚拟网卡抢,除非这个抢到的IP已经30多个了差不多够了。
这些抢到的IP都放入一个IP池内,如果发现需要IP拿来用,那就从IP池里抽一个出来用,创建一个临时的反代,把frp的服务端和客户端对上。

这里我还设计了一个复仇机制,如果我从IP池里抽出来了一个IP拿来用,那我就要继续执行脚本,从可用的网段里寻找至少2个IP拿进IP池里。

那这样做成效如何?
在一开始这样做效果收效很好。巅峰时期IP池内一下子就能同时积攒62个IP,这样算来我们直接垄断了这栋楼将近25%的IP。

第二战

后来我发现这样做会使得我们能分配到的IP越来越少,IP池慢慢会枯竭。
经过实验,我意识到了一个问题:如果同一个MAC地址一直在吞IP,会让学校奇特的交换机做我完全不知道咋回事的一种限制,大概就不会让你一直这样吃IP了。

其实这个问题我早就想到了。这就是为啥要开10台虚拟机的原因。
我又改进了一下这个抢劫系统。这10台机器一开始就有不同的MAC地址,我闲着没事干的时候还会去重新换一个MAC地址玩。
在刚才的调配方案中,我们有9台是一直长期拿着一个IP,能拿就立刻拿过来,还有1台就是到处吃IP。现在我们拽一点,我们把到处吃的那台叫做吞噬者,把长期拿IP的那个叫守望者。

现在的新方案大致是,这10台机器轮班倒去当这个吞噬者,也就是今天你当,明天他当,后天我当。(这里吞噬者吞到的IP放入IP池中,创建虚拟网卡的任务还是吞噬者去干
然后,剩下9名守望者长期持有的IP将不会固定了,它们来自IP池,IP池先满足没拿到IP的守望者然后再做IP积累,守望者一拿到手就占着。

这还没完,守望者每1小时就会等概率随机做下面四件事其中的一件事:

  1. 摆烂:啥也不做
  2. 玩腻了:把自己的IP换给IP池,再从IP池里随机挑一个IP继续拿着
  3. 当懒狗:把自己的IP换给IP池,然后啥IP也不要了,让自己空载
  4. 喜新厌旧:如果发现IP池里IP有不少,那直接把这个IP扔掉了,换个新的

有个小细节:你还记得从IP池里拿出一个IP会启动IP池的复仇机制这件事吗?这可以有利保证如果倒霉情况下,如果大家大多数机器集体喜新厌旧不会导致IP缺乏,因为如果IP真的紧缺,扔出去的IP大概率会被吞噬者立即吃回来。

这样做的结果是,对于交换机而言,IP正在以一个它看不懂的方式来回在几个人手里一直丢来丢去,IP并不会由一个机器一直长期持有。
实测交换机就不会来封机器获取IP了。

第三战

这样过了一段时间安稳日子后,又来了一个神奇的事情:怎么服务突然会抽风一下,一直在切IP,服务还是访问不了。

这里不得不批评我自己写东西不喜欢写日志或者瞎写日志的坏毛病。
经过我的仔细分析(其实就是加上了日志仔细看了看),IP池有一段时间经常迅速枯竭,可能是这段时间里这个楼开机需要上网的设备变多了。

再加上这段时间我们实验室经常时不时停电跳闸。我们知道,这个实验楼里的规则就是弱肉强食的:IP如果在自己手里那就有话语权,在别人手里那就任人宰割,即使你现在拿着这个IP,一断电那就啥也不算了。

解决方法就是摆烂。停电我能咋办,我最多发个QQ或者微信跟老师骂一句。后面我找了个树莓派,跑脚本每天抢个IP用,防止断电。
(这里树莓派防断电的方法就是放在了另一个屋子里,把树莓派藏在了一个公共教室的交换机机柜里。不怕全楼断电,要是那样大家都没网用

第四战

后面突然有些机器来挑战我们机器的服务稳定性。它们经常会来抢我们机器用过的IP,然后就尬了,我们的反代切换不及时,可能会把服务解析到他抢走的IP开的网站上。

解决方法就是,首先这个延迟问题是个BUG,先修一下。然后我猜测这个人肯定是故意的。我直接找了他网站的几个REST API接口,比如几个简单的搜索和登录啥的接口。
然后又增设了一台虚拟机,让他在每次我们的IP丢了的时候去看那个IP的80端口是不是开了网站,如果开了就一直死里发POST打他。

没过多久他就不来抢了。非常好。
后面陆陆续续还遇到过几次这个情况,比如一个很集中的校内IP段来我这边网站一直刷一个API之类的,我们直接把他网段拉黑。这个时候由于我们的系统大家都在用,肯定有一些人会来反应我们的网站在哪里不能用,我们去看一下那里是个啥教学楼,看看是不是这个地方有实验室之类的地方,一般就可以锁定;如果没有就去教务系统上看课表,看看被打的时间段是哪些班在上课,也能轻松锁定。

这里可以细说一下被打了去教务系统爬课表的事情。一个问题:如果是内网打的,由于程序设计这门课实验课就在我们在的这个教学楼,跟我们是一个网段,这个抓起来很好抓,看看现在谁在上课就行了;我们还遇到了其他学院和友好学校来打的,这就不太好抓,爬课表的时候还得留意一下这门课是不是可以在机房上才能有可能锁定范围。

最终

最终我们老师申请了个固定IP,一切都结束了。

完结撒花!

有意思的是,有一次有个学长还来加我QQ问我,我们是如何实现的这个系统的网络部署,比如外网是咋部署的。有一说一,这个真的不是几句话就能说得清的。
回过头来,看我干了多少傻逼事,太生草了

上一篇
下一篇