v4.1
开始支持,TCP Socket 类型的 stream,包括最常见的 Redis
、PDO
、Mysqli
以及用 PHP 的 streams 系列函数操作 TCP 连接的操作,都可以 Hook
,示例:
Co::set(['hook_flags' => SWOOLE_HOOK_TCP]);
Co\run(function() {
for ($c = 100; $c--;) {
go(function () {//创建100个协程
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);//此处产生协程调度,cpu切到下一个协程,不会阻塞进程
$redis->get('key');//此处产生协程调度,cpu切到下一个协程,不会阻塞进程
});
}
});
上述代码使用的就是原生的 Redis
类,但是其实已经变成了异步IO
,Co\run()
是创建了协程容器,go()
是创建协程,这两个操作在 Swoole
提供的 Swoole\Server 类簇都是自动做好的,不需要手动做,参考 enable_coroutine。
也就是说传统的 PHP
程序员用最熟悉的逻辑代码就能写出高并发、高性能的程序,如下:
Co::set(['hook_flags' => SWOOLE_HOOK_TCP]);
$http = new Swoole\Http\Server("0.0.0.0", 9501);
$http->set(['enable_coroutine' => true]);
$http->on('request', function ($request, $response) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);//此处产生协程调度,cpu切到下一个协程(下一个请求),不会阻塞进程
$redis->get('key');//此处产生协程调度,cpu切到下一个协程(下一个请求),不会阻塞进程
});
$http->start();
开启 enable_coroutine
后在上述回调函数会自动创建协程
- 当
enable_coroutine
设置为true
时,底层自动在 onRequest 回调中创建协程,开发者无需自行使用go
函数创建协程 - 当
enable_coroutine
设置为false
时,底层不会自动创建协程,开发者如果要使用协程,必须使用go
自行创建协程,如果不需要使用协程特性,则处理方式与Swoole1.x
是 100% 一致的
$server = new Swoole\Http\Server("127.0.0.1", 9501);
$server->set([
//关闭内置协程
'enable_coroutine' => false,//默认开启
'max_coroutine' => 3000,//设置协程最大数量
'send_yield' => false,//当发送数据时缓冲区内存不足时,直接在当前协程内 yield,等待数据发送完成,缓存区清空时,自动 resume 当前协程,继续 send 数据。【默认值:在 dispatch_mod 2/4 时候可用,并默认开启】
]);
$server->on("request", function ($request, $response) {
if ($request->server['request_uri'] == '/coro') {
go(function () use ($response) {
co::sleep(0.2);
$response->header("Content-Type", "text/plain");
$response->end("Hello World\n");
});
} else {
$response->header("Content-Type", "text/plain");
$response->end("Hello World\n");
}
});
$server->start();
原文参考:
https://wiki.swoole.com/#/runtime?id=swoole_hook_tcp
https://wiki.swoole.com/#/server/setting?id=enable_coroutine