即使session_save_handler被自己的类或者方法重写,write与read的出入数据都还是被序列化的,而且被session序列化不是一般的序列化...还是不能解解决memcached保存session数据为json的格式。

貌似php_memcached扩展有个option是可以选择序列化方式的有json方式的选项,这个还没试过,就怕只有是test|s:4:"data"中右边的部分json编码,再就是自己实现session的过程。。。

session被重新handler后的执行session_start的顺序:

在类析构函数里执行session_write_close函数

open
read--eke723bndobd24jhtn4sivb1i6
gc(有一定的概率执行)
write--eke723bndobd24jhtn4sivb1i6,
close

执行:$_SESSON['test']='data';$_SESSION['test2']=2;赋值操作:

open
read--eke723bndobd24jhtn4sivb1i6
------------------
write--eke723bndobd24jhtn4sivb1i6,--test|s:4:"data";test2|i:2;
close
不管session被赋值几次,都只有一次读取和写入操作。

执行:echo $_SESSION['test'];echo $_SESSION['test2'];

open
read--eke723bndobd24jhtn4sivb1i6
------------------
12 write--eke723bndobd24jhtn4sivb1i6,--test|i:1;test2|i:2;
close

读取之后也要最后写入一次。即使没有session写操作。

附上session_save_handler类:

class Cache_Session_Handler
{
public $_memcache;
public function __construct()
{
$this->_memcache = new Memcache;
$this->_memcache->addServer(
'192.168.11.23', 11211, 1
);
session_set_save_handler(
array($this, "open"),
array($this, "close"),
array($this, "read"),
array($this, "write"),
array($this, "destroy"),
array($this, "gc")
);
} public function open()
{
echo "open<br/>";
$this->_lifetime = ini_get('session.gc_maxlifetime');
return TRUE;
} public function read($id)
{
echo "read--{$id}<br/>";
$data = $this->_memcache->get($id);
return $data;
} public function write($id, $data)
{
echo "write--{$id},--{$data}<br/>";
$ttl = 1200;
//var_dump($data);
$result = $this->_memcache->replace($id, $data, 0, $ttl);
if($result === FALSE)
{
$result = $this->_memcache->add($id, $data, 0, $ttl);
}
return $result;
} public function destroy($id)
{
echo "destory--{$id}<br/>";
return $this->_memcache->delete($id);
} public function gc()
{
echo "gc<br/>";
return TRUE;
} public function close()
{
echo "close<br/>";
return TRUE;
} public function __destruct()
{
//session_write_close();
}
}
new Cache_Session_Handler();
session_start();

自己实现的session的功能,借用session_start产生cookie,也可以手动生成session_id自己控制cookie。

