【无标题】

use Swoole\Coroutine;
class Context
{
   protected static $pool = []; //进程创建后此静态变量就会存在,但只会根据对应的id去覆盖对应协程下的数据

    
// 基于协程 `ID` 获取数据
    static function get($key)
    {
        $cid = Coroutine::getCid();
        if ($cid < 0)
        {
            return null;
        }
        if(isset(self::$pool[$cid][$key])){
            return self::$pool[$cid][$key];
        }
        return null;
    }

    // 基于协程 `ID` 写入数据
    static function put($key, $item)
    {
        $cid = Coroutine::getCid();
        if ($cid > 0)
        {
            self::$pool[$cid][$key] = $item;
        }

    }

    // 基于协程 `ID` 删除数据
    static function delete($key = null)
    {
        $cid = Coroutine::getCid();
        if ($cid > 0)
        {
            if($key){
                unset(self::$pool[$cid][$key]);
            }else{
                unset(self::$pool[$cid]);
            }
        }
    }
}

$pool = new RedisPool();
$server = new Swoole\Http\Server('127.0.0.1', 9501);
$server->set([
    // 如开启异步安全重启, 需要在workerExit释放连接池资源
    'reload_async' => true
]);
$server->on('start', function (swoole_http_server $server) {
    var_dump($server->master_pid);
});
$server->on('workerExit', function (swoole_http_server $server) use ($pool) {
    $pool->destruct();
});
$server->on('request', function (swoole_http_request $req, swoole_http_response $resp) use ($pool) {
    //从连接池中获取一个Redis协程客户端
    $redis = $pool->get();
    //连接失败
    if ($redis === false) {
        $resp->end("ERROR");
        return;
    }
    $result = $redis->hgetall('key');
    $resp->end(var_export($result, true));
    //释放客户端,其他协程可复用此对象
    $pool->put($redis);
});
$server->start();

class RedisPool
{
    protected $available = true;
    protected $pool;

    public function __construct()
    {
        $this->pool = new SplQueue;
    }

    public function put($redis)
    {
        $this->pool->push($redis);
    }

    /**
     * @return bool|mixed|\Swoole\Coroutine\Redis
     */
    public function get()
    {
        //有空闲连接且连接池处于可用状态
        if ($this->available && count($this->pool) > 0) {
            return $this->pool->pop();
        }

        //无空闲连接,创建新连接
        $redis = new Swoole\Coroutine\Redis();
        $res = $redis->connect('127.0.0.1', 6379);
        if ($res == false) {
            return false;
        } else {
            return $redis;
        }
    }

    public function destruct()
    {
        // 连接池销毁, 置不可用状态, 防止新的客户端进入常驻连接池, 导致服务器无法平滑退出
        $this->available = false;
        while (!$this->pool->isEmpty()) {
            $this->pool->pop();
        }
    }
}

错误:
try {
    Swoole\Coroutine::create(function () {
        throw new \RuntimeException(__FILE__, __LINE__);
    });
}
catch (\Throwable $e) {
    echo $e;
}
#try/catch和throw在不同的协程中,
协程内无法捕获到此异常。
当协程退出时,发现有未捕获的异常,将引起致命错误。

正解:
function test() {
    throw new \RuntimeException(__FILE__, __LINE__);
}
Swoole\Coroutine::create(function () {
    try {
        test();
    }
    catch (\Throwable $e) {
        echo $e;
    }
});

posted @ 2022-01-26 18:10  码农编程进阶笔记  阅读(14)  评论(0编辑  收藏  举报
返回顶部 有事您Q我