最近接了一个做房产信息平台的客户,公司在成都,服务器放在杭州的IDC机房。客户说网站从上周开始明显变慢,后台文章编辑保存都要转好几秒才能保存成功,前台页面加载也经常超时,用户访问量并没有明显增加,但服务器却像老牛拉车一样吃力。
登录服务器看了下,CPU使用率一直在70%-90%之间徘徊,几乎要跑满,内存占用倒还好,还有剩余。第一反应是看访问日志,好家伙,/var/log/nginx/access.log刷得飞快,每秒钟有上百条请求记录在往下刷,看得人眼花缭乱。
仔细一看,某个IP段在持续请求 /house/detail/ 类的链接,频率非常均匀,基本每秒2-3次,一天下来就是十几万次请求,而且持续了好几天。这种请求特征太明显了,正常用户不会这么有规律地访问,这摆明了是爬虫在抓数据,而且一点不知道收敛,完全不考虑服务器的承受能力。
先临时止血
不管后面怎么规划,先把眼前的火扑灭再说。直接在nginx配置里把这个IP段封掉:
deny 123.45.67.0/24;
然后重载nginx配置,CPU使用率立刻降到了30%左右,网站访问恢复正常,客户那边马上反馈说好了。
但客户在成都的公司里,运营负责人问了一个很实在的问题:”下次换个IP又来怎么办?总不能每次都手动封吧,万一发生在半夜呢。”
这确实是个问题。爬虫程序换IP太容易了,尤其是现在代理IP池那么便宜,被动防守永远慢一步,得从架构层面做主动防护。于是做了三件事,彻底把这问题解决了。
第一招:在nginx层做频率限制
nginx自带的limit_req模块就可以做请求频率控制,不需要额外装任何东西。配置很简单:
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
location /house/detail/ {
limit_req zone=mylimit burst=20 nodelay;
proxy_pass http://backend;
}
这段配置的意思是:同一个IP每秒最多请求10次,超过的允许排队20个,再超的直接返回503。这样就算爬虫来了,大部分请求在nginx层就被拦住了,到不了后端的PHP和MySQL,服务器压力一下子就下来了。
加了频率限制之后,观察了两天,正常用户根本感觉不到影响,谁没事每秒刷新十几次页面呢?但爬虫的请求大部分被拦截,nginx日志里多了不少503状态码,那些就是被拦下来的恶意请求。
第二招:区分善意爬虫和恶意爬虫
并不是所有爬虫都是坏的。百度、搜狗、360这些搜索引擎的爬虫,如果不让他们抓,网站就不会有收录,SEO就无从谈起。客户这个房产信息平台,主要流量来源就是搜索引擎,要是把百度爬虫也给封了,那等于自断生路。
所以在做频率限制的时候,要区分User-Agent。主流搜索引擎的爬虫放宽松一点,其他未知的或者明显伪造的,限制得更严格。
配置大概是这样的:
if ($http_user_agent ~* (baiduspider|googlebot|sogou|360spider)) {
set $is_bot 0;
}
if ($http_user_agent ~* (python|curl|wget|scrapy)) {
set $is_bot 1;
}
把python、curl、wget、scrapy这类明显是脚本工具的User-Agent直接ban掉,这些基本上都是数据采集程序。搜索引擎的爬虫则单独走一套更宽松的限流规则,保证正常收录不受影响。
第三招:给搜索引擎爬虫引条专用路
光限制还不够,还要主动引导。在网站根目录的robots.txt里明确告诉搜索引擎哪些目录可以抓、哪些不能抓:
User-agent: Baiduspider Allow: / Disallow: /admin/ Disallow: /api/ User-agent: * Allow: / Crawl-delay: 1
Crawl-delay这个指令是告诉爬虫每次抓取间隔至少1秒,这对减少服务器压力很有帮助。大部分主流搜索引擎都遵守这个约定,百度、搜狗、Google都支持。
另外还顺便把sitemap提交到了百度站长平台,让搜索引擎更高效地抓取有价值的内容,而不是在那些不需要收录的目录里浪费时间。
效果怎么样
这三件事做完之后观察了一周,服务器的CPU使用率稳定在15%-25%之间,再也没有出现之前的飙升情况。客户的运营同事说”网站丝滑多了”——这位同事人在西安,远程连到杭州的服务器上操作的,全程没打过一个电话,在线沟通就解决了。这个评价在技术人员听来,比什么都高兴。
顺带做的几件事
在处理爬虫问题的过程中,顺手帮客户做了几个优化:
-
静态资源上CDN。把图片、CSS、JS这些文件切到了CDN上,房产平台的房源图片特别多,一张图几百KB,之前全走服务器带宽,流量费一个月也不少钱。加了CDN之后,客户公司成都那边访问也快了,全国各地的用户访问也快了。这就是GEO(地理位置优化)的实际应用——用户不用管节点在哪,就近加载就行了。
-
数据库加索引。查了一下MySQL的慢查询日志,发现详情页有几个查询没有索引,每次都要扫描几万行数据。加完索引之后,页面响应时间从800ms降到了150ms,变化非常明显。
-
SSL证书检查。客户的证书还有三个月到期,在宝塔面板里设置了自动续期,省得到时候忘记了网站打不开。顺便也把HTTP强制跳转HTTPS的规则检查了一遍,确保所有流量都走加密通道。
-
检查了php.ini配置。把
max_execution_time和memory_limit适当调大了一点,避免有些请求执行到一半被截断。
说回爬虫这件事
爬虫管理是很多网站站长容易忽略的问题。网站流量小的时候感觉不到,一旦内容有价值,各种爬虫就来了。有的是搜索引擎收录,有的是同行采集数据,有的纯粹是恶意扫描漏洞。房产信息、电商商品、新闻资讯、招聘信息,这些都是爬虫重点光顾的对象。
不管哪种,提前做好防护总比被打挂了再处理要强。频率限制加User-Agent识别加robots.txt引导,这三招组合起来,大部分爬虫问题都能解决。
如果您的网站也遇到类似问题,或者想提前做防护,欢迎随时沟通。服务器安全运维、环境部署、宝塔面板配置、数据库优化、CMS搭建、爬虫防护,这些我们每天都在做,有需要直接联系就行。
