教务系统是一个使用规律性特别强的应用系统,常见的系统负载高峰出现在学生集中选课等短时间的高并发情境中。笔者面对的这一教务系统应用3年来,还会在学期末教师录入学生考试成绩期间出现较高的负载,这一现象由于过去一直存在,因此并未引起注意。然而,时间到了这一学期末,整个系统从C/S到B/S都出现了严重的反映迟缓,尤其C/S客户端,平时一个1秒左右就能显示的操作结果或菜单,需要五秒甚至十多秒才能显示,这一异常极大的挑战了使用者耐心的极限和信息化管理的效率,不得不立即采取应对措施来缓解持续的高负载带来的系统使用困境。
1.按图索骥的寻因
该系统独立配置一台sun v890小型机作为oracle数据库,另有4台物理服务器运用虚拟化技术配置为7个web服务。首先查看cacti上监控信息,7个web的cpu使用率、网络流量、内存等情况都很正常,处于较低的水平;而solaris上cpu usage在白天较多时间处于40%上下,尤其用户使用率非常高,每天内存消耗的变化幅度在也很大,如图1所示。
 

图1  数据库所在小型机的负载监控
从监控很明显看出,整个系统的缓慢是被数据库拖累了。登录solaris查看,cpu idle比率基本持续达到一半,在队列中等待的进程数r比较多,每秒的环境切换次数cs和用户进程使用的时间us都比较大,如图2所示。
 

图2  系统异常期间solaris系统负载状况
虽然有预计的数据录入可能产生的负载,但结合cpu usage图来看,似乎白天持续的cpu高使用率并不符合规律,因为成绩录入是分布的,不会产生如此均匀的使用率保持在40%,即使有数个教师同时保存成绩操作产生并发,cpu使用率应该是不均匀的起伏。我继续统计了实例上当前的会话数,达到470多,与选课时间较低的会话数相当,而平时会话数一般只在110-140之间波动,现在的情况于我对系统的了解是不正常的。为进一步了解数据库工作状况,立即用oracle自带AWR(Automatic Workload Repository)工具分析当天下午2点至4点的负载信息。
分析显示,最高的5个等待事件分别是log file sync、enq: CI – contention、enq: RO - fast object reuse、latch: library cache和buffer busy waits。综合前三个等待事件,应该属于写进程开销较大的争用和等待,后面二个事件则是共享池中争用的等待,说明存在大量的sql被反复分析,并且有数据块在被二个或多个会话争抢读取到内存中使用或修改。可是现阶段成绩录入,假设有多个同时保存成绩的操作,在sql方面应该主要是insert和select语句,虽然成绩表已经有300多万条记录,从执行计划上看全表查询需要10000多cpu cost,但实际中不可能如此巧合有这么多老师有序的在白天进行录入操作,所以cpu usage呈现的较为平整的40%使用率一定有其他方面的原因。
2.顺藤摸瓜的意外发现
想起该系统还有一张表记录了B/S登录情况的日志表,遂分组统计了同上述分析时间一致的日志记录,学生登录系统的人数是967,教师登录系统的人数是148,学生登录情况竟然是教师登录数的6.5倍,从这个数据上看,教师登录的并不多,如果把148个登录平均在120分钟内,负载应该很小,但另一方面,我奇怪于有这么多学生登录,是做什么呢?
为解释学生登录数较高的疑问,我对7个web的iis日志进行了抽取,在笼统的查看每个日志记录的情况后,明显发现有很多成绩查询页面的记录,遂统计了上述2个小时内学生登录后主界面,教师登陆后主界面,学生查成绩页面,教师录成绩4个网页的使用次数,结果令人大吃一惊,学生登录的主界面引用5347次,教师登录主界面引用480次,而学生成绩查询页面引用高达16166次,教师录入成绩页面引用仅384次(Iis上记录和rzb上的差异,在于rzb只记录正常登录行为一次,未退出前,只记录一次,未登录的不记录,而iis日志则每相应一次页面刷新都会记录一次),学生和教师登录次数的悬殊,基本上可以肯定负载的异常不是连续录入成绩的结果,相反,是学生反复查询成绩的结果。如果做个不尽科学的算术平均,学生成绩查询的页面在每秒钟都有2.25次,在这个300多万条记录的成绩表中,成绩记录的存储是分散的,根据学年、学期、学号等条件做执行计划查询,都要消耗100cpu cost,一秒内多个并发查询,则需要在这么多记录的表中不停的做分散读和锁操作,虽然1秒钟对于高性能的小型机是个较长的处理时间周期,对于一个需要消耗2,3秒才返回结果的查询操作可能并不算太久,但这几秒内又有持续的查询在不断产生,热块争用也就显现出来,故而cpu消耗持续,查找造成的锁也持续保持,等待队列形成了,这一情况也使awr分析的top事件有了合理解释。另一方面,为数不多的成绩录入在查询量大时,也会造成锁和数据块争用,从而进一步使得整个数据库保持了较多的cpu消耗和等待,在客户端使用时感受到无法忍受的缓慢也就不足为奇了。
3.勿以恶小而放任之
虽然找到了罪魁祸首,也对数据库负载的异常有了合理解释,但还不得不提另外的隐情。关于学生查询成绩的页面,其实是我们已知的一个问题页面,该页面存在验证漏洞,学生能够在不登陆系统时,直接打开该页面并附带学号参数进行查询,形如http://jwxt.domain/xscjcx.aspx?xh=11071025,不仅可以输入自己的学号进行查询操作,还能随意输入其他人学号进行越权查询。如此一来,虽然正常登陆系统选择成绩查询的菜单因为系统控制开关设定而关闭,但“自助式”直接查询却更方便了。
我依次在每台服务器上将学生成绩查询页面进行重命名,随后观察cacti上监控信息,数据库cpu负载立即垂直下降,最终稳定在3%左右的低位,如图3所示。此时,整个系统的响应速度随即也开始变得灵敏,不过有意思的是,每个web的cpu使用率有了5%的小幅上升,我猜想应该是学生继续请求已经不存在的页面而造成的。继续观察2天,数据库负载都平稳正常,系统也运转流畅。
 

图3  重命名学生成绩查询页面后,数据库负载迅速降低
还有一个小疑问,有多少学生在用此方法进行查询?我在google和baidu中输入了学生成绩查询的页面文件名,大量的关于此漏洞的成绩查询方法帖子赫然在目,其中不少本校的链接排列在前,我顿时恍然,原来大部分学生都知道。大家可能觉得好笑,只是个小小验证漏洞,尤其还是个已知的漏洞,竟然造成了这么大的负面影响,虽然各中缘由一言难尽,但对已知漏洞的放任却也难辞其咎。
对漏洞的管理,我们可能早已麻痹于windows系统频繁的补丁升级中,除了冲击波那样令人记忆深刻的漏洞事件,平日里对补丁和更新的概念可能更多的是漠然。对应用系统的漏洞,只要不是影响系统功能,不发生篡改等严重的安全事件,往往也不会引起系统管理员的重视。因此,我们缺乏的是认真和严谨的管理态度,即使存在程序维护方面的困境,技术仍然可以不同的路径避免漏洞带来的潜在影响,尤其对于已知的漏洞,更要毫不手软,不报侥幸心理,管理才能落到实处,安全才能有保障。

文章如转载,请注明转载自:http://www.5iadmin.com/post/977.html