<?php
Class Usession
{
public static $userdata;
public static $destruct = true;
public $memObj;
public $session_name;
public $session_id;
public $sess_match_ip=false;
public $sess_match_useragent=false;
public $now;
public $config_session = array(
'cookie_prefix' => "",
'cookie_domain' => ".mypharma.com",
'cookie_path' => "/",
'cookie_secure' => FALSE,
'cookie_httponly' => FALSE, 'sess_cookie_name' => 'mphsess',
'sess_expiration' => 0,
'sess_expire_on_close' => true,
'sess_memcached_ttl' => 864000,
'sess_match_ip' => TRUE,
'sess_match_useragent' => TRUE,
); private static $_instance; protected $_memcache_conf = array(
'default' => array(
'default_host' => '127.0.0.1',
'default_port' => 11211,
'default_weight' => 1
)
); public static function getInstance($params = array())
{
if(! (self::$_instance instanceof self) )
{
self::$_instance = new self($params);
}
return self::$_instance;
} private function __clone()
{
} private function __construct($params = array())
{
include_once __DIR__."/config_memcached.php";
$this->set_config($config_session,$_memcache_conf);
$this->now = time();
$this->mem_create();
$this->session_name = $config_session['sess_cookie_name'].'_id';
$this->session_id = isset($_COOKIE[$this->session_name]) ? $_COOKIE[$this->session_name] : null;
if(empty($params)){
$this->sess_create();
}
} public function set_config($config_session,$_memcache_conf)
{
if(!empty($config_session) AND is_array($config_session))
{
foreach($config_session as $k => $v){
$this->config_session[$k] = $v;
}
}
if(!empty($_memcache_conf) AND is_array($_memcache_conf))
{
$this->_memcache_conf = null;
foreach($_memcache_conf as $k => $v){
$this->_memcache_conf[$k] = $v;
}
}
} public function set_session_id($session_id)
{
$this->session_id = $session_id;
//$this->set_session_cookie(true,true);
} public function sess_check()
{
// Is the session data we unserialized an array with the correct format?
if ( ! is_array(self::$userdata) OR ! isset(self::$userdata['session_id']) OR ! isset(self::$userdata['ip_address']) OR ! isset(self::$userdata['user_agent']) OR ! isset(self::$userdata['last_activity']))
{
$this->sess_destroy();
return FALSE;
} // Does the IP Match?
if ($this->sess_match_ip == TRUE AND self::$userdata['ip_address'] != $this->ip_address())
{
$this->sess_destroy();
return FALSE;
} // Does the User Agent Match?
if ($this->sess_match_useragent == TRUE AND trim(self::$userdata['user_agent']) != trim(substr($this->user_agent(), 0, 120)))
{
$this->sess_destroy();
return FALSE;
} return TRUE;
} public function set_session_cookie($flag=true,$isset=false)
{
$secure = (bool) $this->config_session['cookie_secure'];
$http_only = (bool) $this->config_session['cookie_httponly']; if ($this->config_session['sess_expiration'] !== FALSE)
{
$expire = ($this->config_session['sess_expire_on_close'] == true) ? 0 : $this->config_session['sess_expiration']+time();
} if ($this->config_session['cookie_path'])
{
$path = $this->config_session['cookie_path'];
} if ($this->config_session['cookie_domain'])
{
$domain = $this->config_session['cookie_domain'];
}
$cookieA = array(
'name' => $this->session_name,
'value' => $isset ? $this->session_id:uniqid("mph_",true),
'expire' => $flag ? $expire : time()-3600,
'domain' => $domain,
'path' => $path,
'secure' => $secure,
'httponly'=>$http_only,
);
$this->set_cookie($cookieA);
$this->session_id=$cookieA['value'];
} public function sess_read()
{
self::$userdata = json_decode($this->memObj->get($this->session_id),true);
}
// -------------------------------------------------------------------- /**
* Write the session data
*
* @access public
* @return void
*/
public function sess_write($array)
{
foreach($array as $k => $v){
self::$userdata[$k]=$v;
}
$data = json_encode(self::$userdata);
if (get_class($this->memObj) === 'Memcached')
{
return $this->memObj->set($this->session_id, $data, $this->config_session['sess_memcached_ttl']);
}
elseif (get_class($this->memObj) === 'Memcache')
{
return $this->memObj->set($this->session_id, $data, 0, $this->config_session['sess_memcached_ttl']);
}
return FALSE;
} // -------------------------------------------------------------------- /**
* Create a new session
*
* @access public
* @return void
*/
public function sess_create()
{
if($this->session_id == null)
{
$this->set_session_cookie();
$this->init_data();
}
$this->sess_read();
if($this->sess_check() === false){
$this->set_session_cookie();
$this->init_data();
}
} // -------------------------------------------------------------------- /**
* Destroy the current session
*
* @access public
* @return void
*/
public function sess_destroy()
{
self::$userdata = array();
self::$destruct = false;
$this->memObj->delete($this->session_id);
return $this->set_session_cookie(false);
} public function userdata($key='')
{
if(empty($key)){
return self::$userdata;
}
if(isset(self::$userdata[$key])){
return self::$userdata[$key];
}else{
return null;
}
} public function set_userdata($key,$val='')
{
if(is_array($key)){
foreach($key as $kk => $vv){
self::$userdata[$kk]=$vv;
}
}else{
self::$userdata[$key]=$val;
}
} protected function init_data()
{
$array['session_id'] = $this->session_id;
$array['ip_address'] = $this->ip_address();
$array['user_agent'] = substr($this->user_agent(), 0, 120);
$array['last_activity'] = $this->now;
$this->sess_write($array);
} protected function mem_create()
{
if (class_exists('Memcached', FALSE))
{
$this->memObj = new Memcached();
}
elseif (class_exists('Memcache', FALSE))
{
$this->memObj = new Memcache();
}
else
{
log_message('error', 'Failed to create object for Memcached Cache; extension not loaded?');
return FALSE;
} foreach ($this->_memcache_conf as $name => $cache_server)
{
if ( ! array_key_exists('hostname', $cache_server))
{
$cache_server['hostname'] = $this->_memcache_conf['default']['default_host'];
} if ( ! array_key_exists('port', $cache_server))
{
$cache_server['port'] = $this->_memcache_conf['default']['default_port'];
} if ( ! array_key_exists('weight', $cache_server))
{
$cache_server['weight'] = $this->_memcache_conf['default']['default_weight'];
} if (get_class($this->memObj) === 'Memcache')
{
// Third parameter is persistance and defaults to TRUE.
$this->memObj->addServer(
$cache_server['hostname'],
$cache_server['port'],
TRUE,
$cache_server['weight']
);
}
else
{
$this->memObj->addServer(
$cache_server['hostname'],
$cache_server['port'],
$cache_server['weight']
);
}
}
return TRUE;
} public function __destruct()
{
if(self::$destruct){
$data = json_encode(self::$userdata);
if (get_class($this->memObj) === 'Memcached')
{
return $this->memObj->set($this->session_id, $data, $this->config_session['sess_memcached_ttl']);
}
elseif (get_class($this->memObj) === 'Memcache')
{
return $this->memObj->set($this->session_id, $data, 0, $this->config_session['sess_memcached_ttl']);
}
}
} // -------------------------------------------------------------------- /**
* Does nothing for native sessions
*
* @access public
* @return void
*/
public function _sess_gc(){} public function ip_address()
{
$this->ip_address = $_SERVER['REMOTE_ADDR']; if ( ! $this->valid_ip($this->ip_address))
{
$this->ip_address = '0.0.0.0';
} return $this->ip_address;
} public function valid_ip($ip, $which = '')
{
$which = strtolower($which); // First check if filter_var is available
if (is_callable('filter_var'))
{
switch ($which) {
case 'ipv4':
$flag = FILTER_FLAG_IPV4;
break;
case 'ipv6':
$flag = FILTER_FLAG_IPV6;
break;
default:
$flag = '';
break;
} return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flag);
} if ($which !== 'ipv6' && $which !== 'ipv4')
{
if (strpos($ip, ':') !== FALSE)
{
$which = 'ipv6';
}
elseif (strpos($ip, '.') !== FALSE)
{
$which = 'ipv4';
}
else
{
return FALSE;
}
} $func = '_valid_'.$which;
return $this->$func($ip);
} protected function _valid_ipv4($ip)
{
$ip_segments = explode('.', $ip); // Always 4 segments needed
if (count($ip_segments) !== 4)
{
return FALSE;
}
// IP can not start with 0
if ($ip_segments[0][0] == '0')
{
return FALSE;
} // Check each segment
foreach ($ip_segments as $segment)
{
// IP segments must be digits and can not be
// longer than 3 digits or greater then 255
if ($segment == '' OR preg_match("/[^0-9]/", $segment) OR $segment > 255 OR strlen($segment) > 3)
{
return FALSE;
}
} return TRUE;
} // -------------------------------------------------------------------- /**
* Validate IPv6 Address
*
* @access protected
* @param string
* @return bool
*/
protected function _valid_ipv6($str)
{
// 8 groups, separated by :
// 0-ffff per group
// one set of consecutive 0 groups can be collapsed to :: $groups = 8;
$collapsed = FALSE; $chunks = array_filter(
preg_split('/(:{1,2})/', $str, NULL, PREG_SPLIT_DELIM_CAPTURE)
); // Rule out easy nonsense
if (current($chunks) == ':' OR end($chunks) == ':')
{
return FALSE;
} // PHP supports IPv4-mapped IPv6 addresses, so we'll expect those as well
if (strpos(end($chunks), '.') !== FALSE)
{
$ipv4 = array_pop($chunks); if ( ! $this->_valid_ipv4($ipv4))
{
return FALSE;
} $groups--;
} while ($seg = array_pop($chunks))
{
if ($seg[0] == ':')
{
if (--$groups == 0)
{
return FALSE; // too many groups
} if (strlen($seg) > 2)
{
return FALSE; // long separator
} if ($seg == '::')
{
if ($collapsed)
{
return FALSE; // multiple collapsed
} $collapsed = TRUE;
}
}
elseif (preg_match("/[^0-9a-f]/i", $seg) OR strlen($seg) > 4)
{
return FALSE; // invalid segment
}
} return $collapsed OR $groups == 1;
} protected function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE)
{
if (is_array($name))
{
// always leave 'name' in last place, as the loop will break otherwise, due to $$item
foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'name') as $item)
{
if (isset($name[$item]))
{
$$item = $name[$item];
}
}
} if ($prefix == '' AND $this->config_session['cookie_prefix'] != '')
{
$prefix = $this->config_session['cookie_prefix'];
}
if ($domain == '' AND $this->config_session['cookie_domain'] != '')
{
$domain = $this->config_session['cookie_domain'];
}
if ($path == '/' AND $this->config_session['cookie_path'] != '/')
{
$path = $this->config_session['cookie_path'];
}
if ($secure == FALSE AND $this->config_session['cookie_secure'] != FALSE)
{
$secure = $this->config_session['cookie_secure'];
} if ( ! is_numeric($expire))
{
$expire = time() - 86500;
}
else
{
$expire = ($expire > 0) ? time() + $expire : 0;
} setcookie($prefix.$name, $value, $expire, $path, $domain, $secure);
} protected function user_agent()
{
return ( ! isset($_SERVER['HTTP_USER_AGENT'])) ? FALSE : $_SERVER['HTTP_USER_AGENT'];
}
}

