日常应用中,我们经常会在php里面用到基于文件系统直接输出一个文件的方法,例如:

 

//////////////////////////////////代码一///////////////////////////////

   \$fp = @fopen(\$src_path, "rb");

       

   if ($fp === false)

   {

            exit(“bad file”);

   }

  

  

   header("Content-Length: " . filesize($src_path));

  

   fpassthru($fp);

  

fclose($fp);

///////////////////////////代码一/////////////////////////////////////

在Linux 2.4+内核版本里面,有了一种新的文件输出方法,那就是sendfile()。在2.6内核里面升级为了 linux-aio-sendfile。Sendfile()的方法是属于内核中的操作,”能把一个文件从特定部分开始的特定块通过一个socket发送出去,从而避免了多次调用read和write的内核上下文和用户上下文切换的开销,并且由于其内部实现利用了mmap技术,也减少了内存的复制开销”,速度比文件系统层的read要快上N++倍。

在Lighttpd中,首次出现了通过程序通知服务器基于X-sendfile的方法,即:

Php程序:

        header("X-Sendfile: /data1/i_m_a_send_file.html");

Lighttpd:

        调用 Sendfile() 发送 /data1/i_m_a_send_file.html

由于lighttpd的这个特性,使得其纯静态文件服务器的性能有了一个质的飞跃。

同样上述方法在Nginx中对应的是:X-Accel-Redirect,叫法不一样,干的是同一件事情。

在apache 2.x版本中,在编译的时候,apache也会检测内核版本,然后决定是否支持sendfile()的方法,也就是说只要2.4以上的内核版本,apache 2.x里面也是支持sendfile()的。不过apache本身并没有提供给cgi任何内部接口给php使用,于是有人写了一个模块,名字就叫作  apahce 2 mod_xsendfile(http://tn123.ath.cx/mod_xsendfile/),可以让apache 2平台上通过cgi header的方法通知apache调用sendfile()去发送某一个文件,从而大大降低系统的资源消耗和提高内容传输的响应速度。

编译方法:libtool的版本为1.5.6版本

        /data1/apache/bin/apxs -i -a -c  mod_xsendfile.c

Httpd.conf 配置方法:

        LoadModule xsendfile_module   modules/mod_xsendfile.so

XSendFile on

        XSendFileAllowAbove on

使用方法:我们将代码一简化为一行:

       

        ////////////////////////代码二////////////////////////

        header("X-Sendfile: {$src_path}");

        //////////////////////代码二/////////////////////////

奇妙的Apache 2.x mod_xsendfile
标签: