php session有一个GC功能,就是Garbage Collector 。这个GC启动的时候,会清除那些已经“超时 ”的session。它的工作原理是这样的(以utblog.com为例):
- 用户访问并登陆网站http://www.utblog.com ,这时候后台会调用session_start来尝试生成一个会话(如果已经有会话,则相当于一次有效会话请求)
- 对于这样的每一次有效会话请求(Request),apache的php模块会根据session相关的全局变量gc_probability/gc_divisor =>计算出启动GC的概率,并由此概率来决定在这次请求中是否应该启动GC 。举例来说,session.gc_probability的缺省值为1,session.gc_divisor的缺省值为100,则启动“垃圾回收”器的概率是1%,这就意味着在每100次请求中,会有可能清理一次过期会话
- 如果GC启动,则GC会扫描当前会话 所 在路径(session.save_path)下的所有会话文件,并根据另外一个全局变量session.gc_maxlifetime的多少来判断哪些 session已经过期(“当前时间”与“会话文件的atime或者mtime”之间的差大于gc_maxlifetime:过期),并删除这些过期的 session
- 如果你在一个session启动后,长时间没有任何交互操作(譬如,不停地码字,没有提交或者保存为草稿),那么你 的保存在后台的会话文件将得不到机会被修改或者访问,在gc_maxlifetime(缺省值1440秒=24分钟)时间后,它有可能因失效而被清理,这 以后你再提交,就会因为会话失效而报错
由此可见,gc_maxlifetime设置为24分钟,对于写某些文章来说还不够。这 是一个原因,另外,session.save_path的缺省路径在linux上是/tmp,很少有程序会修改这个设置。如果这台服务器上有多个虚拟主 机,那么,/tmp目录下会存放许多不同session_name的会话文件。糟糕的是,php的GC不区分会话归属,它会根据它取得的 gc_maxlifetime来清理这个目录下的所有过期session文件。
据以上分析,解决方案是:UTBLOG在.htaccess文件内添加了一条语句,将session.gc_maxlifetime的local value扩大为14400(4小时) ,同时在后台将session.save_path设置为/tmp/utblog,这样,utblog的会话文件就不受其他网站干扰了,而4小时 的失效时间,我想,无论如何应该够用了。
测试下来,一切如我所愿。
另, 如果直接改动/etc/php.ini当然也可以。如果没有权限改动php.ini,也没有权限改动apache的conf文件,.htaccess被禁 止,那么直接修改plog的sessionmanager.class.php文件,在session_start行前添加 ini_alter("session.gc_maxlifetime", 14400)亦可。plog结构良好,只有这一处调用session_start,所以也只有这一处需要修改。我在本地做过测试,可以工作。