导语:对WordPress站点的优化能做基本上都做了,Opcache+Memcached,零插件。于是想起了CDN,想自己来搭建一个免费的。其实也可以用七牛等免费的CDN,但作为写代码的人,总喜欢折腾。
在网络上找到免费资源部落的文章,发现了一个叫做LayerCDN,可以实现本地缓存,到作者的github上把它下载下来。
免费资源部落文章:https://www.freehao123.com/cdn-layer/
LayerCDN下载网址:https://github.com/oott123/Layer
LayerCDN安装报错
修改它的配置文件config.sample.inc.php,基本上没有什么改动的,因为我要本地缓存,所以在高级设定里将RUN_ENV前面的双斜杠去掉,然后将定义改为“’LOCAL’”。
config.sample.inc.php:
//Layer CDN 设定 /**********基本设定**********/ define('STATIC_URL','http://www.baidu.com/'); //源站URL define('DOMAIN','cdn'); //使用云存储时,填写存储空间的名字;使用本地存储时,填写存储的相对路径。 define('WELCOME_DOC',TRUE); //空请求时是否显示欢迎界面 /*********防盗链设定*********/ define('ALLOW_REGX','.*'); //设置防盗链允许的[域名]正则表达式,此表达式只匹配referer的域名部分 //define('ALLOW_REGX','^(best33\.com|.*\.best33\.com|)$'); //允许best33.com,*.best33.com,浏览器直接访问 //define('ALLOW_REGX','^(best33\.com|.*\.best33\.com)$'); //允许best33.com,*.best33.com,不允许浏览器直接访问 //define('ALLOW_REGX','^(.*)$'); //允许任意,允许浏览器访问 //define('ALLOW_REGX','^(.+)$'); //允许任意,但不允许浏览器访问 /**********进阶设定**********/ define('PURGE_KEY','purge'); //刷新缓存的密码,访问http://domain/PURGE_KEY/path/to/file来刷新缓存。 define('MIME','text/html'); //默认MIME类型,可以设为application/octet-stream则对未知项目自动弹出下载。 define('DIRECT_EXT','php|asp|htm|html'); //不进入缓存的扩展名,安全起见不要删除PHP。 define('NO_LOCATE',true); //设置后将不进行跳转而采用read读取方式,可能会降低速度并增加流量。仅当遇到问题时启用。 define('NO_KEY',true); //启用后将不再使用一串md5编码的key作为文件名,当想保持文件名一致时启用之。 define('NO_SECOND_FLODER',true); //启用后将不再使用两层文件夹存储缓存,仅在本地环境、NO_KEY为假时有效。 define('STATIC_HOST',''); //可以留空,也可以在这里填写你的源站域名,而在STATIC_URL中填写IP,减少域名解析的时间。 /**********高级设定**********/ define('RUN_ENV', 'LOCAL'); //自定义运行环境(如不去掉前面的//则自动判断)可选:BAE/SAE/GCS/LOCAL 请大写 //define('CS_AK','dummy'); //自定义云存储空间的Access Token,通常不需要 //define('CS_SK','dummy'); //自定义云存储空间的Secret Token,通常不需要
上传到资源服务器,然后就看到了安装成功的提示,以为万事大吉,没想到这是个开始,我猜中了开头没有猜中结局。
将测试缓存文件,发现它传送过来的JS\CSS文件全部都是文本格式的,然后在服务器上,只在空间里建立了目录,根本没有保存文件。这是什么鬼,想偷一下懒不行,只能老老实实地一行一行地读代码。
代码给我们快乐呀,随便说一句,php是世界上最好的语言。:)
不服气,来辩呀。写文章很无聊,所以逗个乐子,特别是刚刚写了一半的文章因为网络问题保存失败丢失,又要开始重写,想死的心都有了。
:(
修正LayerCDN的BUG过程
带问号的文件名
当读到controller.php时发现了问题,它是截取扩展名来获取文件类型的,但这里有一个BUG,只支持标准格式的文件扩展名,例如:.png。如果遇到那种扩展名后面带问号的地址,它截取的扩展名就变成了:.js?ver=4。这样的扩展名会导致程序在识别MIME TYPE的时候出错。而现在的js、css基本上都会带上问号。那么知道问题所在了,就修改。
修改controller.php:
$ext = strtolower(substr($basename,strrpos($basename,'.')+1)); //解决有带问号的扩展名导致文件类型错误的问题,查找问号第一次出现的位置。 $ext_qm = strpos($ext,'?') ? substr($ext,0,strpos($ext,'?')) : $ext ;
利用函数将问号前面的扩展名分离出来,这样就获得了正确的扩展名。
万事大吉了么?少年,你太天真了,这样的分离办法只能对应一种情况:.js?ver=4。对于这种:.css?ver=4.3.4,那么截取出来的扩展名就变成了:.4。
所以要从根本上解决问题,就要先分离问号。
修改controller.php:
$request = strpos($request,'?') ? substr($request,0,strpos($request,'?')) : $request ;
这样先分离问号后,在利用扩展名获得文件类型。这时,缓存服务器传送过来的文件类型终于正确了。网页可以正常加载。
问题解决了么?没有。
返回目录路径出错
分离问号后获得文件类型虽然正确了,但是缓存服务器并没有存储文件,每次请求都是从主服务器获取的。好吧,继续来读代码。
不能在缓存服务器上保存文件,意味着写出了问题。
读到Local.php的写函数:
public function write($filename,$content){ return file_put_contents($this->get_file($filename),$content); }
它进行了一次调用,继续往下读,找到了问题出在这里:
if(NO_KEY || NO_SECOND_FLODER){ $dir = dirname($this->data_dir.$key); if(!is_dir($dir)){ if(!mkdir($dir,0777,true)) die(json_encode(array('error'=>'cannot_make_dir'))); } if(!$pre) return $key; return $dir.$key; }
这个return返回路径有问题,等于把路径加了两次,导致错误,例如它返回的是:/leaf/wp-content/themes/wordpressleaf/wp-content/themes/wordpressleaf/style.css,其实应该是:/leaf/wp-content/themes/wordpressleaf/style.css。
修改Local.php
return $this->data_dir.$key;
好了,这样就能正确地获取文件,正确地写入文件了。完全没有问题了?
No,请继续看。
返回url重定向出错
我们可以看到,当第一获取文件后,会正确地返回文件,同时在缓存服务器里正确地写入文件,问题来了。当第二次获取文件时,URL就会发生重定向,导致文件获取失败。
例如,正确的ur:http://static.wordpressleaf.com/wp-content/themes/wordpressleaf/style.css。
它却跳转为:http://static.wordpressleaf.com/wp-content/themes/wordpressleaf/leaf/wp-content/themes/wordpressleaf/style.css。
Why?
这又是哪里有错了。宝宝心好累。
我先将配置文件config.sample.inc.php里的NO_LOCATE改为true,这样它会以本地read的方式来访问文件,看看是否报错。
define('NO_LOCATE',true); //设置后将不进行跳转而采用read读取方式,可能会降低速度并增加流量。仅当遇到问题时启用。
设置后,缓存文件完全没有问题。
那就出现在url跳转方面,找到下面的语句:
public function url($filename){ return rtrim(DOMAIN,'/').'/'.$this->get_file($filename,false); }
修改为:
public function url($filename){ return '/'.rtrim(DOMAIN,'/').'/'.$this->get_file($filename,false); }
这样url方式访问就没有问题了。
但我不知道我这种方式是否百分百的正确,所以我就干脆用read方式来读了。那位达人可以指点一下,我的本意是要这个‘/’代表SERVER[“HTTP_HOST”] ,这样用是否百分百的正确,还是要用其他的方法?
好了,基本上本地phpCDN就没有问题了。
但在实际使用中还有一些小的问题,比如,会生成很多无缘无故的目录,无缘无故是指在别人攻击时,它会安装攻击的网址来生成一些目录,或许要加上验证才行。
那都是下一步代码工作了。
结束
这个LayerCDN,我在github上创建了一个分支,并改名为LayerLocalCDN,专注修改本地化的缓存代码。如果你感兴趣,可以在githubLayerLocalCDN下载它。或者访问这里查看它的介绍。
然而依然无法在php空间中使用,更改源站URL之后又该怎么办,没有反应啊
我自己用是服务器,没有问题。如果是空间的理论上是没有问题的,具体要你是怎么设置。这个使用是需要源站和CDN站两个站来一起设置才会有效的,源站把静态资源的域名改为指向CDN站的域名,然后CDN站需要设置源站的域名。这样打开网页时,静态资源是从CDN站读取,CDN站又从源站缓存过来的。
你好我下载了,打开INDEX.PHP是空白的。不知道如何使用。能讲一下流程吗
直接用nginx的缓存代理不就好了??
404,,都用不了