客户端:删除过期session id的cookie记录
  如果用户发现session已经过期,但是服务端的GC还没有启动,服务端可以手通过手工代码setcookie的方式要求用户端浏览器删除键值为session_name()的Cookie记录。这样,下回访问的时候,浏览器以为用户是第一次访问,并且重新给访问用户分配一个新的session_id。较好的做法类似这样:
<?php
//@file session_destroy.php
session_start();
$sess_name = session_name();
$sess_id = session_id();
list(, $path, $domain, ,) = session_get_cookie_params();
if ($sess_name &amp;&amp; isset($_COOKIE[$sess_name])) {
setcookie($sess_name, '', -1, $path, $domain);
if ($sess_id) {
session_destroy();
}
}
  抓取的http数据包如下:
#
T 192.168.0.98:2638 -< 192.168.0.8:8080 [AP]
GET /session_destroy.php HTTP/1.1..Host: 192.168.0.8:8080..Connection: keep-alive..User-Agent: Mozilla/5.0 (Windows; U;
Windows NT 5.1; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.3 Safari/533.2..Accept: application/xml,appl
ication/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5..Accept-Encoding: gzip,deflate,sdch..Accept-Langu
age: zh-CN,zh;q=0.8..Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3..Cookie: PHPSESSID=rjdtgvmueggplgqno66qlfket1....
##
T 192.168.0.8:8080 -< 192.168.0.98:2638 [AP]
HTTP/1.1 200 OK..Date: Tue, 13 Apr 2010 07:08:24 GMT..Server: Apache/2.2.3 (CentOS)..X-Powered-By: PHP/5.1.6..Expires: T
hu, 19 Nov 1981 08:52:00 GMT..Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0..Pragma: no-
cache..Set-Cookie: PHPSESSID=deleted; expires=Mon, 13-Apr-2009 07:08:23 GMT..Content-Length: 222..Connection: close..Con
tent-Type: text/html; charset=UTF-8....
##
T 192.168.0.98:2642 -< 192.168.0.8:8080 [AP]
GET /p1.php HTTP/1.1..Host: 192.168.0.8:8080..Connection: keep-alive..User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.
1; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.3 Safari/533.2..Accept: application/xml,application/xhtml
+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5..Accept-Encoding: gzip,deflate,sdch..Accept-Language: zh-CN,zh
;q=0.8..Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3....
##
T 192.168.0.8:8080 -< 192.168.0.98:2642 [AP]
HTTP/1.1 200 OK..Date: Tue, 13 Apr 2010 07:09:15 GMT..Server: Apache/2.2.3 (CentOS)..X-Powered-By: PHP/5.1.6..Set-Cookie
: PHPSESSID=lbmk3sc5a88e9cjuekr0aa9pc3; path=/..Expires: Thu, 19 Nov 1981 08:52:00 GMT..Cache-Control: no-store, no-cach
e, must-revalidate, post-check=0, pre-check=0..Pragma: no-cache..Content-Length: 11..Connection: close..Content-Type: te
xt/html; charset=UTF-8....hello world
  上面观察可以知道,通过访问/session_destroy.php,它要求客户端将session_id的Cookie记录删除。而接下来访问/p1.php的时候,http请求头没有通过Cookie将用户的session id带给服务器(因为刚被要求删除)。而第二次请求/p1.php的http响应里头可以看到,服务端又给用户重新分配了一个新的session id,而且不会继续使用过去的session数据。
  与session回收相关的php.ini设置:
  1, session.gc_probability和session.gc_divisor
  由这二个函数决定了启用GC的概率,默认是1/1000。也是说,每一千次用户请求中有一次会启动GC回收session。启动GC进程不宜过于频繁。上面的例子,我们可以看到,它会每次检查session.save_path目录下每个文件的状态。这样会降低php的执行效率。
  2, session.gc_maxlifetime = 1440
  设置session存活时间,单位是秒。每次GC启动后, 会通过stat得到session文件后访问的unix时间,通过现在时间减去文件后访问时间之间大于session.gc_maxlifetime,则会删除该文件。
  总结
  1, PHP使用Cookie的方法传递session id。尽量不要使用GET方法传递session id,因为这样很不安全。
  2, 可以通过setcookie()的方法,将客户端的session id的Cookie记录删除。
  3, PHP GC进程由session初始化启动。但不是每一次用户请求都会被启动,它的启动概率默认是1/1000。过于频繁访问的网站,并发量大的网站,可减小PHP GC的启动频率。PHP GC回收session会降低php的执行效率。
  4, 通过下面代码,优化session回收
  <?php
  session_start();
  if (isset($_SESSION['SESS_TIMEOUT'])) {
  if ($_SERVER['REQUEST_TIME'] > $_SESSION['SESS_TIMEOUT']) {
  setcookie(session_name(), session_id(), -1, '/');
  session_unset();
  session_destroy();
  }
  } else {
  $_SESSION['SESS_TIMEOUT'] = $_SERVER['REQUEST_TIME'] + 3600;
  }