大型WEB应用性能调优总结

声明
本文为Gleasy原创文章,转载请指明引自Gleasy团队博客 css

问题初级定位方法: 一感三看
一感,凭我的感受,操做不流畅,有挫折感确定有问题。
三看:
一看ajax请求的执行时间,网络条件好的状况下,超过400MS的确定有问题;
二看静态内容(html,图片,js,css)等是否cache,没有cache确定有问题;
三看同一个ajax请求的数量,若是连续有N个(N>3)以上同一个AJAX请求,确定有问题; html

问题深刻定位方法
方法一:使用stopwatch,在程序中植入log记录执行时间,经过查看执行时间以定位出问题的代码段;
方法二:间隔重复可疑操做,观察记录CPU变化状况。用以观察是否有死循环或者大规模遍历。
方法三:恶意快速重复点击同一个功能按键20次,观察是否会重复发起后端请求20次,若是是,那么,也是有问题的。
方法四:使用SQL监控(druid)来观察每个SQL执行次数,执行时间,从而发现热点问题 前端

应用技巧
NO1. 弱化数据库
1.将数据库弱化为“存储”,避免使用数据库查询能力,尽可能使用主键或惟一键进行精确读取动做,数据量不太大的表可使用普通索引进行精确读取,避免使用范围查询(> < != between in),禁止使用like,禁止使用子查询,联合查询,exists查询;
2.范围查询和like查询,一概使用索引平台CloudIndex替代;
3.子查询,联合查询,exists查询:一概在应用层进行逻辑拼装(若是数据量太大,可使用Map-Reduce进行多线程计算,若是再大可使用cloudjob进行分布式调度) web

NO2. 善用缓存
1.提升缓存命中率为终极目标;
2.容易忽视的缓存问题:大量访问己被删除数据,因为数据不存在,缓存确定不命中,致使频频访问数据库;解决方法是对己删除的数据作特殊缓存标记;
3.对写入性能要求极为苛刻的场景可使用redis缓存-存储切换的方式进行异步写入:写入redis(标记为存储),马上返回,另起独立线程将写入数据同步至数据库,同步成功以后,将redis中相应数据标记为缓存。 ajax

NO3. 用好中间件
1. 对于写入性能要求苛刻(或写入并发量特别大的)且容许写入延迟的状况,使用CloudMQ中间件;好比发邮件,发微博,发留言等;
2. 定时任务(好比定时发送邮件,定时提醒),特别适合使用CloudJob中间件
3. 对于消耗性任务(好比执行时间长且任务量大,消耗CPU资源),可使用CloudJob进行分布式任务调度,将众多大任务放到N台后台机器上执行; redis

NO4. 批量操做(从前端到后端)
1. 前端批量,针对大量重复调用某一接口的状况,因为AJAX的异步性,能够将N个请求合并成一个请求,串行执行AJAX,策略以下(伪代码): 数据库

01 var getDepartmentLinkByUid = function(uid,callback){
02   if(loading){cache.push({uid:uid,callbackup:callback}); return;}
03   loading = true;
04   realGet();
05 }
06  
07 var realGet = function(){
08  var tmp = cache.splice(0);
09  $.ajax({
10     data:由tmp的uid拼接而成,
11     success:function(dt){
12       for(var i=0;i<tmp.length;i++){
13         var uid = tmp[i].uid;
14         var rdata = dd[tt];
15         tmp[i].callback(rdata);
16       }
17       if(cache.length>0)  realGet();
18     }
19   });
20 }

 

2. 缓存批量(承接上面的例子) 后端

1 objects = mget(uids);
2 notcached = new ArrayList();
3 for(uid:uids){
4  if(objects 不包含uid) notcached.add(uid);
5 }

 

3. 数据库批量查询(承接上面的例子),批量更新缓存 缓存

1 notcachedData = select * from department where uid in (notcached列表);
2 mset(notcachedData 生成的 map);
相关文章
相关标签/搜索