• 我所理解的session_set_save_handler的执行顺序机制


    默认的session handler启动顺序

    <?php
    
    ini_set('session.gc_maxlifetime',10);
    
    ini_set('session.gc_probability ' ,1);
    
    ini_set('session.gc_divisor',5 );
    class FileSessionHandler
    {
        private $savePath;
    
        function open($savePath, $sessionName)
        {
            $this->savePath = $savePath;
            if (!is_dir($this->savePath)) {
                mkdir($this->savePath, 0777);
            }
    
            echo __FUNCTION__."<BR>";
            return true;
        }
    
        function close()
        {
            echo __FUNCTION__."<BR>";
            return true;
        }
    
        function read($id)
        {
            echo __FUNCTION__."<BR>";
            return (string)@file_get_contents("$this->savePath/sess_$id");
        }
    
        function write($id, $data)
        {
            echo __FUNCTION__."<BR>";
            return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
        }
    
        function destroy($id)
        {
            $file = "$this->savePath/sess_$id";
            if (file_exists($file)) {
                unlink($file);
            }
            echo __FUNCTION__."<BR>";
            return true;
        }
    
        function gc($maxlifetime)
        {
            foreach (glob("$this->savePath/sess_*") as $file) {
                if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
                    unlink($file);
                }
            }
            echo __FUNCTION__."<BR>";
            return true;
        }
    
    
        function end(){
            echo '我是最后脚本结束register_shutdown_functiond调用'."<br>";
        }
    }
    
    $handler = new FileSessionHandler();
    session_set_save_handler(
        array($handler, 'open'),
        array($handler, 'close'),
        array($handler, 'read'),
        array($handler, 'write'),
        array($handler, 'destroy'),
        array($handler, 'gc')
        );
    // 下面这行代码可以防止使用对象作为会话保存管理器时可能引发的非预期行为
    register_shutdown_function(array($handler,end));
    
    
    session_start();
    $_SESSION['name']='tb';
    // session_commit();
    // session_write_close(); // 如果开启,那顺序就是open read  (gc) write close
    // session_destroy();
    // session_regenerate_id(true);
    

    运行后如下图所示:

    默认是session_start分别调用的回调函数。为open read ,然后等待脚本结束,收集$_SESSION(默认在内存中),然后关闭脚本,然后执行write,写入文件,然后close。

    改变默认session回调顺序

    那么我们使用 session_commit(); 或者 session_write_close();函数调用的时候,session的机制就改变了,直接写入文件,关闭文件。然后再执行脚本。如下图所示:

    那么session_dessory调用的时候,就是在read之后,因为只要sesson_start开启,先执行的就是open 和read。
    那么gc呢,我们都知道gc是根据 session.gc_probabilitysession.gc_divisor 参数控制。本例中我设置了他们的比例为5,但是现在的问题是我刷新5+次可能也调用不了一次gc。可能和我的win平台有关系。如果命中gc,而且没有调用 session_commit(); 或者 session_write_close();函数,运行流程如下图所示:

    在win平台的遗留问题(已经测试解决)

    ps:由于都是在win上测试,可能对gc的回收不是很准确,包括即使我设置为1:1,百分之百回收。在win上仍然存在这个sessionid文件,可能原因是session 锁机制,我在linux上测试了再分享给大家。
    该问题已经澄清,请移步php Session gc机制下在window下与ununtu是不同的。

  • 相关阅读:
    lvs持久连接及防火墙标记实现多端口绑定服务
    LVS负载均衡器DR模型的实现
    CentOS 6.5结合busybox完成自制Linux系统及远程登录和nginx安装测试
    CentOS 6.5下的lamp环境rsyslog+MySQL+loganalyzer实现日志集中分析管理
    centos中selinux功能及常用服务配置
    网站遭遇CC及DDOS攻击紧急处理方案
    centos6.5下系统编译定制iptables防火墙扩展layer7应用层访问控制功能及应用限制QQ2016上网
    centos 6.5内核编译步骤及配置详解
    centos系统初始化流程及实现系统裁剪
    iptables实现网络防火墙及地址转换
  • 原文地址:https://www.cnblogs.com/jianmingyuan/p/6074002.html
Copyright © 2020-2023  润新知