最近频频看到这样的文章:通过在RSS聚合器lilina的首页把全局常量(还一堆人写“全局变量”,constant和variable都不会分么?)MAGPIE_FETCH_TIME_OUT预定义为60 * 60 * 3或60 * 60 * 4,使得3个小时或4个小时才刷新一次缓存,以实现提高lilina显示速度的目的。下文把此种方法简称为“MFTO提速方法”。
这样做真能如愿吗?
第一次看到此种文章时,MAGPIE_FETCH_TIME_OUT这个常量名我看了很久,怎么都跟缓存时间挂不上钩,倒是觉得应该跟另一个东西挂钩。Time out这个词组很熟,没错,通常是远程连接时用的,因为既谓之“远程”,中间就有可能出各种意想不到的事情,导致我们发送的信息无法到达对方,或者对方试图返回的信息无法被我们接收,总之结果就是我们不能正确收到对方返回的信息。但是我们不能无限地等待对方正确返回信息,于是我们设定一个时间限制,超过了此时间(简称超时)还没有收到对方回音,就称为time out。而我们设定的限制时间也称为time out。而本地的缓存失效,应该称为expire (v.)。例如浏览器的cookie失效了,过期了,就称为expire。而且lilina的conf.php中就有以下几行:
/*
Default cache expiration is set to 1 hour.
This can be overriden by loading index.php?force_update=1
*/
define('MAGPIE_CACHE_AGE',60 * 60);难道MAGPIE_FETCH_TIME_OUT和MAGPIE_CACHE_AGE两个常量都是用来控制缓存刷新周期?
我们再继续读MAGPIE_FETCH_TIME_OUT这个常量名。fetch,想想电脑中哪里我们会用到fetch这个词。用过Unix/Linux系统的会知道fetch是一个命令,用来获取远程文件。FreeBSD的ports中还有make fetch指令用于仅获取ports的源代码及必须文件,而不进行编译安装。
现在我们连起来读意思就出来了:fetch time out,就是设定获取远程文件时的超时时间。当然对于lilina或Magpie来说,此远程文件就应该是RSS或Atom等feed文件了。
上述只是字面意思的猜测,还要有实实在在的证据。先上Magpie官方网站找一下,没有找到(也许我太粗心)。那么上Google搜一下,却发现搜出来的英文结果很多都是别人的源代码用到的Magpie部分,而中文结果都是说预定义MAGPIE_FETCH_TIME_OUT可以提高lilina的访问速度,可见其始作俑者害了多少人,而被害者又是这样的盲目和懒惰。
既然找不到官方答案或权威解释,那我们来分析一下源代码好了。首先在lilina的inc目录下找字串MAGPIE_FETCH_TIME_OUT,结果在rss_fetch.inc文件中找到3处,我们来分析一下。
if ( !defined('MAGPIE_FETCH_TIME_OUT') ) {
define('MAGPIE_FETCH_TIME_OUT', 5); // 5 second timeout
}如果未定义MAGPIE_FETCH_TIME_OUT,就定义为5,即5秒。所谓的MFTO提速方法,就是试图通过预定义MAGPIE_FETCH_TIME_OUT常量,增大其数值。但是此常量数值增大后是否能达到目的呢?我们继续看其它有MAGPIE_FETCH_TIME_OUT的地方。
if ( $resp->status == '-100' ) {
$errormsg .= "(Request timed out after " . MAGPIE_FETCH_TIME_OUT . " seconds)";
}定义超时出错信息,光看这句看不出是什么request超时。但是我们往上看一点就看到:
$resp = _fetch_remote_file( $url, $request_headers );我们可以看到$resp是获取远程文件(fetch remote file)的对象,后面这个超时,就是获取远程文件的超时了。
function _fetch_remote_file ($url, $headers = "" ) {
// Snoopy is an HTTP client in PHP
$client = new Snoopy();
$client->agent = MAGPIE_USER_AGENT;
$client->read_timeout = MAGPIE_FETCH_TIME_OUT;
$client->use_gzip = MAGPIE_USE_GZIP;
if (is_array($headers) ) {
$client->rawheaders = $headers;
}
@$client->fetch($url);
return $client;}
这第3处出现的MAGPIE_FETCH_TIME_OUT正好就在函数_fetch_remote_file中,可以看到获取远程文件要依靠一个Snoopy类。此Snoopy非彼
,如代码注释所述,此Snoopy是一个HTTP客户端。在这里用于获取远程的RSS feed文件。我们看到MAGPIE_FETCH_TIME_OUT被赋给了Snoopy类的$client实例的read_timeout属性。
接下来我们来跟踪Snoopy类的read_timeout属性是干什么的。打开lilina的extlib目录下的Snoopy.class.inc文件,可以在开头不久看到这样一行:
var $read_timeout = 0; // timeout on read operations, in seconds
// supported only since PHP 4 Beta 4
// set to 0 to disallow timeouts可见此属性的功能是设置获取远程文件超时的时间。当然还可以继续求证,方法是在此文件中查找$this->read_timeout。这里就不一一列举了,只列出一处比较关键的:
// set the read timeout if needed
if ($this->read_timeout > 0)
socket_set_timeout($fp, $this->read_timeout);这里从php手册中查一下socket_set_timeout函数就清楚了。
用类似的方法,在lilina的目录中搜索MAGPIE_CACHE_AGE,我们也可以求证MAGPIE_CACHE_AGE才是缓存的生命期,也就是缓存的刷新周期。这里就不列举详细的过程了。
总之,所谓的“MFTO提速方法”是荒谬的,预定义MAGPIE_FETCH_TIME_OUT为60 * 60 * 3,就是把获取一个RSS feed的超时时间设为3个小时,如果服务器的网速慢,或者发生了丢包,那就慢慢等它超时吧。当然php脚本默认设置是30秒超时,于是30秒后lilina也就被强制超时了。
最后说一下lilina提速两法:法一是增加常量MAGPIE_CACHE_AGE(而不是MAGPIE_FETCH_TIME_OUT)的数值以减小刷新概率;法二是生成静态缓存页面。
用户登录



