美文网首页
Hyperf框架中开协程的几种方式

Hyperf框架中开协程的几种方式

作者: 左诗右码 | 来源:发表于2024-03-18 00:06 被阅读0次

    基于 Hyperf 框架开协程的几种方式,你用过哪几种呢?

    首先我们先在控制器中写一个方法,用于测试,本地默认启用 9516 端口,则测试路由为 127.0.0.1:9516/co/sleep

    
    <?php
    /**
     * 开协程做请求
     *
     * Created by PhpStorm
     * User: Alex
     * Date: 2021-09-21 19:22
     */
    declare(strict_types=1);
    
    namespace App\Controller;
    
    use Hyperf\Utils\Parallel;
    use Hyperf\Utils\WaitGroup;
    use Swoole\Coroutine\Channel;
    use Hyperf\Guzzle\ClientFactory;
    use Hyperf\HttpServer\Annotation\AutoController;
    use Hyperf\HttpServer\Contract\RequestInterface;
    use Hyperf\Di\Annotation\Inject;
    
    /**
     * @AutoController
     * Class CoController
     * @package App\Controller
     */
    class CoController
    {
    
        /**
         * @Inject
         * @var ClientFactory
         */
        private $clientFactory;
    
        /**
         * 方便测试超时操作
         *
         * @param RequestInterface $request
         * @return mixed
         */
        public function sleep(RequestInterface $request)
        {
            $seconds = $request->query('seconds', 1);
            sleep((int)$seconds);
            var_dump('sleep hello ====> ' . $seconds);
            return $seconds;
        }
    
    }
    
    

    第一种方式:使用 Channel 类做协程请求

    /**
     * 使用 Channel 做协程请求
     *
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function test()
    {
        $channel = new Channel();
    
        co(function () use ($channel) {
            $client = $this->clientFactory->create();
            $client->get('127.0.0.1:9516/co/sleep?seconds=2');
            $channel->push(123);
        });
    
        co(function () use ($channel) {
            $client = $this->clientFactory->create();
            $client->get('127.0.0.1:9516/co/sleep?seconds=2');
            $channel->push(321);
        });
    
        $result[] = $channel->pop();  // 第一个协程返回的结果
        $result[] = $channel->pop();  // 第二个协程返回的结果
    
        return $result;  // [123, 321]
    }
    

    第二种方式:使用 WaitGroup 类做协程请求

    /**
     * 使用 WaitGroup 做协程请求
     *
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function test1()
    {
        // 通过子协程并行的发起多个请求实现并行请求
        $wg = new WaitGroup();
        $wg->add(2);  // 因为开了两个协程,因此就要添加 2
    
        $result = [];
        co(function () use ($wg, &$result) {
            $client = $this->clientFactory->create();
            $client->get('127.0.0.1:9516/co/sleep?seconds=2');
            $result[] = 123;
            $wg->done();
        });
    
        co(function () use ($wg, &$result) {
            $client = $this->clientFactory->create();
            $client->get('127.0.0.1:9516/co/sleep?seconds=2');
            $result[] = 321;
            $wg->done();
        });
    
        $wg->wait();  // 等待 add 计数器变为 0
    
        return $result;  // [321, 123]
    }
    
    

    第三种方式:使用 Parallel 类,做协程请求

    /**
     * 使用 Parallel 类,做协程请求
     *
     * @return array
     */
    public function test2()
    {
        $parallel = new Parallel();
    
        $parallel->add(function () {
            $client = $this->clientFactory->create();
            $client->get('127.0.0.1:9516/co/sleep?seconds=2');
            return 123;
        }, 'foo');
    
        $parallel->add(function () {
            $client = $this->clientFactory->create();
            $client->get('127.0.0.1:9516/co/sleep?seconds=2');
            return 321;
        }, 'bar');
    
        $result = $parallel->wait();
    
        return $result;  // {"foo":123,"bar":321}
    }
    

    第四种方式:使用 parallel 助手函数,做协程请求

    /**
     * 使用 parallel 助手函数,做协程请求
     *
     * @return array
     */
    public function test3()
    {
        $result = parallel([
            'foo' => function () {
                $client = $this->clientFactory->create();
                $client->get('127.0.0.1:9516/co/sleep?seconds=2');
                return 123;
            },
            'bar' => function () {
                $client = $this->clientFactory->create();
                $client->get('127.0.0.1:9516/co/sleep?seconds=2');
                return 321;
            },
        ]);
    
        return $result;  // {"foo":123,"bar":321}
    }
    

    以上 4 种方式,如果你非要说让我推荐哪种,个人还是比较提倡使用 parallel助手函数的方式,感兴趣的童鞋可以去看看 parallel 助手函数的源码,你会发现其实也是使用到了 WaitGroup 类,并且还帮你处理了协程中可能会出现的异常情况,这样你在使用起来的时候就会更加方便且安全。

    但是至于你最终选择哪个,完全取决于你的个人习惯,怎么顺手怎么来就行。

    相关文章

      网友评论

          本文标题:Hyperf框架中开协程的几种方式

          本文链接:https://www.haomeiwen.com/subject/eazozdtx.html