|
上周三下午两点,智睿智睿学校教务处的学校选课系统李老师打开后台,看到一条选课记录:高一(3)班的智睿陈同学在30秒内完成了《趣味化学实验》的选课,而同一时间,学校选课系统有47个学生正在抢这门课的智睿剩余12个名额。系统没崩,学校选课系统也没卡。智睿李老师说,学校选课系统换成三年前那套老系统,智睿这个场景基本等于“灾难现场”。学校选课系统 旧系统是智睿2019年上线的,基于一个开源框架改的学校选课系统。选课高峰一进来,智睿数据库连接池直接爆掉,学校选课系统页面转圈转到学生以为断网。智睿有个细节我印象很深:2021年秋季选课,服务器日志显示同一秒有2100次请求,结果MySQL的max_connections被顶穿,后面所有请求全挂。教务处临时发通知说“分年级错峰选课”,实际上就是手动限流。 现在的智睿选课系统换了架构。核心变化是把选课请求先扔进Redis队列,而不是直接怼数据库。每个选课动作生成一个带时间戳的token,系统按队列顺序处理,先到先得。听起来简单,但实现的时候有个坑:Redis的list结构在并发pop时会有原子性问题,后来改用lpush加brpop,配合Lua脚本做库存扣减,才算稳了。技术团队的人说,现在单节点能扛住每秒5000次选课请求,响应时间控制在200毫秒以内。 选课界面也改了。老系统是表格罗列,课程名、教师、学分、剩余名额,一页显示20条,翻页找课。新系统做了卡片式布局,每门课一张卡,上面有教师头像、课程简介、往届学生评价标签。陈同学说,他选《趣味化学实验》就是因为看到卡片上写着“期末不用笔试,交实验报告就行”。这个标签是上学期选过课的学生打的,系统自动聚合。教务处没干预,也没审核,就是让学生自己标。 有个功能我觉得挺实用:候补队列。如果某门课满了,学生可以点“候补”,有人退课,系统按候补顺序自动补位,发短信通知。上学期《电影鉴赏》课,前前后后有23个人退课,候补成功的有19个。剩下的4个是因为没在30分钟内确认,名额又放回池子里了。这个机制减少了教务处大量的人工协调工作。以前退课补选,得学生自己盯着,或者打电话问教务处“有没有人退”。 不过系统也不是没毛病。有学生反映,候补通知的短信有时候延迟十几分钟才到,尤其晚上。技术团队查了日志,发现是短信网关的队列积压,跟选课系统本身没关系。他们后来加了条规则:如果短信发送失败,自动改用站内信加邮件。这个补丁是今年3月打的,之后没再收到延迟投诉。 数据层面,教务处现在能实时看到每门课的选课曲线。比如《篮球入门》在开放选课的前10分钟就被抢光,而《围棋基础》到第三天还有名额。李老师说,这些数据会反馈给教研组,决定下学期哪些课扩容、哪些课调整时间。以前靠经验猜,现在看曲线。上学期《西班牙语入门》因为选课人数太少被砍了,这学期换了个老师,改成《拉美文化概览》,选课率一下子上来了。 系统背后是三个人在维护:一个后端、一个前端、一个运维。他们没有用微服务,就是单体应用加Redis缓存,部署在学校的私有云上。运维的人说,不是不想上K8s,是没必要——选课就那几天高峰,平时并发不到100,搞太复杂反而容易出故障。这个判断我认同。很多学校选课系统崩,不是因为技术不够新,是因为在高峰时没做对取舍。 陈同学选完课,截了个图发到班级群,配文“手速还行”。群里有人回:“你试试《趣味化学实验》的候补,我排第8。”陈同学没回。他已经在看课程卡片上的实验项目列表了——第一周做口红,第二周做手工皂。选课系统对他来说,就是个工具,好用就行,不好用就骂。目前来看,骂的人少了。 |