构建高性能ASP.NET
站点
第六章—
性能瓶颈诊断与初步调优(下后篇)—
减少不必要的请求
前言:本篇的一些内容比较的有意思,总结了可能平时大家可以注意到的一些优化点,而且非常的实用。
本篇的议题如下:识别和分析服务端的性能瓶颈 ( 上 )内存 ( 前篇 )缓存 ( 前篇 )CPU( 后篇 )处理请求线程 ( 后篇 )提高性能的一些简单改进措施(下)部署优化 ( 前篇 )减少不必要回传 ( 前篇 )减少不必要的请求( 后篇)搜索引擎问题热链接问题验证码(CAPTCHA)网络刮刀
服务端的要处理的请求越多,无疑服务端的压力也就越大,尤其是有些请求需要访问一些比较昂贵的资源,例如数据库,服务端的文件等。但是我们必须知道,在到达服务端的请求中,有些请求时我们希望的,例如网站的用户的请求,有些请求其实是不必要,甚至是我们不想要的,为此,我们要避免这样的请求,节省服务端的资源,从而提高性能。
搜索引擎
首先来看看有关搜索引擎的问题。
然后搜索引擎爬到我们的站点是一件好的事情,很多的SEO
可以进行,推广站点。同时,在站点中,有些文件或者资源比较的私密,或者我们不希望被搜索引擎请求和收录的,因为每次搜索引擎在请求这些资源的时候,就是发送请求到我们的站点服务器,势必会加重服务器的负载。
不需要被搜索引擎请求的文件一般如下:
1.
图片资源
2.
Js
脚本,
css
等
3.
一些需要身份验证或者授权才能看的页面
(
如果页面需要验证之后才能看,搜索引擎收录了也作用不大
)
我们可以设置一下,告诉搜索引擎的蜘蛛程序如何爬我们的站点。
步骤如下:
1.
在站点的根目录下面,创建一个robots.txt
的文件。
2.
写入文件。如果我们希望阻止所有的搜索引擎来爬我们的站点的页面,那么就可以在文件中写入下面的配置:
User-agent: *
Disallow: /
如果希望阻止搜索引擎爬某个文件夹,可以配置如下:
User-agent: *
Disallow: /images/
Disallow: /js/
Disallow: /css/
Disallow: /private/
更有趣的是:对于某些搜索引擎,我们还可以改变他们的蜘蛛程序爬我们站点的频率,设置如下:
User-agent: *
Crawl-delay: 10
大家可以去上网找下一些如何影响Google
,百度等蜘蛛程序的设置。
热链接问题
就是在
A
网站上面显示一个来自
B
网站的图片链接。例如我们在自己的站点上面有一个链接如下:
<img src=”http://www.xxx.com/yyy.gif”/>
,那么在别人在浏览我们的站点的时候,就回去别人的那个站点
(
http://www.xxx.com/yyy.gif
)
去请求这个图片,那么势必会消耗他们的服务器的资源。发过来,如果别人在他们的站点上采用了我们的图片或者其他的链接资料,那么用户在浏览别人的站点的时候就会消耗我们站点的服务端资源和带宽。
为一个组件就可以阻止这种情况的发生:
h
ttp://www.iis.net/community/default.
aspx?tabid=34&i=1288&g=6.
大家去看看。
验证码(CAPTCHA)
我们常常在站点中加入一些验证码的功能来防止网络注册机。一般是生成一张有文字的图片,然后根据验证用户输入的文字和图片中的文字是否一样来判断此时的用户是人还是注册机。
通过验证码阻止了注册机随意的消耗站点资源
(
如果没有验证码,注册机可以不断的注册信息,大小服务器和数据库资源,而且产生很多的垃圾数据
)
。
网络刮刀(Scrapers)
这个问题必须引起重视。如果我们的站点上面有很多的有用的信息,那么别人可能就可能开发一个程序来到我们的站点抓取信息,然后把这些内容放到自己的站点上面。例如,很多的内容型的站点每天都从博客园的首页上面来抓取信息,然后放到他们的站点上,增加他们的访问量。
本来站点被搜索引擎抓就有点消耗性能了,如果还被很多的这样的网络刮刀来抓内容,对站点的性能影响可想而知。
如果那些网络刮刀程序的的
IP
地址变化不频繁,而且请求我们站点的频率比较的由规律,那么我们就可以采用一些代码的方式来防止这样的请求。例如,我们可以监测:同一个
IP
是否在
20min
之内发送了
100
个请求,如果是,我们就推测:可能是别人在抓我们的站点内容,我们就拒绝这个
IP
的请求。
当然了,上面只是一些简单的方法,对于一些复杂的
Dos
攻击,上面的监测代码基本没有作用。因为
Dos
攻击中,攻击的
IP
地址是变化的。
下面我们就写一些代码来防止简单的网络刮刀程序和简单的
Dos
攻击。基本的思想就是:如果在给定的时间段内,如果某个用户的请求很多,超过了一定的数量,那么我们就认为这个
”
用户
”
可能是网络刮刀程序,然后就拒绝下面的请求,一段时间之后,再次允许这个从这个
IP
发出的请求。
下面的代码中:假设如果一个用户在
5
秒之内发出了
100
个请求,那么我们就认为这是网络刮刀程序或者是网站的攻击者。当然,我们还考虑这个发送请求的
”
用户
”
是否是搜索引擎的蜘蛛程序。
(
下面的代码只是简单作为演示,不是实际生产的代码,抛砖引玉
)
private
const
int
intervalSeconds
=
30
;
private const int maxRequestsInInterval = 5 ;
private const int maxRequestsInInterval = 5 ;
如果认为这个
”
用户
”
是攻击者,那么我们就阻止用户的请求,阻止时间是
20
秒
private
const
int
blockedPeriodSeconds
=
20
;
下面,我们创建一个类来描述一个访问者的信息。如下:
![ExpandedBlockStart.gif](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif?x-oss-process=image/resize,w_1400/format,webp)
private
class
VisitorInfo
{
public int nbrHits;
public bool blocked;
public VisitorInfo()
{
nbrHits = 1 ;
blocked = false ;
}
}
{
public int nbrHits;
public bool blocked;
public VisitorInfo()
{
nbrHits = 1 ;
blocked = false ;
}
}
在
BotDefence
类中加入一个方法
IsBotAttach
来判断一个请求是否是攻击性的请求。如下:
![ExpandedBlockStart.gif](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif?x-oss-process=image/resize,w_1400/format,webp)
public
static
bool
IsDosAttack()
{
string visitorIP = HttpContext.Current.Request.UserHostAddress;
VisitorInfo visitorInfo = (VisitorInfo)HttpContext.Current.Cache[visitorIP];
if (visitorInfo == null )
{
HttpContext.Current.Cache.Insert(
visitorIP, new VisitorInfo(), null ,
DateTime.Now.AddSeconds(intervalSeconds),
System.Web.Caching.Cache.NoSlidingExpiration);
}
else
{
if (visitorInfo.blocked)
{
return true ;
}
visitorInfo.nbrHits ++ ;
if (visitorInfo.nbrHits > maxRequestsInInterval)
{
visitorInfo.blocked = true ;
HttpContext.Current.Cache.Insert(
visitorIP, visitorInfo, null ,
DateTime.Now.AddSeconds(blockedPeriodSeconds),
System.Web.Caching.Cache.NoSlidingExpiration);
return true ;
}
}
return false ;
}
{
string visitorIP = HttpContext.Current.Request.UserHostAddress;
VisitorInfo visitorInfo = (VisitorInfo)HttpContext.Current.Cache[visitorIP];
if (visitorInfo == null )
{
HttpContext.Current.Cache.Insert(
visitorIP, new VisitorInfo(), null ,
DateTime.Now.AddSeconds(intervalSeconds),
System.Web.Caching.Cache.NoSlidingExpiration);
}
else
{
if (visitorInfo.blocked)
{
return true ;
}
visitorInfo.nbrHits ++ ;
if (visitorInfo.nbrHits > maxRequestsInInterval)
{
visitorInfo.blocked = true ;
HttpContext.Current.Cache.Insert(
visitorIP, visitorInfo, null ,
DateTime.Now.AddSeconds(blockedPeriodSeconds),
System.Web.Caching.Cache.NoSlidingExpiration);
return true ;
}
}
return false ;
}
上面的代码都是自解释的,很容易看懂,就不赘述了。
当然了,上面的代码很简单,我们可以保存每个请求
IP
的地址,然后分析。相关的方法网络上面有很多,大家自己找!
本篇就到这里了。下一章就详细的讲述如何解决内存的性能瓶颈,敬请关注。
本文转自yanyangtian51CTO博客,原文链接:http://blog.51cto.com/yanyangtian/494683
,如需转载请自行联系原作者