配置文件与上面的类文件同目录:

<?php
$config_session['cookie_prefix'] = "";
$config_session['cookie_domain'] = ".mypharma.com";
$config_session['cookie_path'] = "/";
$config_session['cookie_secure'] = FALSE;
$config_session['cookie_httponly'] = FALSE; $config_session['sess_cookie_name'] = 'mphsess';
$config_session['sess_expiration'] = 0;
$config_session['sess_expire_on_close'] = true;
$config_session['sess_memcached_ttl'] = 10*24*60*60;
$config_session['sess_match_ip'] = TRUE;
$config_session['sess_match_useragent'] = TRUE; $_memcache_conf = array(
'23'=>array(
'hostname'=>'192.168.11.23',
'port'=>11211,
'weight'=>1
)
);

session共享,格式json,php不能简单的设置session.serialize_handler=json,目前只有php,wddx(xml),安装扩展后还有igbinary(二进制)的更多相关文章

  1. 分布式Session共享(一):tomcat+redis实现session共享

    一.前言 本文主要测试redis实现session共享的实现方式,不讨论如何让nginx参与实现负载均衡等. 二.环境配置 本测试在Window下进行 name version port Tomcat ...

  2. 分布式Session共享(二):tomcat+memcached实现session共享

    一.前言 本文主要测试memcached实现session共享的实现方式,不讨论如何让nginx参与实现负载均衡等. 二.环境配置 本测试在Window下进行 name version port To ...

  3. ajax 发送json数据时为什么需要设置contentType: "application/json”

    1. ajax发送json数据时设置contentType: "application/json”和不设置时到底有什么区别? contentType: "application/j ...

  4. ajax发送json数据时为什么需要设置contentType: "application/json”

    1. ajax发送json数据时设置contentType: "application/json”和不设置时到底有什么区别?contentType: "application/js ...

  5. Tomcat利用MSM实现Session共享方案解说

    Session共享有多种解决方法,常用的有四种:1)客户端Cookie保存2)服务器间Session同步3)使用集群管理Session(如MSM) 4)把Session持久化到数据库 针对上面Sess ...

  6. 分布式中使用Redis实现Session共享(二)

    上一篇介绍了一些redis的安装及使用步骤,本篇开始将介绍redis的实际应用场景,先从最常见的session开始,刚好也重新学习一遍session的实现原理.在阅读之前假设你已经会使用nginx+i ...

  7. Tomcat7基于Redis的Session共享实战二

    目前,为了使web能适应大规模的访问,需要实现应用的集群部署.集群最有效的方案就是负载均衡,而实现负载均衡用户每一个请求都有可能被分配到不固定的服务器上,这样我们首先要解决session的统一来保证无 ...

  8. 集群间Session共享问题解决方案

    两个基本概念的生命周期 session: 当新客户端发现一个HTTP请求时服务端会创建一个session.并分配一个sessionID作为服务端来客户端的识别,session对象会保存在服务端.此时s ...

  9. 使用nginx做负载均衡的session共享问题

    查了一些资料,看了一些别人写的文档,总结如下,实现nginx session的共享PHP服务器有多台,用nginx做负载均衡,这样同一个IP访问同一个页面会被分配到不同的服务器上,如果session不 ...

