写这篇经验之前,先总结下做这个系统出现的一些问题:
忽现Unicode编码、票数清零、服务器当机、内存溢出、多线程处理文件造成文件错误更新、没有控制好用户狂刷、最囧的是,IO流没有close掉......
在公司刚换了个项目组,接手了一个投票系统的任务,参于被投票的对象是一批经过多次评选的经纪人(一共60人),谁得票最高即可获得丰厚奖品的。
投票的规则以每个IP每天最多可以投50票,投票者抓住这个规则之后,一直疯狂的刷点...
我们开始把投票结果记录到.properties里面,也许因为刷点的原因,出现了莫名其妙的\u0000空格Unicode错误编码,造成对配置文件解析错误。严重的情况是,有某些参赛者的票数突然清零,狂飙冷汗,有不少的参赛者打电话来投诉(糟了,要被开除了...)看了下配置文件,还是一些无缘无故出现Unicode编码。
原来做了几个投票页,1个IP只能投1票,所以很少同步操作的情况。但现在不同了,于是放弃.properties,改成xml,.properties最大的问题是更新后会引起顺序混乱,不好管理,而xml解决了这个问题,对于编码问题也容易处理。最重要数据被清零的问题也解决了。
<vote>
<members>
<member id="1" count="12839"></member>
<member id="2" count="4550"></member>
<member id="3" count="245"></member>
<member id="4" count="20"></member>
<member id="5" count="39"></member>
....
</members>
<dates>
<date id="20090611">
<ip addr="192.168.16.38" count="6"></ip>
....
</date>
....
</dates>
</vote>
P.S.:这次新学了JDOM,用它来解析XML真的很方便,有兴趣可以学习一下。 http://www.ibm.com/developerworks/cn/java/j-jdom/index.html
为了收集参赛者被投票的信息,在投票中加入了一个记录投票数据的xml,结构如下:
<vote>
<members>
<member id="1" name="张三" count="3">
<ip addr="192.168.16.38" startTime="09:37:35" endTime="09:37:39" count="3"></ip>
....
</member>
....
</members>
<ips>
<ip addr="192.168.16.38" startTime="09:37:35" endTime="09:37:39" count="3">
<info voteId="1" voteTime="09:37:35"></info>
<info voteId="1" voteTime="09:37:37"></info>
<info voteId="1" voteTime="09:37:39"></info>
....
</ip>
....
</ips>
</vote>
这个投票详细记录的方法我们选择在晚上更新,但是更新之前服务器突然挂掉了,不知道什么原因,这个新的生成xml的方法更新以后,服务器挂掉的频率更高了,后来查看内存,一直狂涨,这下子就囧了。。。肯定是流忘记关闭了。然后回忆xml更新的一句代码,这是JDOM封装的保存更新xml的方法。代码如下:
public void updateXml(Document doc, String xmlUrl) {
Format format = Format.getPrettyFormat();
format.setEncoding("UTF-8");
format.setExpandEmptyElements(true);
XMLOutputter printDoc = new XMLOutputter();
printDoc.setFormat(format);
try {
printDoc.output(doc, new FileOutputStream(xmlUrl));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
里面有个 new FileOutputStream(xmlUrl), 问题就出在这里了,压力测试时没注意好内存的变化,于是重新初始化一个FileOutputStream对象,结束时关掉。
修改后,代码如下:
public void updateXml(Document doc, String xmlUrl) {
FileOutputStream out = null;
Format format = Format.getPrettyFormat();
format.setEncoding("UTF-8");
format.setExpandEmptyElements(true);
XMLOutputter printDoc = new XMLOutputter();
printDoc.setFormat(format);
try {
out = new FileOutputStream(xmlUrl);
printDoc.output(doc, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
哎,真失败吖。。搞了两年程序出了这样一个失误。。悲哀吖。。问题还是没有完全解决,投票的人还是一直狂点狂刷,于是在页面加了这样段很简单的脚本,限制了投票人的疯狂操作。js代码如下:
var num = 0;
var oId = "";
function toVote(id){
oId = id;
if(num == 5) {
alert("很抱歉,您投票的频率太快,请稍后再试。");
return;
}
if(num!=1){
num = 1;
createxmlHttpuest("update.jsp?id="+id+"&time"+new Date());
num = 5;
fangshua();
} else {
alert("正在投票中,请稍后");
}
}
function fangshua() {
window.setTimeout(function(){num = 0;} ,5000);
}
红色部分就是新加进去的防刷脚本,虽然简单,但是很实用。
但是为了避免刷票而控制程序问题,还是治标不治本,于是在调用更新票数的方法上加上同步锁,避免多线程引起的错误。代码如下:
Object obj = new Object();
....
synchronized (obj) {
String cTime = xml.CurrentlyTimes("yyyyMMdd");
try {
content = xml.getVoteUpdate(id, cTime, ip);
} catch (Exception e) {
content = null;
}
if (content.equals("ok")) {
xml.statVote(ip, id);
}
}
对更新的方法经过压力测试,50个同步线程执行,统计的xml与详细记录的xml文件更新也不会出现多线程写入的错误。但是还有一个细节,处理一个文件,建议单独使用一个File对象,避免出现引用错误。
File file = new File(this.statVoteXmlURL);
Document newDoc = null;
SAXBuilder sb = new SAXBuilder();
sb.setIgnoringElementContentWhitespace(true);
if (file.exists()) {
sb.setIgnoringElementContentWhitespace(true);
try {
newDoc = sb.build(file);
} catch(Exception e) {
e.printStackTrace();
return ;
}
....
总结一下之前做投票系统需要注意的问题:
1、一定要做防刷分脚本.
2、频繁被调用的方法要做同步,做多线程压力测试.
3、处理文本的对象要单独初始化,避免引用冲突.
4、使用xml记录数据比使用文本记录要好.
5、流对象不能单独在参数中实例化,不然会很囧...它不会自己关掉的,必须手动关掉.
分享到:
相关推荐
【简易网络投票系统】是一个基于Thinkphp框架开发的初级投票应用程序,主要针对小型投票活动而设计。这个系统展示了Thinkphp框架的基本应用,为初学者提供了一个实践和学习的平台。 Thinkphp是一个流行的PHP开发...
《.NET技术构建的在线投票系统详解》 在信息技术飞速发展的今天,各种网络应用层出不穷,其中在线投票系统作为互动性强、参与度高的工具,被广泛应用于各类活动、调查及决策过程中。本篇文章将深入探讨一个基于.NET...
【web投票系统】是一个基于Web技术的互动应用,主要用于收集用户的意见或偏好,例如评选最佳影片、最受欢迎的产品等。在本项目中,你将获得一套完整的代码和SQL建表语句,无需从零开始,只需配置合适的运行环境,...
【标题】"奥运申办国投票系统java"揭示了这个项目是基于Java编程语言实现的一个应用,主要用于模拟奥运申办国的投票过程。在IT领域,这样的系统设计可以帮助开发者提升对Java语言的理解,特别是对于面向对象编程、...
【网上投票系统源代码解析】 本资源提供的是一个完整的网上投票系统的源代码,这是一套用于实现网络上进行各类投票活动的应用程序。网上投票系统在现代社会中广泛应用,无论是企事业单位内部选举、公众议题讨论,...
在这个"asp网上投票系统"中,我们探讨的是如何使用ASP技术来创建一个功能完善的网上投票平台,该平台包括后台管理和数据库支持。 首先,ASP网上投票系统的前端通常会包含HTML、CSS和JavaScript代码,负责展示用户...
【C#开发的小型投票系统】是一个以C#编程语言构建的应用程序,旨在提供一个基本的投票功能。这个系统的设计和实现是针对初学者或有经验的开发者进行技能提升和实践训练的理想平台。通过参与此类项目的开发,可以深入...
在互联网上,投票系统可以有效地实现用户参与、数据收集和结果分析,从而为决策提供依据。本教程将深入探讨如何构建一个基本的PHP投票系统。 首先,我们需要了解PHP的基础知识。PHP(Hypertext Preprocessor)是一...
【北大青鸟投票系统(votes...总的来说,"北大青鸟投票系统(votes)"是一个典型的Java Web项目,体现了现代Web开发中的ORM与MVC模式结合,展现了如何通过技术手段解决实际问题,同时也为学习者提供了宝贵的实践经验。
【基于JavaWeb的投票系统详解】 JavaWeb技术是构建分布式应用程序的一种强大工具,它结合了Java语言的强大功能和Web的广泛可访问性。在本项目中,“基于JavaWeb的投票系统”是一个使用JavaWeb技术实现的互动应用,...
【VC# 投票系统详解】 在信息技术领域,VC#(Visual C#)是一种由微软公司开发的面向对象的编程语言,广泛应用于Windows应用程序的开发。本案例将深入探讨一个基于VC#的投票系统,该系统是软件工程中的一个常见实践...
【PHP在线投票系统源码详解】 本资源是一个基于PHP开发的在线投票系统源码,包含了完整的数据库设计,为用户提供了创建、管理以及参与投票的功能。这个系统的核心目标是实现一个安全、高效且易于操作的投票平台,...
在本项目中,我们关注的是一个基于Java Web的简单投票系统。这个系统旨在提供一个基本的平台,允许用户参与各种主题的投票,并直观地展示投票结果。以下是对这个"java小型投票系统"的关键知识点的详细解释: 1. **...
ASP投票系统源码是一种基于Active Server Pages (ASP)技术构建的网络投票应用程序。ASP是微软开发的一种服务器端脚本环境,用于创建动态交互式网页。它允许开发者使用VBScript或JScript语言编写代码,实现与用户交互...
学习这个PHP投票系统源码,不仅可以帮助开发者理解PHP Web应用的基本结构和工作原理,还可以深入学习数据库操作、用户认证、数据安全等相关知识,对于提升PHP编程技能和实际项目经验非常有帮助。同时,通过分析和...
首先,我们需要理解投票系统的基本组成部分。一个简单的投票系统通常包括以下几个关键功能: 1. **用户认证**:为了确保投票的公正性,系统需要识别和验证用户身份。这可能涉及到登录机制,如通过用户名和密码,...
【Java做的投票系统】是一个基于Java技术栈的实用应用程序,主要使用了jsp、Struts2和Hibernate框架。这个系统的设计和实现旨在为用户提供一个在线投票的功能,用户可以创建投票、参与投票并查看投票结果。对于初学...
《MineVote投票系统 v1.01:基于文本的数据存储解决方案》 MineVote投票系统 v1.01 是一个简洁而实用的投票应用,专为那些不希望或无法使用MySQL等传统数据库支持的用户设计。这个系统的核心特性在于其独特的数据...
【在线投票系统】是一种基于网络的应用程序,它允许用户通过互联网进行投票,收集并统计意见或选择。在本文中,我们将深入探讨一个使用JSP(Java Server Pages)技术开发的在线投票系统的毕业论文内容。 首先,...