背景
突然有一天,有个客户网站打不开了,发来这样一张图片
问题排查
打开阿里云虚拟主机控制面板,CPU 使用率已经达到了100%,这说明网站已经在高负荷运转。
分析访问日志发现,网站出现了大量循环路径,其 UserAgent 为某个搜索引擎, 类似这样的访问路径:
/index.php/news/product/fuwu/fuwu/fuwu/product/about/product/about/fuwu/about/fuwu/news/product/product/product/product/news/product/product/about/product/product/news/product/news/product/news/news/public/web/js/basic.js?1699501429
这应该可以判断,因为页面中错误的路径输出,导致搜索引擎在爬取时,出现了死循环遍历,最终导致网站 CPU 占满,最终也就导致了 PHP 连接 MySQL 的连接数超限,最终导致网站打不开。
解决方案
确认了问题原因,笔者想到两个解决方案,第一当然是需要排查代码,找到输出内链的地方,一律改用绝对路径, 如 /news/product
, 避免出现相对路径,否则则可能出来循环嵌套错误, 如 news/product
。
假设这个内链出现在首页,则链接正确,但是如果出现在子页,则很容易出现路径循环嵌套,假设某个子页面为 news/detail
, 那么使用的相对路径后,这个页面中的内链在搜索引擎看来,就成了 news/detail/news/product
, 显然,这不对。
另外一个临时解决方案是,修改配置文件,禁用搜索引擎访问层级过多的页面,一旦访问,服务器返回 404
修改 .htaccess 文件,添加如下内容:
# 防止路径嵌套过深,如 /search/news/about/news/...(超过4段路径则判定非法)
RewriteCond %{REQUEST_URI} ^/(.+/){4,} [NC]
RewriteRule .* - [R=404,L]
同时,因为网站已经配置了伪静态,所以应该禁止访问 index.php/* 这样的文件
# 禁止通过 index.php/xxx 的路径访问(返回 404)
RewriteCond %{THE_REQUEST} \s/+index\.php/ [NC]
RewriteRule ^index\.php/ - [R=404,L]
修改完 .htaccess 文件后,重启虚拟主机。
最终,一切回顾了平静: