Swoole 从 v4.4.13
版本开始提供了内置协程连接池,本章节会说明如何使用对应的连接池。
ConnectionPool,原始连接池,基于 Channel 自动调度,支持传入任意构造器 (callable
),构造器需返回一个连接对象
get
方法获取连接(连接池未满时会创建新的连接)
put
方法回收连接
fill
方法填充连接池(提前创建连接)
close
关闭连接池
Simps 框架 的 DB 组件 基于 Database 进行封装,实现了自动归还连接、事务等功能,可以进行参考或直接使用,具体可查看 Simps 文档
各种数据库连接池和对象代理的高级封装,支持自动断线重连。目前包含 PDO,Mysqli,Redis 三种类型的数据库支持:
PDOConfig
, PDOProxy
, PDOPool
MysqliConfig
, MysqliProxy
, MysqliPool
RedisConfig
, RedisProxy
, RedisPool
1. MySQL 断线重连可自动恢复大部分连接上下文 (fetch 模式,已设置的 attribute,已编译的 Statement 等等),但诸如事务等上下文无法恢复,若处于事务中的连接断开,将会抛出异常,请自行评估重连的可靠性;
2. 将处于事务中的连接归还给连接池是未定义行为,开发者需要自己保证归还的连接是可重用的;
3. 若有连接对象出现异常不可重用,开发者需要调用 $pool->put(null);
归还一个空连接以保证连接池的数量平衡。
用于创建连接池对象,存在两个参数,分别为对应的 Config 对象和连接池 size
$pool = new \Swoole\Database\PDOPool(Swoole\Database\PDOConfig $config, int $size); $pool = new \Swoole\Database\MysqliPool(Swoole\Database\MysqliConfig $config, int $size); $pool = new \Swoole\Database\RedisPool(Swoole\Database\RedisConfig $config, int $size);
参数
功能:连接池数量
默认值:64
其它值:无
功能:对应的 Config 对象,具体使用可参考下文的使用示例
默认值:无
其它值:【PDOConfig、RedisConfig、MysqliConfig】
$config
int $size
<?php declare(strict_types=1); use Swoole\Coroutine; use Swoole\Database\PDOConfig; use Swoole\Database\PDOPool; use Swoole\Runtime; const N = 1024; Runtime::enableCoroutine(); $s = microtime(true); Coroutine\run(function () { $pool = new PDOPool((new PDOConfig) ->withHost('127.0.0.1') ->withPort(3306) // ->withUnixSocket('/tmp/mysql.sock') ->withDbName('test') ->withCharset('utf8mb4') ->withUsername('root') ->withPassword('root') ); for ($n = N; $n--;) { Coroutine::create(function () use ($pool) { $pdo = $pool->get(); $statement = $pdo->prepare('SELECT ? + ?'); if (!$statement) { throw new RuntimeException('Prepare failed'); } $a = mt_rand(1, 100); $b = mt_rand(1, 100); $result = $statement->execute([$a, $b]); if (!$result) { throw new RuntimeException('Execute failed'); } $result = $statement->fetchAll(); if ($a + $b !== (int)$result[0][0]) { throw new RuntimeException('Bad result'); } $pool->put($pdo); }); } }); $s = microtime(true) - $s; echo 'Use ' . $s . 's for ' . N . ' queries' . PHP_EOL;
<?php declare(strict_types=1); use Swoole\Coroutine; use Swoole\Database\RedisConfig; use Swoole\Database\RedisPool; use Swoole\Runtime; const N = 1024; Runtime::enableCoroutine(); $s = microtime(true); Coroutine\run(function () { $pool = new RedisPool((new RedisConfig) ->withHost('127.0.0.1') ->withPort(6379) ->withAuth('') ->withDbIndex(0) ->withTimeout(1) ); for ($n = N; $n--;) { Coroutine::create(function () use ($pool) { $redis = $pool->get(); $result = $redis->set('foo', 'bar'); if (!$result) { throw new RuntimeException('Set failed'); } $result = $redis->get('foo'); if ($result !== 'bar') { throw new RuntimeException('Get failed'); } $pool->put($redis); }); } }); $s = microtime(true) - $s; echo 'Use ' . $s . 's for ' . (N * 2) . ' queries' . PHP_EOL;
<?php declare(strict_types=1); use Swoole\Coroutine; use Swoole\Database\MysqliConfig; use Swoole\Database\MysqliPool; use Swoole\Runtime; const N = 1024; Runtime::enableCoroutine(); $s = microtime(true); Coroutine\run(function () { $pool = new MysqliPool((new MysqliConfig) ->withHost('127.0.0.1') ->withPort(3306) // ->withUnixSocket('/tmp/mysql.sock') ->withDbName('test') ->withCharset('utf8mb4') ->withUsername('root') ->withPassword('root') ); for ($n = N; $n--;) { Coroutine::create(function () use ($pool) { $mysqli = $pool->get(); $statement = $mysqli->prepare('SELECT ? + ?'); if (!$statement) { throw new RuntimeException('Prepare failed'); } $a = mt_rand(1, 100); $b = mt_rand(1, 100); if (!$statement->bind_param('dd', $a, $b)) { throw new RuntimeException('Bind param failed'); } if (!$statement->execute()) { throw new RuntimeException('Execute failed'); } if (!$statement->bind_result($result)) { throw new RuntimeException('Bind result failed'); } if (!$statement->fetch()) { throw new RuntimeException('Fetch failed'); } if ($a + $b !== (int)$result) { throw new RuntimeException('Bad result'); } while ($statement->fetch()) { continue; } $pool->put($mysqli); }); } }); $s = microtime(true) - $s; echo 'Use ' . $s . 's for ' . N . ' queries' . PHP_EOL;