BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / www-technology / #27906同步于 2014/10/25
该镜像源已超过 30 天没有更新,可能在源站已被删除。
WWWTechnology机器人发帖

[心得]浅谈人文知识竞赛网站的框架设计

emlcj
2014/10/25镜像同步93 回复
[请脑补成Markdown] 前一段时间,搭建了学校人文知识竞赛的网页,说实话,做这玩儿如果只是简单的做一做的话,根本不是什么大问题,但是考虑到之前上一届做的不小心崩掉了最后只有180人答题,所以还是仔细思考了一下在高并发下,如何保证服务器不崩,以及与此同时保证足够的漂亮不俗。 实际上做这个东西,确实是费神费心,关键是我还在上班,上班的内容也不算特别轻松,所以大概所有的时间,是某一个晚上熬夜到3、4点,然后每天下班后修修补补,不过所幸,在最后也基本没有出现什么较大的问题,整体上来说,是成功的。 ## 方案设计 人文知识竞赛是一个及时性很强的东西,一方面要保证答题的迅速,另一方面要尽可能的减少作弊的可能性。 去年的方案是这样设计的: 1. 每答一道题,请求下一道题 2. 三十分钟十道题 3. 报名系统在主页上,随时可以报名 这之间其实需要斟酌的地方有很多,首先,三十分钟十道题,本身就无法抵制作弊的发生,其次,每一个答题者,起码要发生11+的请求,这对服务器是考验的(何况是渣PHP虚拟主机)。而且,报名系统是公开的,可以从这里对服务器进行攻击。 所以,我们索性先不从技术上的角度去考虑,而是从赛制上去考虑: 1. 注册系统需要改,我们最后商议,改成了邮箱注册,因为我觉得除非是够无聊,否则不会注册几十个邮箱去试探我们的系统。并且注册在答题前一天就关闭了,尽可能的减少由于恶意注册而带来的损失。 2. 十分钟五十道题,尽可能的减少作弊的可能性,意味着,网上搜索答案是有限的。 ~~虽然最后我们发现十分钟五十道题依旧不是很多~~ 3. 必须是答完一道题出现下一道,这个无法更改,但是我们可以在一开始就下载到全部的题库。 4. 分时答题,进一步减少服务器压力。 至于防作弊: 1. 一个人的帐号是有限制的,除非无聊去注册辣么多的帐号。 2. 无论是激活,还是抓题库,只能干一次。 3. 验证都在后端完成,前端改东西木有用。 ## 技术设计 大框架设计了,那么剩下的只有实现了,中心设计如图,其中Polymer是所有的核心: ### 前端设计 前端采用的是Polymer,至于Polymer是什么,我在之前的文章里面已经说过了。 为什么采用Polymer呢?首先,Polymer是在本地渲染的,一定程度上缓解了服务器的压力,其次,Polymer适合构建单页App,可以非常方便的完成逻辑以及UI设计。 也就是说,在你第一次访问主页的时候,所有的前端代码都已经下载到本地,**不需要**在对服务器进行请求,对服务器造成的压力是一次性的,更何况服务器不用去渲染数据,进一步减轻压力。 需要数据的时候,向后端发起AJAX请求,获取数据。这个过程是基于JSON BASED TOKEN的,可以更好防止受到污染。 所以最后给用户的效果就像是使用一个app一样,虽说在pc上可能略诡异,爪机上的体验更加,但是总体来说效果是不错的。 前端方面,我使用了Google的Topeka的大部分源代码,不过在逻辑上,也进行了大幅度的修改,等我整理好这一部分代码,过段时间可以开源。 ### 后端设计 #### Nginx 反向代理+静态页面 ~~高并发就不要作死用Apache了~~ 反向代理用于将API的接入交给Nodejs处理 #### Nodejs Stateless Web API 选用nodejs就是为了高并发,我相信选用其他的语言或多或少在性能上都弱于nodejs,我们的需求是IO密集型的,刚好适合nodejs发挥其特长。 后端和普通的后端不一样,只有一个提供JSON API的功能,其他的页面逻辑,全部由前端MVC框架实现,这样可以尽可能的减少后端生成页面所产生的压力。 具体的实现就和普通的程序一样了,无非是CURD,但是考虑到可能的数据库压力,我主要是用MongoDB做数据的持久化,以及Redis缓存临时的数据(比如题库,比如临时生成的答案),事实上,在后来的整理分析中,如果只是使用MongoDB甚至MySQL都是足矣完成任务的,不过使用Redis的性能最佳,只是开发周期可能长一些。 #### SendGrid Mail Service 我们使用了邮箱注册,为了尽可能的减少恶意注册所带来的影响。 实际上在使用的过程中,SendGrid表现的并不出色,每一次请求的成功率大概也只有40%左右,可以说在前端的体验非常不好(这一点也是由于我懒得去重写一个代码),只是有耐心的同学还是挺多的,所以后来邮件注册用户超过700人。 可能在生产环境中,寻求SendCloud是更好的选择。~~只是你们连49元的最便宜方案都不想用,我就只能用这种免费的了~~ 这里提一下,一开始我们使用的是MailGun服务,邮件成功率很高,但由于服务器的姿势不对,经常就爆出异常(分析之后是访问了空域名),不知道为何,总之,我替换掉了。 ## 总结 ### 数据分析 ~~因为学校非常非常抠,所以我就只能找免费的方案了~~ 所幸,找到了一个非常好的方案,M$的Azure正在进行一元免费试用……(这里不是打广告啊喂),大概就是出一元,然后这一个月给你2000的信用额度……所以实际上还是挺赚的,于是我们的服务器就华丽丽的采用了独立4核+7G内存(啥,你问我为啥不用更高的配置?Nodejs是单线程的啊……) 最终的结果还是令人满意的,最开始请求页面并不算慢,并且之后的每一次请求都非常之快,几乎秒开(至少比各大网站登录快),我觉得就算是让我用1G内存+单核CPU,可能是在Redis方面有点瓶颈,但是总体上来说,也可以完成目标的,甚至于全部在一个时间内答题,也是可以Hold住的。 所以,好的架构是成功的一半,虽然目前的架构也说不上完美,但是总比PHP虚拟主机好(很多)吧... ### 改进 需要改进的还有很多的……~~不过由于懒癌晚期被窝忽视了~~ 前端方面:进一步的美化和剔除Bug(咳咳,有个Bug应该被很多人忽视了……) 后端: 1. 完全剔除Mongo,全部采用Redis做持久化 2. Token加入验证机制,并且每完成一次请求,更新一次Token,进一步防止作弊 3. 前端请求的数据加密,~~至少不应该明文传输~~ 4. 可以用socket.io重写AJAX,这样,无论是在安全性还是性能上来说都会更胜一愁 5. 如果还想要提高瞬时的并发,可以在答题之前为每个人缓存好题库,做好静态化处理,这样可以大大的节省服务器的IO。 ### 真正的总结 其实到现在,总共的成本是 近十个小时的工时+1元VPS+49元的域名,还是挺便宜的…… 总共是1200多人完成了信息的绑定,最终900+人答题,除去部分没有答题的,以及少部分因为自己刷新了页面或者其他无聊操作找我们扯淡的,这个任务还是完成的不错。 目前的这个配置下的系统,承受住近万人的并发是没有问题的。 客观上来说,我觉得收获之一就是不要一开始想着技术能解决的问题都不是问题,而是应该从策划上出发,再去决定使用什么计划,否则只能陷入技术陷阱了。 过段时间会完成开源,在GIthub@lcjnil上面,欢迎持续关注。不过由于技术水平+智力受限(还有文字表达捉鸡),还有很多不足以及谬误,欢迎和我讨论...
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
baiyang0132机器人#1 · 2014/10/25
好像很厉害的样子
LYXI机器人#2 · 2014/10/25
大神
frip机器人#3 · 2014/10/25
个人觉得…加上验证码就不会这么麻烦了…… 【 在 emlcj 的大作中提到: 】 前一段时间,参与搭建了学校人文知识竞赛的网页设计,...
emlcj机器人#4 · 2014/10/25
【 在 frip 的大作中提到: 】 : 个人觉得…加上验证码就不会这么麻烦了…… : : 前一段时间,参与搭建了学校人文知识竞赛的网页设计,... …………确实没想到QAQ,不过验证码实现起来确实在防攻击上不错,新姿势GET
whw0928机器人#5 · 2014/10/25
先mark
q644540267机器人#6 · 2014/10/25
来膜拜大神
whitefirl机器人#7 · 2014/10/25
究究吊吊的,先顶,后看⊙▽⊙
sharpzhao机器人#8 · 2014/10/25
为什么会有个反向代理 不是只有一台机子么 【 在 emlcj 的大作中提到: 】 前一段时间,搭建了学校人文知识竞赛的网页,说实话,...
emlcj机器人#9 · 2014/10/25
【 在 sharpzhao 的大作中提到: 】 : 为什么会有个反向代理 不是只有一台机子么 : : 前一段时间,搭建了学校人文知识竞赛的网页,说实话,... nodejs不是跑在80端口,所以需要把外部的80请求转移到nodejs上面去