随机推荐

  1. NDK 编译可执行程序

    以Hello Android工程为例. 建立好工程hello-a,在jni目录下创建文件hello-a.c,文件内容如下.(注意是jni目录,使用src目录编译会出错) #include <st ...

  2. CodeIgniter 错误: In order to use the Session class you are required to set an encryption key

    CodeIgniter SESSION  第一次用 session 遇到这个错误 , 说是要加一个密钥才可以使用,加就加吧, 打开 config.php 找到以下代码 /*|------------- ...

  3. ExtJs之Ext.util.TextMetrics

    <!DOCTYPE html> <html> <head> <title>ExtJs</title> <meta http-equiv ...

  4. Android 中建立一个OpenGL ES的开发环境

    转自: http://wiki.eoe.cn/page/Building_an_OpenGL_ES_Environment.html 负责人:zhangql原文链接:http://docs.eoean ...

  5. lintcode:等价二叉树

    等价二叉树 检查两棵二叉树是否等价.等价的意思是说,首先两棵二叉树必须拥有相同的结构,并且每个对应位置上的节点上的数都相等. 样例 1 1 / \ / \ 2 2 and 2 2 / / 4 4 就是 ...

  6. 545B. Equidistant String

    题目链接 输入两个只含有01的字符串,s,t 求一个字符串p使到s,t的距离一样 这里的距离是指对应位置:0-0的距离是0 ,o-1的距离是1 ,1-1的距离是0,1-0的距离是1 这里只要求找出满足 ...

  7. ubuntu为Python添加默认搜索路径

    我们在自己写python模块的时候,怎么样把自己写的模块加入到python默认就有的搜索路径中呢?不要每次非得import sys; sys.path.append(‘/home/uestc/rese ...

  8. I,P,B帧和PTS,DTS的关系

    http://www.cnblogs.com/qingquan/archive/2011/07/27/2118967.html 基本概念: I frame :帧内编码帧 又称intra picture ...

  9. Android核心分析之十七电话系统之rilD

    Android电话系统之-rild Rild是Init进程启动的一个本地服务,这个本地服务并没有使用Binder之类的通讯手段,而是采用了socket通讯这种方式.RIL(Radio Interfac ...

  10. JavaWeb项目开发案例精粹-第6章报价管理系统-04Service层

    1. package com.sanqing.service; import com.sanqing.dao.DAO; import com.sanqing.po.Customer; /** * 客户 ...