李晓宁 张浩
摘 要:本文以当前全国各省普通高考网上填报系统因并发量过高而极易造成网站的瘫痪的现象着手,设计了普通高校招生网上填报志愿系统的高并发负载解决方案。本系统在尽可能的采用传统的网站高并发负载优化策略的同时,还针对系统本身的特点从宏观架构及微观技术实现手段上都加以研究分析,制定针对网上填报志愿系统的高负载解决方案。宏观上本系统利用了面向服务的程序设计方式将系统分为网站程序层、数据缓存层、数据库层的三层进行设计,实现了系统中应用程序、数据操作、数据存储上的物理及逻辑分离,因此系统应对高并发负载具有了分布式解决能力,实现了系统的可扩展性。微观上,本系统利用了目前许多提高系统性能的新技术新方法,使网站程序运行具有了高效性。本系统的有以下几个特点及创新:(1)架设数据缓存库服务器,建立完善的内存数据缓存管理机制,利用面向服务的技术进行网站程序和数据缓存之间的通讯。(2)WEB程序与数据库隔离,增加系统的安全性。(3)软件程序负载均衡与硬件负载均衡结合应对大并发访问。(4)WEB服务器设置内存字典,使用哈希表进行数据映射,解决频繁数据查询。(5)网站程序层、数据缓存层、数据库层的分层结构设计,方便系统扩展。通过测试和实践证明,使用多种方法对WEB程序进行优化设计及把内存数据库作为向数据库中写入数据前的缓冲的思路,能很好的增加网上填报志愿系统一类的大数据量的网上应用程序的吞吐能力,从而完成高并发负载的网上填报志愿需求。
关键词:高并发 负载 WCF 内存数据库 优化
中图分类号:TP319 文献标识码:A 文章编号:1672-3791(2013)03(c)-0043-05
随着近年来教育部对“阳光工程”的施行和“平行志愿投档”的推广,加强了我国高校招生的公平性和透明性。其中“填报志愿”是考生选择大学的方式,决定着考生一生的发展道路,因此确保志愿信息采集的公平性、及时性、准确性、安全性也成为了各级招生部门工作的重要环节。目前招生部门采用的高考志愿信息采集主要有两种方式:一是的传统的涂卡方式,招生部门发放给考生志愿信息采集卡,由考生根据学校和专业代码填图志愿后,统一利用光标阅读机(OMR)进行读卡;二是开发网上填报志愿系统(以下简称网报系统)利用网页进行志愿信息采集。网上填报志愿针对过去的录卡报志愿网报系统有以下几个方面的优势。
(1)直观、高效。
考生通过通过互联网登录网报系统。考生可以在下拉菜单中做出选择,填入学校和专业代码即可。部分操作熟练的考生十分钟之内就可以完成志愿填报。
(2)简化流程。
采用读卡填报志愿方式流程是让每位考生向老师索取志愿卡后填涂信息,再到招生办读出志愿信息,回来后考生改错,再由招办工作人员重新改正,然后考生确认信息,这些环节不能有半点差错。网上报志愿简化了这些流程,考生可以在任何接入互联网的电脑上填报志愿并在网上确认。
(3)错误率减少。
通过涂卡的方式报志愿时,考生先查找好报考的院校及专业代码,然后根据代码的数字在信息卡上相应的代表位置涂黑,由于填涂过程不能直观的反应出所填报的院校及专业,所以很容易因涂错位置而发生填报错误。通过网上报志愿考生所录入的院校及专业的代码可以及时的进行翻译和校验,大大减少了填报错误的发生。
采用网上填报志愿是发展必然趋势,也是互联网高速发展及计算机普及的产物。随着部分省份对网上填报志愿的率先尝试并取得较好的社会反响,网上填报志愿已成为考生志愿信息采集的最好方法。同时,进行网上填报志愿的省份也都面临着一个严峻的问题:由于考生人数多,并且访问时间集中同时单个考生修改及查询频率又高,极高的瞬时并发操作请求致使系统和数据库超负荷运行,系统不能及时响应访问请求,旧的请求还未处理完,新的访问请求又到来,从而导致服务器处于假死状态。一旦进入假死状态,用户的操作就会得不到响应,页面长时间打不开会延误考生填报志愿,造成不良的社会影响,甚至致使考生不能完成填报志愿造成重大责任事故。
如何有效的对系统进行高并发负载已成为网报系统的瓶颈和使用上的软肋,也制约了网上填报志愿在全国范围内的推广,目前各省教育考试部门都在针对这一问题进行积极的探索。我们就对这一问题在Asp.net平台上提出解决方案:根据木桶原理,要想提高系统的整体能力就需要找到系统的瓶颈加以解决。我们首先分析了整个系统的结构,由于网报系统需要响应大量的考生访问,并且每个考生的访问都要进行大量的数据查询存取操作,因此网站不同功能之间的处理能力和速度上的差别也就成为了系统存在的瓶颈。本着为处理压力较大的模块增加扩展,为处理速度较慢的模块设计缓冲这一理念,我们对系统中的应用程序、数据操作和数据存储这三大应用功能进行了分层设计,将系统分为网站程序层、缓存数据库层和数据库层。网站程序处理压力大,该层要进行可扩展性设计;数据库层存在速度较慢,该层要由数据缓存层进行缓冲设计,(如图1)所示。下面分别对各层的设计进行分析。
1 网站程序层
该层使用最新的ASP.NET技术进行开发,部署在WEB服务器上。肩负着同考生进行交互,实现志愿填报业务逻辑;完成志愿代码翻译查询,通过WCF服务从数据缓存层中读取数据。由于该层的负载压力大,因此需要很好的横向扩展设计。
(1)负载均衡。
同时由于程序的主要负载都集中在网站程序上,为了应对大并发的负载,我们把网站程序在每台WEB服务器上都设计为独立运行,采用F5负载均衡设备为用户访问提供20分钟的会话保持。这样就为程序提高了良好的横向扩展性和可靠性,如果WEB服务出现负載饱和时,只需添加服务器即可实现负载分流,(如图2)所示。
(2)内存数据字典。
在填报志愿过程中查询最频繁的就是计划表,计划库表放着招生院校的层次、批次和其专业的科类、计划性质等信息,总记录数为3万条左右。通过计划表查询将考生填写的院校编码和专业编码翻译成院校名称和专业名称,并判断考生是否将院校代码和专业填错并提醒考生不要误报达不到要求的专业浪费报考机会,因此计划表能否正确、高效、快速的查询对网报系统能否正常运行起着至关重要的作用。以某省50万考生来计算,对计划表的查询量达十一亿次,显然在集中的时间段内应对如此大量的查询请求数据库已经很难负载。内存数据字典,是将计划表在程序首次运行时加载到每台WEB服务器内存中,可供程序直接在内存中访问的数据集合。通过测试内存的读取速度为18000多M/S,写入速度在15000左右(HP GX580服务器),而现在最好的固态硬盘读取速度也就能到400多M/S,相对于磁盘内存的数据读写速度要高出几个数量级。所以从内存中读取数据相比从磁盘上读取能够极大地减少查询时间提高应用的性。
2 数据缓存层
在填报志愿过程中,按50万考生每个考生可以填报8个批次,每个批次可以填报5所院校,其中1秒中有1000个考生在操作志愿数据的情况下计算,就要满足1秒钟内在两千多万记录中进行四万次数据修改操作的需求。面对苛刻的高并发负载需求,传统数据库很难实现。要完成如果高速的操作,IO速度极高的内存将会是最合适的场所,所以需要自行开发内存数据库作为数据缓存层来实现这一需求。该层是整个网报系统的数据处理中心,部署在专门设立的缓存服务器上。数据缓存层运行有一套完成的数据维护机制。实现增、删、查、改的数据操作;实现监听、应答的通讯机制;实现数据备份和回复功能。作为网站程序层和数据库层的速度差异缓冲,该层也就成为了系统中数据操作、交互的核心。
构建内存数据缓存层后,我们对内存数据库和SQLSERVER数据库进行了2万次数据读写效率对比测试,如图3所示。
设计时我们需要考虑以下几个方面。
(1)数据操作模式。
作为内存数据库和前面的内存字典不一样,不仅仅要完成对数据的查询请求,还要完成对数据的增加、删除、修改的操作。
(2)通讯机制。
如果没有通讯内存数据库就是聋子和哑巴,对外是发挥不了任何作用的,因此在内存数据库中还要建立对请求的监听和应答机制。
(3)数据备份。
内存作为高速暂时存储器,其数据在断电后会立刻丢失,因此要将内存中的数据写入到数据库中并妥善存储在硬盘上才能确保数据不会丢失。
我们将上述功能通过数据缓存、通讯、调度三个模块来实现,这些模块的分工如下。
(1)数据缓存模块。
该模块负责在内存中存放数据,并在运行期间维护数据的完整性;数据缓存层初始化运行时从数据库中加载数据并建立索引;提供数据查询接口函数;定时将改动的数据以xml文件保存到硬盘上供调度程序写入数据库。该模块是内存数据库的实现基础,由于这些功是在内存中实现,需要考虑以下几个方面。
①数据占用空间。
在志愿表中一条考生志愿信息经计算形成数据对象存储后每条记录的大小为1K左右。按50万考生每个考生填报8个批次,每批报5所院校计算,内存数据库中所存储的数据最大容量为22400000×1K,即22.4GB。加上windows2008和WCF服务需要占用的2~3G内存空间,我们需求的最低内存容量为26GB。
②数据安全。
内存作为暂存器,断电后造成数据丢失,针对该问题我们采用了定时增量日志备份来完成,即内存数据库每隔1秒钟(这个时间间隔可以任意设置)会将每次对数据进行的修改操作以XML格式存储为操作日志文件。如果发生断电事故,最多会丟失1秒钟内未及时保存到磁盘的操作日志,因此可以将事故影响控制在可控范围之内。
③存放形式。
内存中数据存放的方式有很多种选择,如数组、链表、队列、哈希表、字典等。通过对数据操作的分析,缓存服务形式就是以最快的速度响应网站程序层的读写请求,所以最重要的因素就是从海量数据中定位单条数据的速度,因此哈希表是承载数据的最佳形式。
④数据查询。
内存表在建立后查询操作是通过在哈希表中建立关键码来完成的,查询效率很高。在考生数据表中,我们通过初始化在具有唯一性的考生号来设立关键码并预留查函数接口来构建查询语句,根据通讯模块调用传递的参数筛选符合条件的数据并返回。
(2)通讯模块。
通讯模块实现了数据缓存层与网络程序层之间的交互,因此该模块最为关键之处就是要建立一个可靠、高效的监听、应答机制。我们采用了WCF服务去完成这种监听应答机制。WCF(Windows Communication Foundation)是由微软公司发展的一组数据通信的应用程序开发接口,WCF构建了一个在互联系统中实现各个应用程序之间通信的分布式框架。在该框架内数据缓存层的通讯模块与网站程序层的数据访问类之间通过契约实现数据请求操作,与访问请求发起者无关,从而使网站程序层的每台服务器进行的访问操作都是相互的独立的,为网站程序层的可扩展性提供了保障。
(3)调度模块。
该模块负责数据缓存增量日志的定时备份;负责将数据缓存模块保存的数据改动文件写入到数据库层中,将数据持久化。调度模块负责内存数据库与SQLSEVER数据库之间的同步,是数据缓存层与数据库层之间的桥梁。
调度模块的运行机制是:数据缓存模块每1秒钟将发生变化的数据以一个XML文件的形式写入磁盘中,调度模块每隔5秒中(时间可以自行设定)将这些文件读取写并将这些操作写入数据库,然后这些XML文件压缩打包后移动到磁盘中设定的备份目录中。在大并发访问发生时,因数据库操作写入速度远比不上内存数据库的操作速度,这时会发生待写入XML文件的积攒的现象,但是只要有内存数据库操作量较小于数据库写入的时段出现,这部分积攒的操作文件就可以按时间顺序被逐渐写入。通过这样的原理,数据缓存层为数据库层起到了缓冲的作用。
通过这样的运行机制数据缓存层会在运行过程中就会产生一个可操作的数据库副本和一个日志副本,这时如果数据库发生故障,我们可以将保存的xml文件解压后重新写入到数据中,为系统的数据安全性提供了双重保障。
由于数据缓存层的操作量会很大,要将这些操作保存在文件中,这就涉及到内存对象序列化。使用xml序列化内存对象,结果简洁,读写效率高,同时也便于在一个文件中序列化多条数据,如图4所示。
3 数据库层
在网报系统中,由于采用了数据缓存层的设计,数据操作压力集中在了内存数据库中,而SQLSERVER仅作为数据持久存储和少量的管理用数据查询挖掘使用,因此网报系统中仅使用了一台服务器作为数据库服务器使用。
4 系统测试
构建测试环境
为了详尽的对网报系统进行测试,确保系统的稳定运行。我们构建一个较为接近实际情况的运行实验环境。该环境包括以下几点。
(1)网报系统部署:测试环境中使用了7台HP服务器。分配为:WEB服务器4台,部署相同的网站程序层;WCF服务器2台,一台部署通讯模块和数据缓存模块,一台部署调度模块并且用于XML文件备份;数据库服务器1台,部署数据库层。服务器部署情况如图5所示。
(2)网络部署:采用实际应用状态下网络拓扑结构,通过F5对WEB服务器进行负载均衡,具体网络结构如图6所示。
(3)测试服务器:采用1台HP580服务器,用于测试软件安装,测试工具LoadRunner (V8.1)。
(4)测试方法:本次测试包括功能测试和性能测试。
功能测试:即黑盒测试,测试人员在了解被测评目标的功能规格、高层设计和操作规范等的基础上,测试被测系统的可用性。
性能测试:对系统在多种并发连接数情况下的处理能力进行测试。本次测试主要采用Dynamic workload(动态负载模型)逐步增加并发用户数,给系统逐步加载压力,并且让系统在该负载条件下持续运行一段时间,然后逐渐减少并发用户数,检验被测系统是否能够稳定运行,同时监测Web服务器和缓存服务器的性能。
志愿填报测试。
(1)测试目的。
分别测试从网站程序层内网单台web服务器接入和外网4台WEB服务器负载均衡接入网上填报志愿系统,测试在多用户并发登录时的处理能力。
(2)测试步骤。
①从内网单台WEB服务器接入网报系统,验证系统“志愿填报和修改”功能可用。
②利用LoadRunner录制并保存为“tiaobao”的脚本,对脚本中实时参数VIEWSTATE和考生考号进行参数化。
③启动LoadRunner负载生成器,加载“tianbao”脚本,设置并发用户数为200,设置持续运行时间为“5 min”,并且选择“运行前初始化所有Vuser”。
④执行负载测试,运行完成后,启动“Mercury LoadRunner Analysis”生成并保存测试结果。
⑤依次调整步骤③中的并发用户数为200、500、1000、1500、2000、2500,并分别重复步骤③~步骤④。
⑥从外网通过F5负载均衡4台WEB服务器接入网报系统,并分别重复步骤②~步骤⑤,由于会话保持策略会持续将访问指向同一台服务器,此时将会话保持和session验证均去掉,采用随机发牌模式测试。
测试结果如表1所示,事物响应时间对比如图7、8所示。
5 測试结果分析
测试期间在上述压力条件下,从内网单台服务器接入,占用了200 Mbps的带宽,服务器CPU满负荷运行,系统运行正常。从外网负载均衡接入,此时由4台服务器共同负载,占用了500 Mbps的带宽,服务器CPU资源有富余,平均事务响应时间远低于内网,但性能没有出现理论上的4倍提升,由此可见网络设备会带来一定的效率损耗,应用系统自身运行正常。性能测试完成后,CPU和内存占用均回落至正常水平,未出现内存泄露现象。
通过测试看出WCF数据缓存层成功的实现了高并发负载下的内存数据库功能,在数据库操繁忙的情况下为数据库起到了缓冲的作用。通过F5负载均衡设备成功实现了WEB服务器的负载均衡,虽然单台WEB服务器有一定的效率损耗,但是却带来了网站程序层的可扩展性,实战状态下如果系统出现负荷过高的情况,只需增加WEB服务器的数量即可实现系统性能的提升。
6 结论
实践证明,对网报系统进行分层,网站程序进行可扩展设计和把内存数据库作为向数据库中写入数据前的缓冲的思路,能很好的增加网上填报志愿系统一类的大数据量的网上应用程序的吞吐能力,从而完成高并发负载的网上填报志愿需求。不足之处是,这种形式需要占用大量的内存,对服务器内存有一定的硬件要求。在方案思路的基础上还可以对以下几方面进行完善。
(1)考虑将数据缓存层转化为分布式应用系统从而增强其负载的数据量和安全性。
(2)数据在内存中的保存形式针对具体的业务应用做进一步的优化,在性能上还有挖掘的潜力。
(3)Xml数据文件在保存在磁盘上的操作可以考虑放在固态硬盘上可以能进一步提高读写性能。
参考文献
[1]奚江华.圣殿祭司的ASP.NET3.5开发详解II[M].电子工业出版社,2008.
[2]金益民.一种基于XML的WEB数据库应用模型研究及应用[J].现代电子技术,2004.
[3]蒋金楠.WCF技术剖析[M].电子工业出版社,2009,6.
[8]曾凯,曾斌,杨英,等.扩展SQL跟踪数据技术在数据性能诊断上的应用[J].计算机应用与软件,2006,23(1):128-130.
[9]卢成均.多层模式下通用数据存取层的设计与实现[J].计算机工程与设计,2007,28(13):3265-3269.
[10]Andrews A,Offutt J,Alexander R.Testing Web applications by modeling with FSMS[J].Software Systems and Modeling,2005,4(3):326-345.
[11]王昌辉,王远景.基于URL路径的Web信息检索模型的研究[J].贵州教育学院学报(自然科学),2008,19:36-39.
[12]尚俊杰,秦卫中.ASP.NET程序设计案例教程[M].北京:清华大学出版社,2005.