最近在部署nodejs和php的通过memcached实现session共享的pc和andriod的实时聊天。看到此片文章,感觉非常不错,留下以备后用。谢谢作者了,帮助很大。
I was needing some real time performance using PHP. After searching and creating « patched » systems, i’ve to admit there is no real good system using only PHP.
First step
The best way i found was using long polling system using a file system + Mysql to store current system (file, when user first connect), and last commands sended (Mysql, for user already logged who need only small updates). The system still have some trouble because of lost messages while transfering and sometimes time difference while using clearstatcache.
You can found a really basic example of such kind of system here.
This system in general is not stable for production. So I decide to extend existing PHP system with Node.JS + socket.io.
Extending PHP
Because the PHP system was already finished, and only few parts use real time, the idea was using a share system between PHP and Node.JS. The main problem was in fact to share session from PHP to Node.JS.
Understanding PHP’s session
PHP session are not easy to change/manipulate when serialized, basically PHP use a handler to store data, a stored sessions will look like this :
user_id|s:1:"1";password|s:0:"";firstname|s:7:"Charles";
Basically it is : key | type : length : value ;
In case of integer, it will be type : value directly.
The problem is that, this serialize system is not so easy to manipulate in PHP, and in Node.JS also. PHP use a specific serializer/unserializer called session_decode and session_encode for that. And Node.JS got nothing. The problem is pretty simple, imagine a string variable using a « ; » inside. In such case you just can’t use a split(« ; ») (like many link on internet suggest) because you will cut the variable content. That’s why we should change the storing system to get a more easy-to-change format for both PHP and Node.JS : JSON.
PHP Session Handler
There is many way to change the session handler, but in fact only one is enough flexible to change the stored result. If you use directly php.ini to set a different storage (like memcache), you will not get what we want, because session will still be stored like previous system but in memcache, and you cannot change anything to that. PHP provide a more flexible system, using the session_set_save_handler. This function allow to manipule each basic operation on session storage : open/read/write/delete/close and gc (garbage collector).
By the way, we must have a shared system flexible for Node.JS and PHP, basically there is two main system : memcache and SQL storage, which are both pretty easy to use in Node and PHP.
From now, I consider you got PHP/Node.JS & memcache configured, with memcache running on port 11211 on localhost, PHP is linked to memcache using php-memcache. There is plenty tutorials on internet, for every system (Windows, linux/OSX).
Custom Handler to share with Node.JS
The problem with session_set_save_handler function, is that save function already got session encoded data version passed (so we recieve the encoded session), and read function must retrieve the same already-encoded version, so we must unserialize before storing, and re-serialize after storing.
This class already do the trick properly :
<?php /** * memcacheSessionHandler class * @class memcacheSessionHandler * @file memcacheSessionHandler.class.php * @brief This class is used to store session data with memcache, it store in json the session to be used more easily in Node.JS * @version 0.1 * @date 2012-04-11 * @author Deisss * @licence LGPLv3 * This class is used to store session data with memcache, it store in json the session to be used more easily in Node.JS */ class memcacheSessionHandler{ private $host = "localhost"; private $port = 11211; private $lifetime = 0; private $memcache = null; /** * Constructor */ public function __construct(){ $this->memcache = new Memcache; $this->memcache->connect($this->host, $this->port) or die("Error : Memcache is not ready"); session_set_save_handler( array($this, "open"), array($this, "close"), array($this, "read"), array($this, "write"), array($this, "destroy"), array($this, "gc") ); } /** * Destructor */ public function __destruct(){ session_write_close(); $this->memcache->close(); } /** * Open the session handler, set the lifetime ot session.gc_maxlifetime * @return boolean True if everything succeed */ public function open(){ $this->lifetime = ini_get('session.gc_maxlifetime'); return true; } /** * Read the id * @param string $id The SESSID to search for * @return string The session saved previously */ public function read($id){ $tmp = $_SESSION; $_SESSION = json_decode($this->memcache->get("sessions/{$id}"), true); if(isset($_SESSION) && !empty($_SESSION) && $_SESSION != null){ $new_data = session_encode(); $_SESSION = $tmp; return $new_data; }else{ return ""; } } /** * Write the session data, convert to json before storing * @param string $id The SESSID to save * @param string $data The data to store, already serialized by PHP * @return boolean True if memcached was able to write the session data */ public function write($id, $data){ $tmp = $_SESSION; session_decode($data); $new_data = $_SESSION; $_SESSION = $tmp; return $this->memcache->set("sessions/{$id}", json_encode($new_data), 0, $this->lifetime); } /** * Delete object in session * @param string $id The SESSID to delete * @return boolean True if memcached was able delete session data */ public function destroy($id){ return $this->memcache->delete("sessions/{$id}"); } /** * Close gc * @return boolean Always true */ public function gc(){ return true; } /** * Close session * @return boolean Always true */ public function close(){ return true; } } new memcacheSessionHandler(); ?>
You just need to include this script at the beginning of each script wich use session, it must be included before every session_start call (it start by itself memcacheSessionHandler class).
This system will overpass all php.ini config about session handling. Now if you check inside memcache, the session are now stored in JSON. It will serialize/unserialize to still let PHP system using his own way. It is totally transparent for PHP.
Be carefull session_set_save_handler change with PHP5.4, so in this case you have to modify little bit this class :
class memcacheSessionHandler implements SessionHandlerInterface{
For PHP5.4 now there is interface to implements. There is also session_set_save_handler little bit different (replace on __construct function) :
session_set_save_handler(&$this, true);
Instead of long code function… This is enough for support on PHP5.4.
Node.JS Part
Now we just need to use memcache (wich store JSON session file, and delete them after session max lifetime) inside Node.JS :
First don’t forget to install memcache : npm install memcache
Here is a basic example how to use PHP Session (using cookie session ID) :
var app = require("http").createServer(handler), fs = require("fs"), memcache = require("memcache"), co = require("./cookie.js"); app.listen(7070); //On client incomming, we send back index.html function handler(req, res){ fs.readFile(__dirname + "/index.html", function(err, data){ if(err){ res.writeHead(500); return res.end("Error loading index.html"); }else{ res.writeHead(200); res.end(data); } }); //Using php session to retrieve important data from user var cookieManager = new co.cookie(req.headers.cookie); var client = new memcache.Client(11211, "localhost"); client.connect(); client.get("sessions/"+cookieManager.get("PHPSESSID"), function(error, result){ console.log("error : "+error); if(typeof(error)==="undefined"){ var session = JSON.parse(result); } }); }
You need to get also this cookie module (./cookie.js) :
//Directly send cookie to system, if it's node.js handler, send : //request.headers.cookie //If it's socket.io cookie, send : //client.request.headers.cookie module.exports.cookie = function(co){ this.cookies = {}; co && co.split(';').forEach(function(cookie){ var parts = cookie.split('='); this.cookies[parts[0].trim()] = (parts[1] || '').trim(); }.bind(this)); //Retrieve all cookies available this.list = function(){ return this.cookies; }; //Retrieve a key/value pair this.get = function(key){ if(this.cookies[key]){ return this.cookies[key]; }else{ return {}; } }; //Retrieve a list of key/value pair this.getList = function(map){ var cookieRet = {}; for(var i=0; i<map.length; i++){ if(this.cookies[map[i]]){ cookieRet[map[i]] = this.cookies[map[i]]; } } return cookieRet; }; };
Now it’s almost finish, Node.JS and PHP are both linked to memcache, and share session in JSON. When one (PHP in fact), disconnect, the other (Node.JS) will do the same because PHP continue to keep hand on memcache like it use to do with session (so login & logout should stay on PHP side).
Don’t forget on Node.JS the PHPSESSID => may be different if you use a different session name on PHP.ini.
相关推荐
PHP实现多服务器session共享之memcache共享
php5.3.8下载内含php5apache2_2.dll,php_memcache.dll,php_xdebug.dll vc9版本配合apache2.2版本 根据自己的情况来配置php.ini文件
windows下的memcache服务,在windows平台下搭建wamp或者php环境的时候,如果没有memcache服务,会报错找不到memcache()方法,下载并解压这个压缩包,将memcache.exe放到任意位置,然后使用管理员权限在命令行转到...
windows 64 位 V15 nts IIS8.5 php7.2.x 扩展php_memcache.dll 亲测好用
MemCache.0.2.0.zip Memcached Client for Delphi 客户端调用类 MemCache.0.2.0.zip Show all LinksExternal links Memcached Project This project is a delphi unit which implements a thread safe client for ...
php_memcache.dll
PHP 添加 Memcache 扩展 : 下载包中包括如下: php_memcache-3.0.8-5.5-nts-vc11-x64.zip php_memcache-3.0.8-5.5-nts-vc11-x86.zip php_memcache-3.0.8-5.5-ts-vc11-x64.zip ...
亲测可用,用的时候,将php-7.2.x_memcache.dl或者php-7.1.x_memcache.dll修改为php_memcache.dll之后,在php.ini中加入配置 extension=php_memcache.dll和 [Memcache] memcache.allow_failover = 1 memcache.max_...
php5.4 php_memcache.dll;memcached window64位
tar -zxvf pecl-memcache-4.0.4.tar.gz && cd /root/pecl-memcache-4.0.4 && /usr/local/php7/bin/phpize && ./configure --with-php-config=/usr/local/php7/bin/php-config && make && make install
windows memcached安装,php_memcache.dll 5.3 , php_memcache.dll 5.4 php_memcache.dll 5.5 安装说明及实例代码。
Memcached.exe服务器端安装 php_memcache.dll客户端 extension=php_memcache.dll
最新windows的memcache模块下载 这个模块是平和php5.3的,在我的windowsxp php5.3.5上安装成功 里面有两个php库,一个php_memcache.dll.vc6 和一个php_memcache.dll.vc9 另外一个windows的memcache.exe文件,都是网上...
memcache win8 x64 php5.4.7 测试通过(开发套件 xampp 1.8.1) 配置如下: 1、开启memcached 服务,注意路径 memcached.exe -d install(安装) memcached.exe -d start(自动启动) 2、调整 php.ini 增加如下...
测试环境 php7.1.11 ts vc14 x64 ,直接放到php安装目录的ext文件夹下 即可
适合于PHP5.4.3版本,通过memcache可以对数据读取速度进行优化,有效加快web的访问速度。
window下安装的memcache以及dll扩展,亲测可用
1.设置session用memcache来存储方法I: 在 php.ini 中全局设置session.save_handler = memcachesession.save_path = “tcp://127.0.0.1:11211”方法II: 某个目录下的 .htaccess :php_value session.save_handler ...
本文实例讲述了PHP保存session到memcache服务器的方法。分享给大家供大家参考,具体如下: 传统的 session 是写入到服务器文件中,可以在 php.ini 中看出,清单如下 session.save_handler = files session.save_...
windows php7.3.~redis和memcache扩展包,每次安装都要找好久,存到这里分享一下吧