记一次大型活动-圣诞苹果活动的心得

圣诞送苹果活动过去几天了,回顾一下这次活动是笑递(创业项目)第一次真正的大型活动,为了做好这次线上200抢两百个苹果的活动,三个星期前决定重构一遍笑递web前端的代码,从14周结课,我一直在想该怎么重构,之前的前端代码非常混乱,用的是python的flask框架,保存会话用的js的cookie,为什么说混乱。

1. cookie的保存,很多地方都有,js的几个函数,还有python在返回头加Set-Cookie,要是想改变过期时间要改很多地方

2. 登录验证,前端每个页面有个登陆验证,因为路由规则还是用的python,所以python那边也要进行登录控制,不但如此,要想在页面渲染之前判断一些需要登陆才能的逻辑,python还必须用前端的cookie,就是这样

auth = dict([tuple(cookie.split("=")) for cookie in request.headers.get("Cookie").split("; ")])
严重依赖于前端的cookie,要是哪次cookie不小心丢了,整个逻辑就错了

3. next_url的控制,完全由前端控制,写了几个函数都有,记得有次跳转发生了错误,找半天都不知道怎么改,心累

4. css和js文件,这个是最坑的地方,一个登陆注册就有好几个短的css文件,命名混乱,有的用了sass有的没用,js也乱,每次做压缩都要手动,几个几个文件嵌在一起,嵌错了整个js逻辑就乱了,还有一点最最坑的是因为微信缓存这个坑货,我必须每次改动css和js文件之后手动在引用的文件之后改版本号,比如user-tpl.js?v=1.0,工作量之大令人崩溃。

5. 实时通信很卡,实时通信完全由前端控制,请求对话列表和请求聊天记录都要和leancloud进行连接,在移动端,浏览器的完成一个HTTP事务所需的时间严重依赖于手机(3G/4G)网速,有些人手机网慢,进去聊天就卡死了

6. 短信验证违反了单一职责原则,短信验证是交给后端,因为当时想短信验证必须交给后端,要不然随便一个人写个脚本绕过前端就可以用任何手机号注册,但是转念一想,你个后端不好好返回数据跑去做短信验证搞毛线,那是你干的事情么。

基于以上六点,我已经忍无可忍了,本身我对代码质量的要求就很高,居然每次改需求都要做一大堆容易出错又费劲的无用功。

说干就干,因为重构之前我已经对gulp、nodejs、文件压缩和文件哈希有所了解,知道nodejs是完全异步的语言,这对于io密集型应用简直是太友好了,然后马上花了10分钟去菜鸟教程看了下语法,然后又去找框架,叫express(之前没听说过express,但是咱们靳东哥说过风水宝地,必有大墓,这么优秀的语言用脚趾头想想都能想到一定有非常优秀的框架),找到了就马上开始了孤独的重构生活。

重构完说说解决方案

1. cookie的保存,前端不再自己操作cookie,改用nodejs 的session

2. 登录验证,因为改用了session,所以前端不再有登陆验证,全部利用express的中间件实现,交给nodejs

3. next_url控制,还是由前端和nodejs一起控制,但是前端控制的少

4. css和js文件,该合并的合并,css全部使用sass,img和css,js压缩,文件哈希全部利用gulp自动完成

5. 获取对话列表和聊天记录交给nodejs,前端只做实时发消息

6. 短信验证交给nodejs,注册api不再是普通接口

做完这些项目的可维护性上了一个台阶,然而已是快16周了,圣诞活动马上就来了,于是又匆忙去学如何写抢购页面,我想抢购的后端逻辑肯定不是来一个用户抢到了就把苹果数减1,要考虑并发的问题,有线程安全问题,看了网上的一些说法,决定用redis的watch、multi实现,后者是实现事务,因为苹果减1和把这个抢到的人的身份记录,这两个过程不可被打断(考虑到抢到的顺序问题),watch则是观察在事务执行过程中苹果数有没有改变,一旦改变,整个事务将失败(考虑这个问题,苹果只剩一个了,现在有10个人同时发了请求,服务器发现苹果数量还剩1,10个请求同时要set苹果数为0,那到底谁抢到了,所以必须要用乐观锁,只要在修改的过程中key发生了变化,事务就失败),代码贴出来给大家看一下(csrf防范不在这里,用了中间件)

router.post('/christmas', middleware.needOpenid, function (req, res) {
    var lastApples;
    var openid = req.body.openid;
    client.selectAsync(config.redis.apple_db).then(function () {
        return client.watchAsync('apples');
    }).then(function (result) {
        if (result == 'OK') {
            return client.hexistsAsync('users', openid);
        } else
            Promise.reject('error');
    }).then(function (result2) {
        if (result2) {
            res.status(400).json(tool.makeErrorJson('您已经抢过了'));
            res.end();
            return Promise.reject('error');

        } else {
            return client.getAsync('apples');
        }
    }).then(function (apples) {
        apples = parseInt(apples);
        if (apples >= 0)
            lastApples = apples - 1;
        //再次判断
        if (lastApples < 0) {
            res.status(400).json(tool.makeErrorJson('啊欧,苹果没有了...'));
            res.end();
            return Promise.reject('error');
        }
        return client.multi().set('apples', lastApples).hsetnx('users', openid, 0).execAsync();
    }).then(function (result4) {
        if (result4 == null) {
            res.status(400).json(tool.makeErrorJson('系统繁忙'));
            res.end();
            client.unwatchAsync();
        }
        else {
            res.json({});
            res.end();
        }
    }).catch(function (error) {
        res.end();
        console.log(error);
    });
});
做完之后就各种测试,再把数据分析的代码放到页面里,到了21号晚上,激动人心的时刻到了,产品经理和技术总监同时守着电脑。

8点已到,产品经理那看到的PV(页面浏览量)数瞬间爆发,升到几千,服务器慢慢地越来越卡了,用户的电话一个接一个的打过来,反应进不去页面,瞬间懵逼,感觉到事态严重,我用top命令查看一下,有个cpu 90% id,我以为是cpu利用率90%了,其实是90%的空闲,后面才反应过来,但是当时完全急了,于是做了一个艰难的决定,把服务器升级到2核,重启服务器,要知道重启服务器又耗时间还容易出错,但是当时脑袋懵了,只想着重启,升级了内核,重启了服务器,靠,redis的数据丢了,当时的我眼泪都快掉下来了,心里一万个自责,靠,redis是半持久化数据库,东西是暂时存在内存的,没做备份重启服务器数据都丢了,还好当时成功的人很少,要不然就gg了。但是重启之后发现问题并没有多大改善,而且服务器oss的连接一直卡死,当时更急了,这时群里张老师说你们的图片多大,我说几百k,说出这一句的时候犹如醍醐灌顶,靠,是带宽问题,服务器只有1M带宽,于是马上去升级带宽到6M,问题瞬间解决。

21号结束之后总结了一下抢之前没考虑带宽问题,还有图片也太大了,所以以后规定笑递web平台的图片不能超过50k,然后马上做图片压缩,到了23号再一次抢,我事先把带宽升级到10M,图片压缩到十几k,再用htop命令(top命令的友好版)看cpu,iftop看带宽,然后完全无压力了。
总结一下,经过这次活动,对项目的理解有了一个新的高度!






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值