Описание

Workerman с версии 4.x усилил поддержку HTTP сервиса. Введены классы запросов, ответов, сессий и SSE. Если вы хотите использовать HTTP сервис Workerman, настоятельно рекомендуется использовать Workerman версии 4.x или более поздние версии.

Обратите внимание, что все приведенные примеры относятся к версии Workerman 4.x и несовместимы с 3.x.

Изменение движка хранения сессий

Workerman предоставляет файловый движок хранения сессий и движок хранения сессий 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::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_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';

// Установка местоположения хранения файлов сессий
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();

Очистка файлов сессий

При использовании движка хранения сессий по умолчанию на диске будет множество файлов сессий. Workerman будет очищать устаревшие файлы сессий в соответствии с параметрами session.gc_probability, session.gc_divisor, session.gc_maxlifetime, установленными в php.ini. Подробности об этих трех параметрах см. в руководстве php

Изменение драйвера хранения

Помимо файлового движка хранения сессий и драйвера Redis, Workerman позволяет добавлять новые движки хранения сессий через стандартный интерфейс SessionHandlerInterface, такой как хранилище сессий mongoDb, хранилище сессий MySQL и т.д.

Процесс добавления нового движка хранения сессий

  1. Реализуйте интерфейс SessionHandlerInterface
  2. Используйте метод Workerman\Protocols\Http\Session::handlerClass($class_name, $config) для замены класса интерфейса SessionHandler

Реализация интерфейса SessionHandlerInterface

Кастомный драйвер хранения сессий должен реализовывать интерфейс SessionHandlerInterface. Этот интерфейс включает следующие методы:

SessionHandlerInterface {
    /* Методы */
    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, из хранилища. Не выполняйте десериализацию данных, так как фреймворк выполнит это автоматически.
  • Метод write используется для записи данных сессии в хранилище, соответствующих session_id. Не выполняйте сериализацию данных, так как фреймворк делает это автоматически.
  • Метод destroy используется для уничтожения данных сессии, соответствующих session_id.
  • Метод gc используется для удаления устаревших данных сессий; хранилище должно выполнять операцию удаления для всех сессий, последние изменения в которых произошли более чем maxlifetime назад.
  • close не требует никаких операций, просто возвращайте true.
  • open не требует никаких операций, просто возвращайте true.

Замена базового драйвера

После реализации интерфейса SessionHandlerInterface используйте следующий метод для изменения базового драйвера сессий.

Workerman\Protocols\Http\Session::handlerClass($class_name, $config);
  • $class_name — это имя класса SessionHandler, реализующего интерфейс SessionHandlerInterface. Если есть пространство имен, укажите полное пространство имен.
  • $config — это параметры конструктора класса SessionHandler.

Конкретная реализация

Обратите внимание, что этот класс 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::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();