网站上线时间长了,内容质量高了,越来越多的爬虫来的越发频繁了,然后问题就频频出现了。。。。
一个网站服务器,一个数据库服务器,两个独立服务器最大支持并发能支持多少,文盲并不清楚,毕竟没有专门研究过这些,但是,爬虫过来后,直接造成cpu100%的情况太恶心了,不能不处理。。。。于是文盲琢磨了一下,觉得可以尝试一下
首先是第一步:如何确定当前请求过多
嗯,开始是考虑检测cpu使用率,后来觉得不合适,于是决定使用网站的应用程序池排队的数量来作为依据
public static int IIS_QueueCount()
{
int r = 0;
Process p = new Process();
try
{
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
string cmd = @"c:\windows\system32\inetsrv\appcmd list requests";
p.StandardInput.WriteLine(cmd);
p.StandardInput.WriteLine("exit");
while (!p.HasExited)
{
p.WaitForExit(1000);
}
string output = p.StandardOutput.ReadToEnd();
string error = p.StandardError.ReadToEnd();
p.StandardError.Close();
p.StandardOutput.Close();
if (!string.IsNullOrEmpty(error))
{
LogHelper.LogMessage("Server", error);
}
else
{
r = output.Split(new string[] { "\n" }, StringSplitOptions.None).Length;
}
}
catch (Exception ex)
{
LogHelper.LogMessage("Server", ex);
}
finally
{
p.Close();
p.Dispose();
}
return r;
}
LogHelper忽视吧,用来记录异常的一个静态类
这个静态方法是模拟执行命令“c:\windows\system32\inetsrv\appcmd list requests”,来获取该指令返回的数据,这个数据就是当前在IIS应用程序池内正在处理的请求,可以打开IIS管理器,根节点,工作进程,然后打开每个应用程序池看排队队列
在获得了当前队列数量后,我们开始做一个阈值,这个阈值是自行设定的支持的并发数量
然后开始判定,当前请求是否正常响应
private bool IpFilter()
{
bool r = false;
if (Common.IIS_QueueCount() < 220)
{
return r;
}
r = true;
return r;
}
因为文盲的数据库不够强壮,部分指令相对耗时,所以文盲的网站自认为支持200个并发就差不多了,所以,先把阈值设定成220,后边再修改这个方法
然后,所有页面继承一个基类
public class BasePage : Page
{
protected override void OnLoad(EventArgs e)
{
if (IpFilter())
{
HttpStateHelper.Return502();
return;
}
base.OnLoad(e);
}
}
在请求进来之后,我们处理之前,先判断一下是否有阻塞现象,如果阻塞了,那就不再处理,直接返回502状态码,否则正常处理
嗯。。。。基本上就是这么个流程
然后,下一个问题,如何区分是蜘蛛或者正常访问
文盲使用了一个最笨的办法,那就是打开IIS日志,把里边的所有IP做了分析,并通过whois、nslookup等方法来确定IP所属,然后将IDC机房的IP做了一个IP池,当请求时的IP处于IP池内时,再判断是否有队列,否则全部正常返回
再然后,有些蜘蛛是我们所需要的,也进行放行
那么,修改上边的IpFilter方法
private bool IpFilter()
{
bool r = false;
if (!HttpStateHelper.IsSpider)
{
return r;
}
if (Common.IIS_QueueCount() < 220)
{
return r;
}
if (HttpStateHelper.IsBaidu)
{
return r;
}
r = true;
return r;
}
public static bool IsSpider
{
get
{
if (RegexExpand.IsMatch(Agent, @"spider"))
{
return true;
}
long[] spider_ip_list = new long[]
{
IPv4ToNum("38.75.137.100"), // 华盛顿Cogent通信公司
IPv4ToNum("38.108.108.178"), // 华盛顿Cogent通信公司
IPv4ToNum("45.58.125.90"), // 美国
IPv4ToNum("61.185.255.173"), // Xi'An silver fox Netbar
IPv4ToNum("66.117.9.26"), // 加利福利亚州洛杉矶Corporate Colocation公司
IPv4ToNum("69.195.137.34"), // 美国
IPv4ToNum("104.149.7.122"), // readers.popularsunglassonline-plc.club
IPv4ToNum("192.89.0.73"), // 芬兰
IPv4ToNum("192.161.85.250"), // 美国
IPv4ToNum("192.186.48.2"), // 韩国
IPv4ToNum("216.244.66.246"), // 加利福尼亚州洛杉矶Wowrack科技公司
IPv4ToNum("17.58.103.0"), // APPLE-WWNET
IPv4ToNum("23.19.69.0"), // 亚利桑那州凤凰城LeaseWeb数据中心
IPv4ToNum("23.19.70.0"), // 亚利桑那州凤凰城LeaseWeb数据中心
IPv4ToNum("23.89.139.0"), // 内华达州克拉克县亨德森市Enzu股份有限公司
IPv4ToNum("23.89.142.0"), // rdns.scalabledns.com
IPv4ToNum("36.110.147.0"), // sogou spider
IPv4ToNum("39.104.160.0"), // aliyun
IPv4ToNum("39.105.214.0"), // aliyun
IPv4ToNum("40.77.167.0"), // search.msn.com
IPv4ToNum("42.120.160.0"), // aliyun
IPv4ToNum("42.120.161.0"), // aliyun
IPv4ToNum("42.156.136.0"), // aliyun
IPv4ToNum("42.156.137.0"), // aliyun
IPv4ToNum("42.156.138.0"), // aliyun
IPv4ToNum("42.156.139.0"), // aliyun
IPv4ToNum("42.156.254.0"), // aliyun
IPv4ToNum("42.157.128.0"), // IDC 雷傲科技IDC机房
IPv4ToNum("42.236.10.0"), // 北京奇虎科技有限公司联通CDN节点
IPv4ToNum("42.236.12.0"), // 360搜索蜘蛛
IPv4ToNum("42.236.46.0"), // 360搜索蜘蛛
IPv4ToNum("42.236.54.0"), // 360搜索蜘蛛
IPv4ToNum("42.236.55.0"), // 360搜索蜘蛛
IPv4ToNum("42.236.99.0"), // 360搜索蜘蛛
IPv4ToNum("42.236.101.0"), // 360搜索蜘蛛
IPv4ToNum("42.236.102.0"), // 360搜索蜘蛛
IPv4ToNum("42.236.103.0"), // 360搜索蜘蛛
IPv4ToNum("43.239.120.0"), // Hebei HuiRi Information Technology Co. Ltd. || 河北惠日信息技术有限公司
IPv4ToNum("43.239.122.0"), // Hebei HuiRi Information Technology Co. Ltd. || 河北惠日信息技术有限公司
IPv4ToNum("45.124.124.0"), // IDC 驰联网络电信数据中心
IPv4ToNum("45.194.243.0"), // 百度蜘蛛香港IP
IPv4ToNum("46.4.96.0"), // iis server of Germany(de)
IPv4ToNum("46.229.168.0"), // bl.semrush.com
IPv4ToNum("47.89.178.0"), // aliyun
IPv4ToNum("47.89.181.0"), // aliyun
IPv4ToNum("47.92.118.0"), // aliyun
IPv4ToNum("49.4.93.0"), // compute.hwclouds-dns.com
IPv4ToNum("52.83.226.0"), // 宁夏回族自治区中卫市 BGP多线
IPv4ToNum("54.36.148.0"), // a.ahrefs.com
IPv4ToNum("54.36.149.0"), // a.ahrefs.com
IPv4ToNum("54.36.150.0"), // a.ahrefs.com
IPv4ToNum("58.87.62.0"), // 韩国
IPv4ToNum("58.87.68.0"), // 腾讯云
IPv4ToNum("60.247.77.0"), // IDC 中国数码港科技有限公司BGP节点
IPv4ToNum("62.234.79.0"), // 腾讯云
IPv4ToNum("66.249.79.0"), // google bot
IPv4ToNum("101.132.173.0"), // aliyun
IPv4ToNum("104.161.102.0"), // we.love.servers.at.ioflood.com
IPv4ToNum("106.11.152.0"), // aliyun
IPv4ToNum("106.11.153.0"), // aliyun
IPv4ToNum("106.11.154.0"), // aliyun
IPv4ToNum("106.11.155.0"), // aliyun
IPv4ToNum("106.11.156.0"), // aliyun
IPv4ToNum("106.11.157.0"), // aliyun
IPv4ToNum("106.11.158.0"), // aliyun
IPv4ToNum("106.11.159.0"), // aliyun
IPv4ToNum("106.14.197.0"), // aliyun
IPv4ToNum("106.38.241.0"), // sogou spider
IPv4ToNum("106.120.173.0"), // sogou spider
IPv4ToNum("106.120.185.0"), // IDC 北京电信互联网数据中心节点
IPv4ToNum("106.120.188.0"), // sogou spider
IPv4ToNum("107.167.77.0"), // we.love.servers.at.ioflood.com
IPv4ToNum("107.167.79.0"), // we.love.servers.at.ioflood.com
IPv4ToNum("107.189.157.0"), // we.love.servers.at.ioflood.com && www.10mvps.com
IPv4ToNum("111.202.100.0"), // sogou spider
IPv4ToNum("111.206.36.0"), // IDC 北京百度网讯科技有限公司联通节点(BGP)
IPv4ToNum("111.206.221.0"), // baidu spider
IPv4ToNum("111.230.136.0"), // tencent yun
IPv4ToNum("115.182.24.0"), // IDC 北京市 BGP多线
IPv4ToNum("115.182.25.0"), // IDC 北京市 BGP多线
IPv4ToNum("115.239.212.0"), // IDC 百度网讯科技电信节点
IPv4ToNum("119.57.158.0"), // IDC 东四机房
IPv4ToNum("119.57.159.0"), // IDC 东四机房
IPv4ToNum("119.90.61.0"), // IDC 北京市门头沟区 BGP多线
IPv4ToNum("121.52.226.0"), // IDC 诺信科技有限公司
IPv4ToNum("123.125.67.0"), // baidu
IPv4ToNum("123.125.71.0"), // baidu spider
IPv4ToNum("123.125.125.0"), // sogou spider
IPv4ToNum("123.126.68.0"), // sogou spider
IPv4ToNum("123.126.113.0"), // sogou spider
IPv4ToNum("138.201.126.0"), // webmeup.com
IPv4ToNum("140.143.183.0"), // tencent yun
IPv4ToNum("140.143.236.0"), // tencent yun
IPv4ToNum("144.76.22.0"), // clients.your-server.de
IPv4ToNum("151.80.39.0"), // ahrefs.com
IPv4ToNum("157.55.39.0"), // search.msn.com
IPv4ToNum("178.255.215.0"), // exalead.com
IPv4ToNum("180.76.15.0"), // baidu spider
IPv4ToNum("180.97.35.0"), // 北京百度网讯科技有限公司电信节点
IPv4ToNum("191.101.75.0"), // 黑森州法兰克福Host1Plus数据中心
IPv4ToNum("192.80.158.0"), // rdns.scalabledns.com
IPv4ToNum("192.168.1.0"), // wan
IPv4ToNum("207.46.13.0"), // search.msn.com
IPv4ToNum("220.181.51.0"), // baidu
IPv4ToNum("220.181.108.0"), // baidu spider
IPv4ToNum("220.181.125.0"), // sogou spider
IPv4ToNum("220.243.135.0"), // IDC 广州恒汇网络通信有限公司
IPv4ToNum("220.243.136.0"), // IDC 广州恒汇网络通信有限公司
IPv4ToNum("127.0.0.0") // local
};
for (int i = 0; i < spider_ip_list.Length; i++)
{
string ip = Common.NumToIPv4(spider_ip_list[i]);
if (RegexExpand.IsMatch(ip, @"\.0$"))
{
if (ClientIP_Num > spider_ip_list[i] && ClientIP_Num < spider_ip_list[i] + 256)
{
return true;
}
}
else
{
if (ip == ClientIP)
{
return true;
}
}
}
return false;
}
}
IsSpider方法就是用来验证访问的IP是否是IDC过来的,这个数据可以自行补充调整,然后IsBaidu和这个方法一样,不过是允许放行的IP段,IPv4ToNum就是把IP地址转换成Int64格式的数字,以方便比较
经过这么一番操作后,对数据库压力明显降低,队列池拥塞现象基本不存在了,网站服务器CPU也不会永远飚到100%了,嗯,就是需要维护,如果发现大并发请求过来,还需要自行维护IP池
再说个题外话,如果是服务器组或者购买的CDN服务的话,可以不用考虑这个办法,小公司可以尝试下