說明

workerman從4.x版本開始加強了HTTP服務的支持。引入了請求類、響應類、session類以及SSE。如果你想使用workerman的HTTP服務,強烈推薦使用workerman4.x或者以後的更高版本。

注意以下都是workerman4.x版本的用法,不相容workerman3.x。

更改session儲存引擎

workerman為session提供了檔案儲存引擎和redis儲存引擎。默認使用檔案儲存引擎。如果想更改為redis儲存引擎,請參考如下代碼。

<?php
use Workerman\Worker;
use Workerman\Protocols\Http\Session;
use Workerman\Protocols\Http\Session\RedisSessionHandler;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

// redis配置
$config = [
    'host'     => '127.0.0.1', // 必選參數
    'port'     => 6379,        // 必選參數
    'timeout'  => 2,           // 可選參數
    'auth'     => '******',    // 可選參數
    'database' => 1,           // 可選參數
    'prefix'   => 'session_'   // 可選參數
];
// 使用 Workerman\Protocols\Http\Session::handlerClass方法來更改session底層驅動類
Session::handlerClass(RedisSessionHandler::class, $config);

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    $session = $request->session();
    $session->set('somekey', rand());
    $connection->send($session->get('somekey'));
};

Worker::runAll();

設定session儲存位置

使用默認儲存引擎時session資料默認儲存在磁碟中,默認位置為session_save_path()的返回的位置。
你可以使用以下方法改變儲存位置。

use Workerman\Worker;
use \Workerman\Protocols\Http\Session\FileSessionHandler;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/vendor/autoload.php';

// 設定session檔案儲存位置
FileSessionHandler::sessionSavePath('/tmp/session');

$worker = new Worker('http://0.0.0.0:8080');

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    $session = $request->session();
    $session->set('name', 'tome');
    $connection->send($session->get('name'));
};

// 運行worker
Worker::runAll();

session檔案清理

使用默認session儲存引擎時磁碟上會有多個session檔案,
workerman 會根據php.ini中設定的session.gc_probability session.gc_divisor session.gc_maxlifetime 選項清理過期的session檔案。關於這三個選項說明參見 php手冊

更改儲存驅動

除了檔案session儲存引擎和redis session儲存引擎,workerman允許你通過標準的SessionHandlerInterface 接口添加新的session儲存引擎,比如mangoDb session儲存引擎、MySQL session儲存引擎等。

新增session儲存引擎流程

  1. 實現 SessionHandlerInterface 接口
  2. 使用 Workerman\Protocols\Http\Session::handlerClass($class_name, $config) 方法替換底層SessionHandler接口

實現 SessionHandlerInterface 接口

自定義session儲存驅動須實現 SessionHandlerInterface 接口。這個接口包含以下方法:

SessionHandlerInterface {
    /* Methods */
    abstract public read ( string $session_id ) : string
    abstract public write ( string $session_id , string $session_data ) : bool
    abstract public destroy ( string $session_id ) : bool
    abstract public gc ( int $maxlifetime ) : int
    abstract public close ( void ) : bool
    abstract public open ( string $save_path , string $session_name ) : bool
}

SessionHandlerInterface 說明

  • read方法用來從儲存中讀取session_id對應的所有session資料。請不要對資料進行反序列化操作,框架會自動完成。
  • write方法用來向儲存寫入session_id對應的session資料。請不要對資料進行序列化操作,框架已經自動完成。
  • destroy方法用來銷毀session_id對應的session資料。
  • gc方法用來刪除過期的session資料,儲存應該對最後修改時間大於maxlifetime的所有session執行刪除操作
  • close 無需任何操作,直接返回true即可
  • open 無需任何操作,直接返回true接口

替換底層驅動

實現完SessionHandlerInterface接口後,使用以下方法更改session底層驅動。

Workerman\Protocols\Http\Session::handlerClass($class_name, $config);
  • $class_name 為實現SessionHandlerInterface接口的SessionHandler類的名字。如果有命名空間則需要帶上完整的命名空間
  • $config 為SessionHandler類的構造函數的參數

具體實現

注意,這個MySessionHandler類僅僅為了說明更改session底層驅動的流程,MySessionHandler並不能用於生產環境。

<?php
use Workerman\Worker;
use Workerman\Protocols\Http\Session;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

class MySessionHandler implements SessionHandlerInterface
{
    protected static $store = [];

    public function __construct($config) {
        // ['host' => 'localhost']
        var_dump($config);
    }

    public function open($save_path, $name)
    {
        return true;
    }

    public function read($session_id)
    {
        return isset(static::$store[$session_id]) ? static::$store[$session_id]['content'] : '';
    }

    public function write($session_id, $session_data)
    {
        static::$store[$session_id] = ['content' => $session_data, 'timestamp' => time()];
    }

    public function close()
    {
        return true;
    }

    public function destroy($session_id)
    {
        unset(static::$store[$session_id]);
        return true;
    }

    public function gc($maxlifetime) {
        $time_now = time();
        foreach (static::$store as $session_id => $info) {
            if ($time_now - $info['timestamp'] > $maxlifetime) {
                unset(static::$store[$session_id]);
            }
        }
    }
}

// 假設新實現的SessionHandler類需要一些配置傳入
$config = ['host' => 'localhost'];
// 使用 Workerman\Protocols\Http\Session::handlerClass($class_name, $config) 來更改session底層驅動類
Session::handlerClass(MySessionHandler::class, $config);

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    $session = $request->session();
    $session->set('somekey', rand());
    $connection->send($session->get('somekey'));
};

Worker::runAll();