Swoole协程并发调用

作者: 温新

分类: 【高性能PHP】

阅读: 2897

时间: 2021-04-24 15:12:45

Swoole协程并发调用实现原理:

  • onRequest中需要并发两个http请求,可使用go函数创建 2 个子协程,并发地请求多个URL
  • 并创建一个chan,使用use必报引用语法,传递给子协程;
  • 主协程循环调用chan-pop,等待子协程完成任务,yield进入挂起状态;
  • 并发的两个子协程其中某个完成请求时,调用chan-push将数据推送给主协程;
  • 子协程完成URL请求后退出,主协程从挂起状态中恢复,继续向下执行调用$response-end发送响应结果。

第一步:编写代码

文件:d14.php

<?php

use Swoole\Coroutine\MySQL;
use Swoole\Coroutine\Redis;

// 创建HTTP服务器
$serv = new Swoole\Http\Server("127.0.0.1", 9503, SWOOLE_BASE);

// 监听
$serv->on('Request', function ($res, $resp) {
	// 创建通道
	$chan = new chan(2);

	// 创建协程
	go(function () use ($chan) {
		var_dump(time());

		// 连接mysql
		$mysql = new MySQL();
		$mysql->connect([
        'host'     => '127.0.0.1',
        'user'     => 'root',
        'password' => '123456',
        'database' => 'test',
    	]);
    	$result = $mysql->query('select sleep(3)');
    	// 将结果推送给主协程
		$chan->push($result);
	});

	go(function () use ($chan) {
		var_dump(time());

		$redis1 = new Redis();
    	$redis1->connect('127.0.0.1', 6379);
    	$result = $redis1->set('hello','swoole');

    	$chan->push($result);
	});

	go(function () use ($chan) {
		var_dump(time());

		$redis2 = new Redis();
    	$redis2->connect('127.0.0.1', 6379);
    	$result = $redis2->get('hello');

    	$chan->push($result);
	});

	// 从通道中读取数据并存入数组
	$results = [];
	for ($i = 0; $i < 3; $i++) {
		$results[] = $chan->pop();
	}

	// 响应请求
	$resp->end(json_encode([
		'data'	=>	$results,
		'time'	=>	time()
	]));

});


$serv->start();

第二步:运行http服务器

php d14.php

第三步:浏览器中访问

http://192.168.172.130:9503/

// 页面输出结果
{"data":["swoole",true,[{"sleep(3)":"0"}]],"time":1619270058}

第四步:查看http服务器

int(1619270058)
int(1619270058)
int(1619270058)

可以看到打印三个客户端请求时间是一致的,说明它们是并发执行的。

2021-04-21

请登录后再评论