Рубрики
Uncategorized

Swool 4.Безопасность доступа к переменным процессам xcp и реализация пула подключений к процессам Co

Автор оригинала: David Wong.

Проблемы с безопасностью доступа

Почему у нас есть доступ к системе безопасности? Традиционно в средах PHP немногие пользователи Phper сталкиваются с так называемыми проблемами доступа с переменной безопасностью. Например, код примерно выглядит следующим образом:

class db
{
    protected static $instance;
    protected $dbCon;
    
    function __construct()
    {
        /*
         * Here we use stdClass to simulate a database connection
         */
        $this->dbCon = new \stdClass();
    }

    public static function getInstance()
    {
        if(!isset(self::$instance)){
            self::$instance = new db();
        }
        return self::$instance;
    }

    function dbCon()
    {
        return $this->dbCon;
    }
}

$con = db::getInstance()->dbCon();
$con->key = 'new';
var_dump($con->key);

Это очень распространенное использование одноэлементного режима подключения к базе данных в режиме FPM. На первый взгляд, никаких проблем, но на самом деле в контексте совместной работы возникнут проблемы с использованием соединений для совместной работы, например, следующие

go(function (){
    go(function (){
        db::getInstance()->dbCon()->key = 'one';
        // Suppose that this SQL executes for 1s
        \co::sleep(1);
        var_dump(db::getInstance()->dbCon()->key);
    });
    go(function (){
        db::getInstance()->dbCon()->key = 'two';
        // Suppose this SQL executes 0.1s
        \co::sleep(0.1);
        var_dump(db::getInstance()->dbCon()->key);
    });
});

Мы обнаружим, что в приведенном выше коде данные совместного выполнения 2 загрязняют данные совместного выполнения 1, поэтому это, безусловно, невозможно.

Контекстный менеджер

Чтобы решить эту проблему, мы вводим концепцию управления контекстом совместной работы для обеспечения изоляции данных в каждой среде совместной работы.

class dbContext
{
    private $container = [];

    private static $instance;

    public static function getInstance()
    {
        if(!isset(self::$instance)){
            self::$instance = new dbContext();
        }
        return self::$instance;
    }

    function dbCon()
    {
        $cid = \co::getCid();
        if(!isset($this->container[$cid])){
            $this->container[$cid] = new stdClass();
            defer(function (){
                $this->destroy();
            });
        }
        return $this->container[$cid];
    }

    function destroy()
    {
        $cid = \co::getCid();
        if(!isset($this->container[$cid])){
            unset($this->container[$cid]);
        }
    }
}

go(function (){
    go(function (){
        dbContext::getInstance()->dbCon()->key = 'one';
        // Suppose that this SQL executes for 1s
        \co::sleep(1);
        var_dump(dbContext::getInstance()->dbCon()->key);
    });
    go(function (){
        dbContext::getInstance()->dbCon()->key = 'two';
        // Suppose this SQL executes 0.1s
        \co::sleep(0.1);
        var_dump(dbContext::getInstance()->dbCon()->key);
    });
});

В приведенном выше коде мы используем идентификатор каждого протокола в качестве маркера данных каждого стека протоколов и используем метод отсрочки для автоматической очистки данных при выходе из каждого протокола, что позволяет избежать утечки памяти.

Универсальная версия управления контекстом пула соединений и совместной работы

Мы легко можем обнаружить, что в приведенном выше коде, на самом деле, это все еще режим управления коротким соединением. Нет возможности повторно использовать ссылки. Поскольку в статье объясняются только основные принципы, студенты, которые заинтересованы в этом, могут проверить пул соединений и следующий менеджер фреймворка Easy swool. Домашняя страница проекта находится на сайте www. easyswool .com. Если вам захочется, вы можете помочь Е. На складе GitHub Asyswool есть несколько комплиментов.