php的session实现

    对于两次http请求,如果第一次http请求的重要数据要被第二次请求获取,办法是将第一次http请求数据保存下来,保存的办法很多,大体上有使用数据库,缓存,文件等等,那么php中的session实现实际上就是用文件保存http请求的重要数据,我们这里先看看php的session的实现

 

1、我们先看一下浏览是否有我们测试服务器的cookie信息,如果有,先移除掉。

 

 

2、我们开始一个非常简单的php脚本,从浏览器发起请求。

<?php
session_start();

if(isset($_SESSION["name"])) {
    echo $_SESSION["name"];
}
else {
    echo "name set";
    $_SESSION["name"] = "Tom";
}

 

3、我们在服务器端抓包看一下浏览器发送给web服务器的数据包,可以看到在删除我们测试服务器的cookie信息后,发送过去的http头不再带有cookie信息。

 
4、web服务器在处理后,会将请求信息转给php处理,php处理后会在response 头上增加 Set-Cookie:PHPSESSID=xxxxxxxx ,而后web服务器会把请求头转给浏览器,浏览器在收到Set-cookie要求后,会在客户端增加cookie信息,也就是我们第一步中删除的cookie信息
 
 
5、而后,只要cookie信息存在,从浏览器发出的请求都会把cookie信息作为参数发送给web服务器,而后到php,我们再请求一次,可以抓包看到。
 
 
6、前面第四步,我们看到php在response头上要求浏览器Set-Cookie,那么PHP在服务端做了什么,我们可以看看php调用了哪些系统函数,至于详细的实现过程,可以参考php的源码。我们看看下图,php打开一个文件/tmp/sess_84uv4bfgrngrgr1285s8a9d8a6文件,实际上这里分成两步,第一步,就是php在服务端,先生成一个唯一的id也就是sess_84uv4bfgrngrgr1285s8a9d8a6,以这个id为文件名,在/tmp/目录下生成一个文件;第二步,将id作为浏览器和服务端通信的一个标识,保存在浏览器的cookie信息里面。
open("/tmp/sess_84uv4bfgrngrgr1285s8a9d8a6", O_RDWR|O_CREAT, 0600) = 5
flock(5, LOCK_EX)                       = 0
fcntl64(5, F_SETFD, FD_CLOEXEC)         = 0
fstat64(5, {st_mode=S_IFREG|0600, st_size=15, ...}) = 0
lseek(5, 0, SEEK_SET)                   = 0
read(5, "name|s:3:\"Tom\";", 15)        = 15
chdir("/usr/local/sina_mobile/php/sbin") = 0
clock_gettime(CLOCK_MONOTONIC, {870988, 244632423}) = 0
times({tms_utime=0, tms_stime=1, tms_cutime=0, tms_cstime=0}) = 516512946
brk(0xa174000)                          = 0xa174000
brk(0xa1b4000)                          = 0xa1b4000
brk(0xa134000)                          = 0xa134000
lseek(5, 0, SEEK_SET)                   = 0
write(5, "name|s:3:\"Tom\";", 15)       = 15
close(5)                                = 0

 这里面还看见了tmp文件下session内容的存储格式,我们设置的name值为Tom,存储在文件下,是 name|s:3:"Tom";

 
6、session使用文件的形式存储是存在缺陷的,我们知道在处理并发比较大的请求的时候,一般有多台前端机,使用文件形式将不能实现session共享,一般情况下会使用memcache缓存来实现session共享。下面是网上摘录的实现session共享的memcache配置方式;

     方法I: 在 php.ini 中全局设置
         session.save_handler = memcache
       session.save_path = "tcp://127.0.0.1:11211"
     
              方法II: 某个目录下的 .htaccess :
      php_value session.save_handler "memcache"
      php_value session.save_path  "tcp://127.0.0.1:11211"
    
     方法III: 再或者在某个一个应用中:
      ini_set("session.save_handler", "memcache");
      ini_set("session.save_path", "tcp://127.0.0.1:11211");  使 用多个 memcached server 时用逗号","隔开,并且和 Memcache::addServer() 文档中说明的一样,可以带额外的参数"persistent"、"weight"、"timeout"、"retry_interval" 等等,类似这样的:"tcp://host1:port1?persistent=1&weight=2,tcp://host2:port2" 。
如果安装的PECL是memcached(使用libmemcache库的那个),则配置应为
ini_set("session.save_handler", "memcached"); // 是memcached不是memcache
ini_set("session.save_path", "127.0.0.1:11211"); // 不要tcp:
 
 
 
结论:
  介绍了php对session的大体实现过程,其实里面也可以看出session的问题,session局限于单服务器。 对于一个php应用部署到多台服务器,那么每次访问可能会到不同服务器上,那么就会造成session数据的不一致,目前有些采用memcache来实现session共享,实际上也是对php的session功能的否定。
 
 
 
 
 

 

posted @ 2015-06-23 18:02  壹木人  阅读(261)  评论(0编辑  收藏  举报