成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Swoole4.x之協(xié)程變量訪問(wèn)安全與協(xié)程連接池實(shí)現(xiàn)

aisuhua / 3739人閱讀

摘要:訪問(wèn)安全問(wèn)題為什么說(shuō)有訪問(wèn)安全問(wèn)題呢傳統(tǒng)地,在的的環(huán)境中,很少有遇到所謂變量安全訪問(wèn)問(wèn)題。上下文管理器為了解決這個(gè)問(wèn)題,我們引入?yún)f(xié)程上下文管理這樣的概念,由此來(lái)實(shí)現(xiàn)每個(gè)協(xié)程環(huán)境內(nèi)的數(shù)據(jù)隔離。

訪問(wèn)安全問(wèn)題

為什么說(shuō)有訪問(wèn)安全問(wèn)題呢?傳統(tǒng)地,在php的的環(huán)境中,很少有Phper遇到所謂變量安全訪問(wèn)問(wèn)題。舉個(gè)例子,代碼大約如下:

class db
{
    protected static $instance;
    protected $dbCon;
    
    function __construct()
    {
        /*
         * 我們這里用stdclass來(lái)模擬一個(gè)數(shù)據(jù)庫(kù)連接
         */
        $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);

這個(gè)是在fpm模式下,很常見(jiàn)的數(shù)據(jù)庫(kù)連接單例模式的使用。乍一看沒(méi)有問(wèn)題,但實(shí)際上,在協(xié)程環(huán)境下,會(huì)出現(xiàn)連接跨協(xié)程使用問(wèn)題,舉例如下

go(function (){
    go(function (){
        db::getInstance()->dbCon()->key = "one";
        //假設(shè)這sql執(zhí)行了1s
        co::sleep(1);
        var_dump(db::getInstance()->dbCon()->key);
    });
    go(function (){
        db::getInstance()->dbCon()->key = "two";
        //假設(shè)這sql執(zhí)行了0.1s
        co::sleep(0.1);
        var_dump(db::getInstance()->dbCon()->key);
    });
});

我們會(huì)發(fā)現(xiàn),以上代碼當(dāng)中,協(xié)程2的數(shù)據(jù)污染到了協(xié)程1的數(shù)據(jù),那么因此這樣肯定是不行的。

上下文管理器

為了解決這個(gè)問(wèn)題,我們引入?yún)f(xié)程上下文管理這樣的概念,由此來(lái)實(shí)現(xiàn)每個(gè)協(xié)程環(huán)境內(nèi)的數(shù)據(jù)隔離。

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";
        //假設(shè)這sql執(zhí)行了1s
        co::sleep(1);
        var_dump(dbContext::getInstance()->dbCon()->key);
    });
    go(function (){
        dbContext::getInstance()->dbCon()->key = "two";
        //假設(shè)這sql執(zhí)行了0.1s
        co::sleep(0.1);
        var_dump(dbContext::getInstance()->dbCon()->key);
    });
});

以上代碼中,我們用每個(gè)協(xié)程的id,來(lái)作為每個(gè)協(xié)程棧的數(shù)據(jù)token,用了defer方法,實(shí)現(xiàn)了每個(gè)協(xié)程退出的時(shí)候的數(shù)據(jù)自動(dòng)清理,從而避免了內(nèi)存泄露。

通用版本的連接池與協(xié)程上下文管理

我們不難發(fā)現(xiàn),以上代碼中,實(shí)際上依舊是短連接的管理方式,沒(méi)辦法對(duì)鏈接進(jìn)行復(fù)用,由于本文章僅做基礎(chǔ)原理講解之用,具體有興趣的同學(xué),可以查看下Easyswoole這個(gè)框架的連接池和協(xié)程上下文管理器,項(xiàng)目主頁(yè)在 www.easyswoole.com ,若覺(jué)得喜歡,有幫助,可以給easyswoole的github倉(cāng)庫(kù)點(diǎn)個(gè)贊。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/31790.html

Failed to recv the data from server completely (SIZE:0/8, REASON:closed)