PHP大型Web应用入门(三)

PHP大型Web应用入门(三)

 

接上一篇:还是郁字符长度的限制。
早期版本的PHPWIND论坛的cache机制是很差的,虽然它很快,但是很脆弱,一旦cache文件损坏或丢失,它不会自己去创建它,而是直接导致程序无法运行,这种只能叫做临时文件,而不能叫cache。我不知道现在的PHPWIND什么样,因为我一直没兴趣去看它……
    
    下面的部分是mSession的实现,它只是模拟了session的存取过程,并对系统session进行了改进。它用了Hash目录。它的缺点是在程序结束部分还要Rewrite一下,把数据更新到session文件里,当然这个很容易被改进。

 

< ? php
class  BsmSession
{
    var  $ sid ;
    var  $ sess_file ;
    
    function  mSession_Start ( )
    {
        // Special Function...session_start()

        global  $ cookie_sess_id_varname ,  $ cookie_path ,  $ sess_liftime ,  $ mSession ;
        
        $ sid  =  $ _COOKIE [ $ cookie_sess_id_varname ]  ?  $ _COOKIE [ $ cookie_sess_id_varname ]  :  $ this - > _Gen_Sid( ) ;
        setcookie  ( $ cookie_sess_id_varname ,  $ sid ,  $ sess_liftime ,  $ cookie_path ) ;
        
        $ sess_file  =  $ this - > _Hash_Dir( $ sid )  .  'sess_'  .  $ sid ;
        
        if  ( file_exists  ( $ sess_file ) )  {
            if  ( ! @ $ fp  =  fopen  ( $ sess_file ,  'rb' ) )  {
                // Debug Info...No Log.

                fatal_error ( 'Session Error...' ) ;
            }
            
            if  (= =  ( $ fl  =  filesize  ( $ sess_file ) ) )
                $ sess_content  =  '' ;
            
            else
                $ sess_content  =  fread  ( $ fp ,  $ fl ) ;
        }
        else  {
            if  ( ! @ $ fp  =  fopen  ( $ sess_file ,  'wb' ) )  {
                // Debug Info...No Log.

                fatal_error ( 'Session Error...' ) ;
            }
            
            $ sess_content  =  '' ;
        }
        
        fclose  ( $ fp ) ;
        
        $ this - > sid =  $ sid ;
        $ this - > sess_file =  $ sess_file ;
        
        $ mSession  =  unserialize ( $ sess_content )  or  $ mSession  =  array  ( ) ;
    }
    
    function  mSession_Destroy  ( )
    {
        global  $ mSession ;
        
        $ mSession  =  array  ( ) ;
        return  @ unlink  ( $ this - > sess_file) ;
    }
    
    function  mSession_Rewrite ( )
    {
        // Restore Session Data into Session File

        global  $ mSession ;
        
        $ sess_content  =  serialize ( $ mSession ) ;
        
        if  ( ! @ $ fp  =  fopen  ( $ this - > sess_file,  'wb' ) )  {
            // Debug Info...No Log.

            fatal_error ( 'Session Error...' ) ;
        }
        
        fwrite  ( $ fp ,  $ sess_content ) ;
        fclose  ( $ fp ) ;
        
        return ;
    }
    
    function  _Hash_Dir ( $ sid )
    {
        // Hash the Session file Dir

        
        global  $ user_sess_base_dir ;
        
        $ sess_dir  =  $ user_sess_base_dir  .  substr  ( $ sid ,  0,  1)  .  '/'  .  substr  ( $ sid ,  16,  1)  .  '/' ;
        return  $ sess_dir ;
    }
    
    function  _Gen_Sid ( )
    {
        // Gen an Unique Session ID

        
        $ key_1  =  rand  ( 32768,  65535) ;
        $ key_2  =  microtime  ( ) ;
        $ key_3  =  sha1  ( time  ( ) ) ;
        
        $ sid  =  md5  ( $ key_1  .  $ key_3  .  $ key_2 ) ;
        
        return  $ sid ;
    }
    
    function  _Get_Sid ( )
    {
        // Get Current Session ID

        global  $ cookie_sess_id_varname ;
        
        $ sid  =  $ _COOKIE [ $ cookie_sess_id_varname ]  ?  $ _COOKIE [ $ cookie_sess_id_varname ]  :  FALSE ;
        return  $ sid ;
    }
}
? >

    Hash目录是一种优化文件存储性能的方法。无论是Windows还是Linux,无论是NTFS还是ext3,每个目录下所能容纳的项目数是有限的。并不是不能保存,而是当项目数量过大的时候,会降低文件索引速度,所以权衡一个目录下应该保存多少文件是很必要的。保存得多了会影响性能,保存得少了会造成目录太多和空间浪费。所以当保存大批文件的时候,需要有一种算法能将文件比较均匀地“打散”在不同的子目录下以提高每一级的索引速度,这种算法就是 Hash。通常用的MD5、sha1等都可以用来做Hash目录,我的mSession里也同样使用了MD5,取得sessionID的第一位和第九位,这就构成了两级Hash路径,也就是说,系统把所有的Session文件分散到了16×16=256个子目录下。假设Linux每个目录下保存1000个文件可以获得最好的空间性能比,那么系统在理想情况下可以同时有256000个session文件在被使用。
    Hash目录还被广泛应用在备份、图库、电子邮件、静态页生成等文件密集型应用上。
    
    再来点一下我的模板类,我很懒地保留了Discuz模板函数的所有标签。一方面是我确实很懒,另一方面是我曾经试图修改Discuz,把它改成一个专用的版本,不过这是一个类,它的使用方法和Discuz函数没什么两样,都是include一个parse结果返回的文件名。
    所不同的是在处理{template}标签的时候。Discuz的处理方式是把{template}替换成再次调用模板解析函数去解析另一个模板文件,这样,模板函数可能会被调用多次,编译的结果里也会有很多include另一个模板文件Parse结果的地方。这里涉及另一个优化点——尽量少地 include文件。过多地include会带来更多的IO开销和CPU处理开销,所以我把{template}改成直接读入文件内容,然后再 parse。这样一个模板文件即使有1000个{template},编译的结果也只有一个文件。
    这个模板类用起来是如此地简单方便,更重要的是,它确实很快~~呵呵,我从来不否认我有时候也会做一些比较有用的事,哈哈:

阅读全文>>

你可能感兴趣的:(PHP大型Web应用入门(三))