nginx,php,会话数据与服务器发送事件有关

时间:2015-10-21 12:57:51

标签: node.js mongodb session nginx server-sent-events

我正在使用多种技术来处理Web应用程序: socket.io和request的nodejs nginx / php 服务器发送事件 会议商店在mongodb集合中。

  • node / socketio / request:充当中间件,代替“旧”ajax方式。在发布的标题中添加“set-cookie”可以使事情变得非常快,从而保持会话数据跨导航。
  • 会话使用session_save_handler存储在mongodb库中。
  • 发出了服务器发送的事件连接,这是一个奇怪的行为: 如果我没有将'session_write_close'放在sse的被调用文件之上,则会话在页面刷新时丢失。 如果我把它,好吧似乎很好,但我无法监控会话对象的任何变化,即使在用户登录/注销时也没有变化。

这是我的会话类文件:

class Session {
    protected $dbSession;
    protected $maxTime;

    public function __construct() {
        $this->conn =  new Mongo('mongodb://user:passwd@hostip');
        $sitebase_app   = 'base_for_coll';

        $this->dbSession     = $this->conn->$sitebase_app->session;
        $this->maxTime = get_cfg_var("session.gc_maxlifetime");

        register_shutdown_function('session_write_close');
        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() { return true; }
    public function close() { return true; }
    public function read($id) {
        $doc = $this->dbSession->findOne(array("_id" => $id), array("sessionData" => 1));
        return $doc['sessionData'];
    }
    public function write($id,$data) {
        //
        $this->dbSession->save(array("_id" => $id, "sessionData" => $data, "timeStamp" => time()));
        return true;
    }
    public function destroy($id) {
        $this->dbSession->remove(array("_id" => $id));
        return true;
    }
    public function gc() {
        $agedTime = time() - $this->maxTime;
        $this->dbSession->remove(array("timeStamp" => array('$lt' => $agedTime)));
    }
}

ini_set('session.save_handler' , 'user');
$session = new Session();

瞧我的SSE php文件:

include_once($_SERVER['CONF_INC']);

$APP = new App();

$APPCACHE = $APP->plug('sitebase_sockets','data_activity');
$APPCACHE->ensureIndex(['timeData_activity'=>1]);
$APPCACHE->ensureIndex(['codeData_activity'=>1]);

ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Content-Encoding: none;');

session_write_close();

flush();
ob_end_flush();
//
$time = time();
$lastmodif = filemtime(ACTIVEMODULEFILE);



function sendMsg($id , $msg) {
    ini_set('implicit_flush', true);
    ob_implicit_flush(true);
    $sessid = session_id();
    echo "id: ".uniqid() . PHP_EOL;
    echo "event: $id" . PHP_EOL;
    echo "data: {\n";
    echo "data: \"msg\": $msg  \n";
    echo "data: }\n";
    echo PHP_EOL;
    ob_flush();
    flush();
}


$notify = 1;




$startedAt = time();
do {

    $TEST = $APPCACHE->find(['timeData_activity'=>['$gte'=>$startedAt]]);
    if($TEST->count()!=0){
        // event : act_upd_data
        // data : json
        $startedAt = time();

        while($ARR = $TEST->getNext()){
            unset($ARR['_id']);
            $json = json_encode($ARR,JSON_FORCE_OBJECT);
            sendMsg($ARR['eventData_activity'] ,$json);
        }
        sleep(1);
    }
    if ((time() - $startedAt) > 360) {
        skelMdl::send_cmd('act_notify',['options'=>['sticky'=>'true']]+ array('msg'=>'DIE FOR PERIODIC TEST RELOAD'.session_id()),session_id());
        die();
    }

    usleep(250000); // 1/4 seconde

    ob_flush();
    flush();

    if(empty($_SESSION['idagent'])){
        $notify = 0;
        skelMdl::send_cmd('act_notify', array('msg'=>' Session agent empty'.session_id()),session_id());
        sleep(5);
    }

} while(true);

我的conf.inc.php文件的开头

header('Content-Type: text/html; charset=UTF-8');
//
ini_set('display_errors', 55);
// THE SESSION_HANDLER
include_once('appclasses/ClassSession.php');
// 

if ( session_status() == PHP_SESSION_NONE ) { 
    session_start();
}

我找不到更多的想法,任何建议都会受到赞赏。 谢谢, Mydde。

ps:socket.io而不是nature websocket,因为房间和名称空间...但当然,我更喜欢使用原生websocket,避免使用中间件......

0 个答案:

没有答案