web性能优化

      

[文章作者:狂奔的鹿 本文版本:v1.0  转载原文链接:http://dynamiclu.iteye.com/]

  web性能优化(一)弱请求处理

     从开发人员到系统工程师、运维工程师以及架构师,经常会收到用户或需求方的反映,说我们网站打开地很慢,甚至出现了502等。这个问题原因较多,处理方式也较多。我要分享的是一个弱请求处理的优化方式。

      弱请求在这里是指那些响应较慢、耗时较长的HTTP请求,是笔者临时命名的。有经验的工程师都知道,我们要分析系统性能问题时,只需分析这个系统的请求处理容量和单个请求的平均响应时间。有前辈分享的2/8原则,提到我们的系统有20%左右响应较慢的请求占用了超过20%以上的资源。这里要说的就是对这些请求响应时间的处理方式。

 

1.如何获取系统的单个请求响应时间?

     客户端层面的较复杂,不同的地区有差别,可以用httpwatch,压力测试软件,或部署在各国的各地的性能监控平台获取。
     服务器端的方式有:1.配置nginx,apache日志格式  2.在工程代码里加filter,记录下来。建议用第一种方式。

  

步骤代码
  1. 修改nginx配置文件   
  2. vi /usr/local/nginx/conf/nginx.conf   
  3. 找到log_format,在最后添加request_time项,如下   
  4. log_format main '$remote_addr - $remote_user [$time_local] '  
  5. '"$request" $status $bytes_sent '  
  6. '"$http_referer" "$http_user_agent" '  
  7. '"$gzip_ratio"'  
  8. '"$request_time"';   
  9. 保存退出.   
  10.   
  11. kill -HUP PID(nginx的PID)  

 

   提醒:日志格式修改后,注意是否有相关的日志分析程序需要相应的修改

 

步骤代码
  1. 打开的nginx时志文件   
  2.   
  3. tail -fn100 /usr/local/nginx/logs/access.log  

 

    会发现在最后多了一项数据,如下图

        

表示请求/msg/replyList/msg/1/1.html   响应时间为:0.053秒

 

太好了,服务器请求时间记录下来了。

apache也可以作类似设置,有兴趣的同学可以在baidu里google一下就知道了。

 

然后,让我们的系统跑动若干时间段。

 

我们再取出日志,执行:

步骤代码
  1. cat access.log |awk  '($7~/\.html/){print $NF " " $1 " " $4 " " $7}'|sort -nr|head -100  
  2.   
  3. #意思是列出到客户端最耗时的前100个请求的html页面, (可修改,为jsp,php)分别显示响应时间  IP来源  请求发生的时间   请求页  

 

如下图

 

 

 

     说明请求/msg/msgup.html较慢,超过了6秒,太消耗资源了。

 

     经常分析日志,我们会得到一系列的这样的请求页面。

 

     找到了妨碍我们系统性能的打开较慢的并页面了,根据前辈的提到了2/8原则,我们需要对这些请求进得处理:

 

  方法一:
      分析这个请求对应的程序,是不是有很多for循环,是不是直接读库,缓存策略是否还可以优化,等等。修改程序就OK

  方法二:
     利用nginx的正则匹配转发,我们把这些弱请求统计转到其它服务器处理,分流的作用。

 

上述策略之后,我们会发现我们系统负载下来了,502更少了,页面打开更快了。

 

 

注:两分种可以当面说完的策略,写文章却花了近一个小时,希望给各位看官平时的工作带来帮助。

 

 

Web 优化(二)优化思维图:

 

Web 优化(三)反爬虫策略

反爬虫策略,表面上看似乎跟WEB系统优化没有关系,经过分析,发现该策略是可以归到WEB性能优化的系列之中。

   通过分析apache日志发现,某系统40%的带宽和服务器资源都消耗在爬虫上,如果除去10%-15%搜索引擎的爬虫,做好反爬虫策略,能节省20%-25%的资源,其实是变向优化了web系统。

一、爬虫请求与正常用户请求的区别

     爬虫请求是类似httpClient的机制或curl,wget的命令,用户请求一般走浏览器。

    区别:爬虫请求一般不会执行页面里的异步JavaScript操作,而用户请求则执行Jquery提供的异步JavaScript操作,具体如下:

  

Js代码
<script type="text/javascript">      
  1.  $(document).ready(function(){       
  2.    alertFunTest();      
  3.  }      
  4.  function alertFunTest() {       
  5.    alert(“异步”);      
  6.  }      
  7. </script >    

 

 

代码alert(“异步”)一般不会被爬虫请求执行。

 

二、分析系统有多少爬虫行为

   某系统某天的日志分析如下:

 

Shell代码
  1. cat access20110421.log | wc -l      
  2. 2156293     
  3.      
  4. cat  page_access20110421.log | sort | uniq -c | sort -nr | head -n20      
  5.  441421 /读帖页          20.4%      
  6.  374274 /弹出框          17.3%      
  7.  266984 /帖子点击数      12.3%      
  8.  213522 /读取支持数和反支持数     9.9%      
  9.  207269 /其它              9.6%      
  10.  203567 /帖子列表页      9.4%      
  11.  185138 /刷新功能          8.5%      
  12.  164884 /帖子列表点击     7.6%    

 

   如上所示,帖子点击数请求是不会被爬虫执行的。

(读帖页数-帖子点击数)/ 读帖页数=爬虫执行读帖页次数的比例

(441421 - 266984 )/ 441421=39.6%

结论:近40% 帖子的读取操作是爬虫行为,读帖占系统85%以上的操作,也就是说近1/3以上的网络和服务器资源在为爬虫服务。 

 

三、请求在不同层面对应的反抓策略

(一)防火墙层面

   通过netstat80端口的tcp连接量判断IP是否非法。

   WEB系统都是走http协议跟WEB容器连通的,每次请求至少会产生一次客户端与服务器的tcp连接。通过netstat命令,就可以查看到当前同时连接服务器所对应的IP以及连接量。

   命令  /bin/netstat -nat -n | grep 80   一般都几百或几千个。

   同一个IP对应的连接数超过我们观察到的一个阀值时,就可判断为非正常的用户请求。阀值设定至关重要,大型网吧或同一个学校、公司出来的IP也可能会被误判为非法请求。

  此策略我写了两个定时脚本去,一个定时封IP( tcpForbidCmd.sh ),一个定时释放IP ( tcpReleaseCmd.sh ),分别是每隔5分钟和40分钟各执行一次

tcpForbidCmd.sh参考代码如下:

Shell代码
  1. #!/bin/sh      
  2. file=/home/songlin.lu/shell/log/forbid-ips-tmp.log      
  3. myIps=/home/songlin.lu/shell/log/noforbid_ips.log      
  4. today=`date +'%Y%m%d'`      
  5. logForbidIp=/home/songlin.lu/shell/log/forbid-iptables-logs-$today.log      
  6. netstatFile=/home/songlin.lu/shell/log/forbid-netstat-nat-tmp.log      
  7. /bin/netstat -nat -n > $netstatFile      
  8. nowDate=`date +'%Y-%m-%d %H:%M'`      
  9. /bin/awk -F: '/tcp/{a[$(NF-1)]++}END{for(i in a)if(a[i]>90)print i}' $netstatFile > $file      
  10. drop_ip=`cat $file |awk '{print $2}'`      
  11. for iptables_ip in $drop_ip      
  12.  do      
  13.   if [ $iptables_ip != $0 ] && [ -z "` iptables -L -n | grep DROP | awk '{print$4}'|grep $iptables_ip`" ] && [ -z "` cat $myIps |grep $iptables_ip`"];then      
  14.    /sbin/iptables -A INPUT -s $iptables_ip -p tcp --dport 80 -j DROP       
  15.    echo $iptables_ip >> /home/songlin.lu/shell/log/release-forbid-logs-tmp.log      
  16.    echo '--------------------'$nowDate'----'$iptables_ip >> $logForbidIp      
  17.   fi      
  18.  done    

 

 

 

 文件/home/songlin.lu/shell/log/noforbid_ips.log为白名单列表

 

tcpReleaseCmd.sh参考代码如下:

 

 

Shell代码
  1. #!/bin/sh      
  2. today=`date +'%Y%m%d'`      
  3. logReleaseIpLog=/home/songlin.lu/shell/log/release-iptables-log-$today.log      
  4. iptables=/home/songlin.lu/shell/log/release-iptables-save-tmp.log      
  5. tmpFile=/home/songlin.lu/shell/log/release-forbid-logs-tmp.log      
  6. /sbin/iptables-save > $iptables      
  7. drop_ips=`cat $tmpFile`      
  8. nowDate=`date +'%Y-%m-%d %H:%M'`      
  9. for iptables_ip1 in $drop_ips      
  10.  do      
  11.   if [ ! -z "`cat $iptables |awk /DROP/'{print $4}' | grep $iptables_ip1`" ]      
  12.   then      
  13.    /sbin/iptables -D INPUT -s $iptables_ip1 -p tcp --dport 80 -j DROP      
  14.    echo '--------------------'$nowDate'----'$iptables_ip1 >> $logReleaseIpLog      
  15.   fi      
  16.  done      
  17. > $tmpFile    

 

 

此策略相当于给我们的系统设定了门槛,类似公路交通系统内,某马路设定限高4米栏杆,高于4米的车不能在此通行。该策略能预防恶意的或新手写的请求频率不规则的爬虫。

 

(二)WEB服务器容器层面

a.User-Agent判断      b. connlimit模块判断

     每个爬虫会声明自己的User-Agent信息,我们可以通过判断爬虫的User-Agent信息来识别,具体查看相关文档

    Apache作connlimit需要mod_limitipconn来实现,一般需要手动编译。

  编辑httpd.conf文件,添加如下配置

 

 

配置代码
  1. ExtendedStatus On      
  2. LoadModule limitipconn_module modules/mod_limitipconn.so      
  3. < IfModule mod_limitipconn.c >      
  4.       < Location / >   # 所有虚拟主机的/目录      
  5.           MaxConnPerIP  20     # 每IP只允许20个并发连接      
  6.           NoIPLimit image/*  # 对图片不做IP限制      
  7.     < /Location>        
  8. < /IfModule>   

 

 

      Nginx作connlimit,限制ip并发数,比较简单,添加limit_conn  这个变量可以在http, server, location使用  如:limit_conn   one  10;

 

(三)日志层面

   通过日志和网站流量分析识别爬虫

   用awstats分析服务器日志,用流量统计工具,如Google Analytics来统计IP对应的流量记录,流量统计在网页里面嵌入一段js代码。把统计结果和流量统计系统记录的IP地址进行对比,排除真实用户访问IP,再排除我们希望放行的网页爬虫,比如Google,百度,youdao爬虫等。最后的分析结果就得到爬虫的IP地址。

 

(四)程序层面

    时时反爬虫过滤机制

   实现起来也比较简单,我们可以用memcached或本地内存来做访问计数器,在缓存过期之前的时间段内(如3分钟),每个IP访问一次,计数器加1,缓存的KEY包括IP,通过计数器得到的值,判断超过一个阀值,这个IP很可能有问题,那么就可以返回一个验证码页面,要求用户填写验证码。如果是爬虫的话,当然不可能填写验证码,就被拒掉了,保护了后端的资源。

   阀值的设定也是很重要的,不同的系统不一样。

   我们将这个过滤机制改进一下,将更加准确。 即我们在网页的最下面添加一个JS的异步请求,此异步请求用来减计数器的值,进页面时对IP进行加值,出页面时减值,生成一个差值。 根据我们之前的分析,爬虫不会执行异步JS减值请求。 这样可以从生成的值的大小上判断这个IP是否为爬虫。

   程序逻辑如下图所示:

  

 

 

[文章作者:狂奔的鹿 本文版本:v1.0  转载请注明原文链接:http://dynamiclu.iteye.com/]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值