使用协程的优势

Swoole是高性能异步框架,正因为异步所以高性能,但是异步也有异步的不好,写逻辑代码有时候就非常的不方便,需要多层嵌套回调,弄得代码的可读性很差维护起来非常的不方便,那么如何解决这个弊端呢?那就是使用协程。

SwooleDistributed框架提供了一套基于yield关键字的协程写法。

回调风格和协程风格的区别

举例说明:

回调风格:

    /**
     * mysql 测试
     * @throws \Server\CoreBase\SwooleException
     */
    public function mysql_test()
    {
        $this->mysql_pool->dbQueryBuilder->select('*')->from('account')->where('sex', 1);
        $this->mysql_pool->query(function ($result) {
            print_r($result);
        });
        $this->destroy();
    }

协程风格:

    /**
     * mysql 测试
     * @throws \Server\CoreBase\SwooleException
     */
    public function mysql_test()
    {
        $mySqlCoroutine = $this->mysql_pool->dbQueryBuilder->select('*')->from('account')->where('sex', 1)->coroutineSend();
        $result = yield $mySqlCoroutine;
        print_r($result);
        $this->destroy();
    }

上述代码还只是基础,想想看多次请求并且依赖的情况 回调风格:

    public function test($callback)
    {
        $this->redis_pool->get('test',function ($uid)use($callback){
            $this->mysql_pool->dbQueryBuilder->select('*')->from('account')->where('uid', $uid);
            $this->mysql_pool->query(function ($result)use($callback) {
                call_user_func($callback,$result);
            });
        });
    }

协程风格:

    public function test()
    {
        $redisCoroutine = $this->redis_pool->getCoroutine()->get('test');
        $uid = yield $redisCoroutine;
        $mySqlCoroutine = $this->mysql_pool->dbQueryBuilder->select('*')->from('account')->where('uid', $uid)->coroutineSend();
        $result = yield $mySqlCoroutine;
        return $result;
    }

上面的代码是在一个model中,按照以往的回调风格,controller调用这个model还需要传进去一个回调函数才能获取到值(我觉得这么做的人一定会疯),而协程风格你只需要按部就班的return结果就行了。和同步的代码唯一的区别就是多了一个yield关键字。

好了我们再看调用这个model的controller怎么写。
回调风格:

    /**
     * 非协程测试
     */
    public function http_testNOCoroutine()
    {
        $this->testModel = $this->loader->model('TestModel', $this);
        $this->testModel->test(function($result){
           $this->http_output->end($result);
        });        
    }

协程风格:

    /**
     * 协程测试
     */
    public function http_testCoroutine()
    {
        $this->testModel = $this->loader->model('TestModel', $this);
        $result = yield $this->testModel->test();
        $this->http_output->end($result);
    }

同样只是要多加一个yield关键字。是不是很方便~,注意只有这个model的方法内使用了yield,控制器调用的时候才需要加yield关键字。普通的方法是不需要的,当然你加了也不会报错。

协程中的异常?

swooleDistributed框架已经将协程的使用变得很方便了,至于异常和平常的写法一毛一样。

    public function test_exceptionII()
    {
        $mySqlCoroutine = $this->mysql_pool->dbQueryBuilder->select('*')->from('account')->where('uid', 10303)->coroutineSend();
        $result = yield $mySqlCoroutine;
        throw new \Exception('test');
    }

无论你是在model中还是在controller中,还是在model的model中。。。。
总之throw出来就行,上一层使用try可以捕获到错误。
这里还有个小小的体验优化,当报错一直到controller层的时候,会被controller的onExceptionHandle捕获到,你可以重写这个函数实现异常情况下的客户端回复。

协程的嵌套

随便嵌套。enjoy yourself。

协程的调度顺序

调节yield的位置即可调节接收的顺序。

    $redisCoroutine = $this->redis_pool->getCoroutine()->get('test');
    $uid = yield $redisCoroutine;
    $mySqlCoroutine = $this->mysql_pool->dbQueryBuilder->select('*')->from('account')->where('uid', $uid)->coroutineSend();
    $result = yield $mySqlCoroutine;

上面的代码调度顺序是redis_send->redis_rev->mysql_send->mysql_rev。

    $redisCoroutine = $this->redis_pool->getCoroutine()->get('test');
    $mySqlCoroutine = $this->mysql_pool->dbQueryBuilder->select('*')->from('account')->where(123, $uid)->coroutineSend();
    $uid = yield $redisCoroutine;
    $result = yield $mySqlCoroutine;

上面的代码调度顺序是redis_send->mysql_send->redis_rev->mysql_rev。

results matching ""

    No results matching ""