`
hongtoushizi
  • 浏览: 372692 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

PHP and Node.JS session share using memcache

阅读更多

最近在部署nodejs和php的通过memcached实现session共享的pc和andriod的实时聊天。看到此片文章,感觉非常不错,留下以备后用。谢谢作者了,帮助很大。

转载自: https://www.evernote.com/shard/s209/sh/740efea8-dded-40d0-95cd-2f1041b48eb5/c75e2226f8d896249b540d9f60f0f7a5

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共享.rar

    memcache提供了CAS(Compare and Swap)机制,可以在读取和更新session时避免数据冲突。 5. **优化与扩展**:根据需求,可能需要考虑session数据的序列化和反序列化策略,以及在服务器扩展时的负载均衡和故障恢复...

    PHP7.x 8.0 memcache dll php_memcache.dll

    标题 "PHP7.x 8.0 memcache dll php_memcache.dll" 涉及到的是在PHP 7.x和8.0版本中使用memcache扩展的相关内容,特别是关于`php_memcache.dll`这个动态链接库文件。memcache是广泛应用于Web开发中的一个内存对象...

    php5.4_memcache.dll 64位

    标题 "php5.4_memcache.dll 64位" 指的是针对PHP 5.4版本的一个64位扩展,用于支持Memcache缓存系统。这个扩展使得PHP应用程序能够利用Memcache服务来存储和检索数据,从而提高网站性能,减少数据库负载。 描述中的...

    windows下32位php-5.4.x的memcache.dll扩展

    windows下的memcache服务,在windows平台下搭建wamp或者php环境的时候,如果没有memcache服务,会报错找不到memcache()方法,下载并解压这个压缩包,将memcache.exe放到任意位置,然后使用管理员权限在命令行转到...

    windows 64 位 V15 nts IIS8.5 php7.2.x 扩展php_memcache.dll 亲测好用

    windows 64 位 V15 nts IIS8.5 php7.2.x 扩展php_memcache.dll 亲测好用

    delphi memcache MemCache.0.2.0.zip

    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 ...

    php5.3.8下载含apache2_2.dll,php_memcache.dll,xdebug2.1.1版本文件

    `php_memcache.dll`是PHP的Memcached扩展,用于在PHP应用中与Memcached内存缓存系统交互。Memcached是一种高性能的分布式内存对象缓存系统,适用于减轻数据库负载,提高网站性能。通过安装这个扩展,开发者可以在PHP...

    PHP5.5/5.6的 32&63 VC11 Memcache扩展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 ...

    php7.1和7.2的memcache.dll文件

    亲测可用,用的时候,将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_...

    PHP 实现多服务器session共享之memcache共享

    这里,`session.save_handler`指定session的处理方式为memcache,`session.save_path`定义了memcache服务器的地址和端口。 3. **session配置优化**: 为了提高session存储的效率,可以调整session的过期时间、...

    session共享之memcache Redis

    本文将深入探讨如何利用memcache和Redis实现session的共享,以此提高应用的性能和可扩展性。 首先,让我们理解什么是Session。Session是Web应用程序中用于跟踪用户状态的一种机制。在HTTP协议无状态的特性下,...

    pecl-memcache-4.0.4.tar.gz

    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 memache+php_memcache.dll(php5.5.12)

    本文将详细介绍如何在Windows上安装并配置Memcached,同时结合PHP的`php_memcache.dll`扩展实现PHP应用程序中的缓存功能。 首先,我们需要下载`memcached`的Windows版本。Memcached官方并不提供Windows二进制包,但...

    php 5.4.15 64位 memcache.dll

    标题 "php 5.4.15 64位 memcache.dll" 指的是针对 PHP 5.4.15 版本的一个64位系统优化的 memcache 扩展库。Memcache 是一种广泛使用的分布式内存缓存系统,用于在 Web 应用程序中提高数据读取速度,通过存储经常访问...

    Memcached与php_memcache.dll

    Memcached和`php_memcache.dll`是Web开发中常见的缓存解决方案,特别是在PHP环境中。Memcached是一个高性能的分布式内存对象缓存系统,用于减少数据库负载,通过在内存中存储数据来提高应用程序的性能。`...

    php7.3.~redis和memcache扩展包.rar

    标题中的“php7.3.~redis和memcache扩展包.rar”表明这是一份针对PHP 7.3版本的Redis和Memcache扩展的压缩文件,适用于Windows操作系统。这两个扩展是PHP开发过程中常用的缓存管理工具,对于提升Web应用程序的性能至...

    适合php5.3 的memcache.dll文件

    标题中的“适合php5.3的memcache.dll文件”指的是PHP的一个扩展库——Memcache,它是专门为PHP设计的,用于与Memcached内存缓存系统进行交互。Memcache.dll是这个扩展在Windows环境下运行所需的动态链接库文件。在...

    PHP实现多服务器session共享之memcache共享

    1. `session.save_handler` - 将其值改为"memcache",指定使用memcached作为session处理器。 2. `session.save_path` - 设置为memcached服务器的连接字符串。例如:"tcp://192.168.1.1:11211,unix:///var/run/...

    php7.2 memcache.dll

    标题 "php7.2 memcache.dll" 涉及到的是PHP编程语言的一个扩展模块,具体是Memcache的动态链接库(DLL)文件,用于在PHP 7.2环境中与Memcache缓存系统进行交互。PHP是一种广泛使用的开源服务器端脚本语言,尤其适合...

Global site tag (gtag.js) - Google Analytics