做网站开发离不开缓存,缓存分好多种:服务器缓存,第三方缓存,浏览器缓存等。其中浏览器缓存是代价最小的,因为浏览器缓存依赖的是客户端,而几乎不耗费服务器端的资源。
让浏览器做缓存需要给浏览器发送指定的Http头,告诉浏览器缓存多长时间,或者坚决不要缓存。作为.net的程序员,其实我们一直都在用这种方 法,在OutputCache指令中指定缓存的Location为Client时,其实就是给浏览器发送了一个Http头,告诉浏览器这个Url要缓存多 长时间,最后修改的时间。
微软在OutputCacheModule中对这些缓存用到的Http头给我们进行了很好的封装,但是了解这些Http头可以更灵活的使用它们。
和客户端缓存相关的Http头有以下几个,分别是:
1. Expires:+过期时间
表示在指定时间后浏览器缓存失效,需要注意的是这儿的过期时间必须是HTTP格式的日期时间,其他的都会被解析成当前时间“之前”,缓存会马上过期,HTTP的日期时间必须是格林威治时间(GMT),而不是本地时间。举例:
Expires: Fri, 30 Oct 2009 14:19:41
使用Expires过期必须要求服务器的时间是正确的,否则发送的http头就会出问题,在windows服务下可以设置时间服务器来同步时间
2. Cache-control:
Cache-control直译成中文就是缓存控制,它的作用就是缓存控制,这个http头的值有几种。
1) max-age=[秒] — 执行缓存被认为是最新的最长时间。类似于过期时间,这个参数是基于请求时间的相对时间间隔,而不是绝对过期时间,[秒]是一个数字,单位是秒:从请求时间开始到过期时间之间的秒数。
2) s-maxage=[秒] — 类似于max-age属性,除了他应用于共享(如:代理服务器)缓存
3) public — 标记认证内容也可以被缓存,一般来说: 经过HTTP认证才能访问的内容,输出是自动不可以缓存的;
4) no-cache — 强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。这对于需要确认认证应用很有用(可以和public结合使用),或者严格要求使用最新数据的应用(不惜牺牲使用缓存的所有好处);
5) no-store — 强制缓存在任何情况下都不要保留任何副本
6) must-revalidate — 告诉缓存必须遵循所有你给予副本的新鲜度的,HTTP允许缓存在某些特定情况下返回过期数据,指定了这个属性,你高速缓存,你希望严格的遵循你的规则。
7) proxy-revalidate — 和 must-revalidate类似,除了他只对缓存代理服务器起作用
举例:
Cache-Control: max-age=3600, must-revalidate
很显然Cache-control可以提供比Expires更灵活的缓存控制,而且它不需要依赖于服务器时间。
在Asp.Net中微软把对Cache-control属性的设置封装到了HttpCachePolicy类中,我们可以通过Response.Cache来调用以下方法来做到对Cache-Control Http头值的控制:
Response.CacheControl;
Response.Cache.SetNoStore
Response.Cache.SetMaxAge
Response.Cache.SetProxyMaxAge
Response.Cache.SetRevalidation
3. Last-Modified/If-Modified-Since
这 两个Http头是一对,前者表示某个地址的最近更新时间,是服务器端响应给客户端的;而后者是客户端浏览器发送给服务器的,告诉web服务器客户端有一个 最后更改时间为什么时间的缓存,服务器端接收到If-Modified-Since头后则判断客户端缓存的这份url地址的缓存是否是最新的,如果是最新 的则服务器端直接给客户端返回HttpStatus 304,意思是说这个内容在你上次请求之后没有变化过,你直接用缓存就可以了;如果服务器发现url的最后更新时间比If-Modified-Since 的值要新,则会输出新的内容。
同样微软也为我们做了服务器端设置的封装,我们可以这样调用
Response.Cache.SetLastModified(DateTime)
Response.Cache.SetLastModifiedFromFileDependencies()
如果有更复杂的需求就需要自己处理了。
4. ETag/If-None-Match
ETag和Last-Modified类似,不过他发送的是一个字符串来标示url的版本,如果url变了则此标示也跟着变化,在浏览器发送If-None-Match时告诉浏览器内容已经变了,或者没变可以使用缓存。
Iis会自动给静态文件加上Etag,在文件发生改变时重新生成一个Etag,这样对于一个网站中的n多个静态文件如:样式表,小图片等,客户端只下载一次就够了,可以减轻负载。
在Asp.Net中我们可以用以下两个方法来设置
Response.Cache.SetETag(string)
Response.Cache.SetETagFromFileDependencies()
尽管微软为我们做了很多封装,但是我们还是需要详细的了解之后才可以用好这几个Http头。
Following some of the "backlash" of Google posting their "performance tips" for PHP developers, Marco Tabini has written up a post with a suggestion of his own - stop teaching developers how to optimize their code and teach them how to code it better from the start.
In principle, I have nothing against micro-optimizations; I just think they're a waste of time - perhaps even more so because they take the focus away from the simple fact that it's a rare performance problem that is cause by the language: the problem, almost inevitably, resides either with the developer, or with an external system.
He explains that it's no so much about dropping them all together as it is starting from the beginning and teaching best practices and good use of standards and proper development practices. That's what we should be promoting, not things that might shave milliseconds off the total execution time.
written by Chris Cornutt, url is :http://www.phpdeveloper.org/news/12840
在手册上看到的,原文地址为:http://cn.php.net/manual/en/function.spl-autoload.php
很吃惊,原来,在默认情况下,spl_autoload的效率并不高?
我没有测试,原文测试的时间在07年,不知道现在的效率怎么样了。以后有空的时候测试一下。。。
以下是原文:
Note that, the orders of file extensions is important for performance. You should make the priority of your favourite file extension higest or use only one extension for your class files. Check out this example:
Some class files:
ClassA.php
PHP代码
- <?php class ClassA { var $val = 'Hello from class "ClassA"'; } ?>
ClassB.php
PHP代码
- <?php class ClassB { var $val = 'Hello from class "ClassB"'; } ?>
ClassC.php
PHP代码
- <?php class ClassC { var $val = 'Hello from class "ClassC"'; } ?>
ClassD.php
PHP代码
- <?php class ClassD { var $val = 'Hello from class "ClassD"'; } ?>
ClassE.php
PHP代码
- <?php class ClassE { var $val = 'Hello from class "ClassE"'; } ?>
1. Simple:
PHP代码
- <?php
-
- for($n=65; $n<70; $n++) {
- $className = 'Class'.chr($n);
- spl_autoload($className);
- $ins = new $className;
- echo $ins->val.'<br>';
- }
-
- ?>
2. Change priority:
PHP代码
- <?php
- spl_autoload_extensions('.php,.inc');
-
- for($n=65; $n<70; $n++) {
- $className = 'Class'.chr($n);
- spl_autoload($className);
- $ins = new $className;
- echo $ins->val.'<br>';
- }
-
- ?>
Or you can use this simple function that runs a bit faster for the extensions with lower priority :)
PHP代码
- <?php
- function my_autoload($className, $extList='.inc,.php') {
- $ext = explode(',',$extList);
- foreach($ext as $x) {
- $fname = $className.$x;
- if(@file_exists($fname)) {
- require_once($fname);
- return true;
- }
- }
- return false;
- }
-
- for($n=65; $n<70; $n++) {
- $className = 'Class'.chr($n);
- my_autoload($className);
- $ins = new $className;
- echo $ins->val.'<br>';
- }
-
- ?>
---
Safak Ozpinar - Istanbul University, Computer Engineering
本来我以为是虚拟机,后来一看,原来是建多个目录。我是被人问过类似问题的。。这个到正好解决我当初被人问的问题
原文来自:http://xinsync.xju.edu.cn/index.php/archives/5134
更改第一个站点的根目录:在文件Apache2.2\conf\httpd.conf中查找 DocumentRoot 属性,将后面的路径改为你的主站点的路径,如:D:\www\web1
为第二个Apache服务建立配置文件:复制并重命名httpd.conf为web2.conf(举个例子而已,也可以叫my.conf等等), 修改web2.conf中的Listen 8080(原来为80)、ServerName localhost:8080(原来为80)、DocumentRoot “D:/www/web2″ (原来为web1)
添加第二个Apache服务:Apache安装目录的bin子目录下,使用如下命令将Apache安装为Windows NT服务:httpd.exe -k install -n “服务名” -f “d:\apache2.2\conf\web2.conf”
其他的命令:
将Apache安装为Windows NT服务:
httpd -k install
指定服务的名称,当你在同一机器上安装多个Apache服务时,你必须为它们指定不同的名字。
httpd -k install -n “服务名”
为不同名称的服务使用不同的配置文件,则安装时需要指定配置文件:
httpd -k install -n “服务名” -f “c:\files\my.conf” 如果你使用的是第一个命令,也就是除 -k install 外没有其它命令行参数,那么被安装的服务名称将是:Apache2 ,配置文件将使用conf\httpd.conf 。
移除一个Apache服务:
httpd -k uninstall
使用下述命令移除特定名称的Apache服务:
httpd -k uninstall -n “服务名”
通常,启动、重启、关闭Apache服务的方法是使用Apache Service Monitor工具,另外也可以使用控制台命令:NET START Apache2 和 NET STOP Apache2 或者通过Windows服务控制面板。在启动Apache服务之前,你应当使用下面的命令检查一下配置文件的正确性:
httpd -n “服务名” -t
你可以通过命令行开关来控制Apache服务。要启动一个已经安装的Apache服务,可以使用:
httpd -k start
要停止一个已经安装的Apache服务,可以使用:
httpd -k stop
或
httpd -k shutdown
要重启一个运行中的Apache服务,强制它重新读取配置文件,可以使用:
httpd -k restart
PHP更改文件编码应该算是比较简单的事情,在使用uchome项目(UTF-8)的时候,发现程序的编码好奇怪,有ANSI的,和UTF-8的。
很妖的是,我在ubuntu下面打开这些ansi的文件时,由于文件中含 有中文,结果全显示乱码,编码还显示为latin1。然后拷到另外一个目录,编码显示就正常了,为CP936。
由于编辑器没有批量转换功能,固此,只能使用PHP自带的功能了。。。(关键我也不会其他语言)
由于转换的时候会需要判断一下编码,如果编码本身是UTF-8的,再使用mb_convert_encoding($data,'utf-8','gbk'),反而会导致乱码。。
所以。。。就有了以下程序
慎重申明:Dir类的rmdir有BUG,请勿使用。。。。写的时候,我没有考虑太多,如果设定了某个目录,最终是会把这个目录也会删除的,而与我事先想的。把该目录下的内容清空有误差。(当然也可以在删除后重建,但毕竟不是原来的权限了。)
代码如下:
PHP代码
- <?php
-
- $dirName = "./uchome";
-
- $files = Dirs::read( $dirName , true);
-
- foreach( $files as $fileName )
- {
- if( is_file( $fileName ) && in_array(Files::extension( $fileName ) , array('php','html','htm'))){
- $fileData = Files::read( $fileName );
- $fileType = mb_detect_encoding($fileData , array('UTF-8','GBK','LATIN1','BIG5')) ;
- if( $fileType == 'CP936'){
- $fileData = mb_convert_encoding($fileData ,'utf-8' , 'gbk');
- if( Files::save( $fileName , $fileData )){
- echo "{$fileName} convert successed";
- echo "<br />";
- }
- }
- }
- }
-
-
-
-
- class Dirs
- {
- static function read ( $dirname , $recursive = false)
- {
- static $allInfo;
- $dirname .= subStr( $dirname, -1 ) == "/" ? "" : "/";
- $dirInfo = glob( $dirname . "*" );
- if ( $recursive == false ){
- return $dirInfo;
- }else{
- foreach ( $dirInfo as $info ){
- if ( is_dir( $info ) ){
- if ( !is_readable( $info ) ){
- chmod( $info, 0777 );
- }
-
- $allInfo[] = $info;
- self::read( $info , true);
- }else{
-
- $allInfo[] = $info;
- }
- }
- }
- return $allInfo;
- }
-
- static function rmdir ( $dirname )
- {
- if ( is_dir( $dirname ) && !is_writeable( $dirname ) ){
- if ( !chmod( $dirname , 0666 ) ){
- return false;
- }
- }else if ( !is_dir( $dirname ) ){
- return false;
- }
- $dirname .= subStr( $dirname, -1 ) == "/" ? "" : "/";
- $dirInfo = glob( $dirname . "*" );
- foreach ( $dirInfo as $info ){
- if ( is_dir( $info ) ){
- self::rmdir( $info );
- }else{
- unlink( $info );
- }
- }
- @rmdir( $dirname );
- }
-
- function mkdir($dir, $mode = 0777)
- {
- if (!is_dir($dir)){
- $ret = @mkdir($dir, $mode, true);
- if (!$ret){
- exit('function:mkdirs failed');
- }
- }
- return true;
- }
- }
-
- class Files
- {
- static function read ( $filename )
- {
- if ( !is_readable( $filename ) ){
- chmod( $filename, 0644 );
- }
- return file_get_contents( $filename );
- }
-
- static function create ( $filename , $mod = 0666 )
- {
- if ( @touch( $filename ) == false){
- $fp = fopen( $filename, "a+" );
- if ( $fp ){
- fclose( $fp );
- }
- }
- chmod( $filename, 0666 );
- }
-
- static function save ( $filename , $data , $append = false)
- {
- if ( !file_exists( $filename ) ){
- self::create($filename);
- $append = false;
- }
- if ( $append == false ){
- return file_put_contents( $filename , $data );
- }else{
- if ( !is_writeable( $filename ) ){
- chmod( $filename, 0666 );
- }
- return file_put_contents( $filename , $data , FILE_APPEND );
- }
- }
-
- static function delete ( $filename )
- {
- if ( !is_array( $filename ) ){
- $filenames = array($filename);
- }
- foreach ( $filenames as $filename ){
- if ( is_file( $filename ) ){
- if( !unlink( $filename ) ){
- chmod( $filename , 0666 );
- unlink( $filename );
- }
- }
- }
- }
-
- static function extension( $filename ){
- return strtolower(pathinfo( $filename , PATHINFO_EXTENSION ));
- }
- }