Pool 연결 풀
여러 코루틴이 동일한 연결을 공유하면 데이터가 혼란스러워질 수 있으므로, 데이터베이스, redis 등의 연결 리소스를 관리하기 위해 연결 풀을 사용해야 합니다.
팁
이 기능은 workerman>=5.1.0이 필요합니다.
주의
- 바닥에서 자동으로 Swoole/Swow/Fiber/Select/Event 드라이버를 지원합니다.
- Fiber/Select/Event 드라이버를 사용할 때, 블로킹 확장인 PDO redis 등을 사용하는 경우, 자동으로 단일 연결의 연결 풀로 하위 격화됩니다.
Redis 연결 풀
<?php
use Workerman\Connection\TcpConnection;
use Workerman\Coroutine\Pool;
use Workerman\Events\Swoole;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
class RedisPool
{
private Pool $pool;
public function __construct($host, $port, $max_connections = 10)
{
$this->pool = new Pool($max_connections);
// 연결 풀 생성 방법 설정
$this->pool->setConnectionCreator(function () use ($host, $port) {
$redis = new \Redis();
$redis->connect($host, $port);
return $redis;
});
// 연결 풀 파괴 방법 설정
$this->pool->setConnectionCloser(function ($redis) {
$redis->close();
});
// 심장 박동 검사 방법 설정
$this->pool->setHeartbeatChecker(function ($redis) {
$redis->ping();
});
}
// 연결 가져오기
public function get(): \Redis
{
return $this->pool->get();
}
// 연결 반납
public function put($redis): void
{
$this->pool->put($redis);
}
}
// Http 서버
$worker = new Worker('http://0.0.0.0:8001');
$worker->eventLoop = Swoole::class; // 또는 Swow::class 또는 Fiber::class
$worker->onMessage = function (TcpConnection $connection, Request $request) {
static $pool;
if (!$pool) {
$pool = new RedisPool('127.0.0.1', 6379, 10);
}
$redis = $pool->get();
$redis->set('key', 'hello');
$value = $redis->get('key');
$pool->put($redis);
$connection->send($value);
};
Worker::runAll();
MySQL 연결 풀(자동으로 연결 가져오기 및 반납 지원)
<?php
use Workerman\Connection\TcpConnection;
use Workerman\Coroutine\Context;
use Workerman\Coroutine;
use Workerman\Coroutine\Pool;
use Workerman\Events\Swoole;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
class Db
{
private static ?Pool $pool = null;
public static function __callStatic($name, $arguments)
{
if (self::$pool === null) {
self::initializePool();
}
// 코루틴 컨텍스트에서 연결 가져오기, 같은 코루틴이 동일한 연결을 사용하도록 보장
$pdo = Context::get('pdo');
if (!$pdo) {
// 연결 풀에서 연결 가져오기
$pdo = self::$pool->get();
Context::set('pdo', $pdo);
// 코루틴이 종료될 때 자동으로 연결 반납
Coroutine::defer(function () use ($pdo) {
self::$pool->put($pdo);
});
}
return call_user_func_array([$pdo, $name], $arguments);
}
private static function initializePool(): void
{
self::$pool = new Pool(10);
self::$pool->setConnectionCreator(function () {
return new \PDO('mysql:host=127.0.0.1;dbname=your_database', 'your_username', 'your_password');
});
self::$pool->setConnectionCloser(function ($pdo) {
$pdo = null;
});
self::$pool->setHeartbeatChecker(function ($pdo) {
$pdo->query('SELECT 1');
});
}
}
// Http 서버
$worker = new Worker('http://0.0.0.0:8001');
$worker->eventLoop = Swoole::class; // 또는 Swow::class 또는 Fiber::class
$worker->onMessage = function (TcpConnection $connection, Request $request) {
$value = Db::query('SELECT NOW() as now')->fetchAll();
$connection->send(json_encode($value));
};
Worker::runAll();
인터페이스 설명
interface PoolInterface
{
/**
* 생성자
* @param int $max_connections 최대 연결 수, 기본값 1
* @param array $config = [
* 'min_connections' => 1, // 최소 연결 수, 기본값 1
* 'idle_timeout' => 60, // 연결 공백 초과 시간(초), 기본값 60초, 60초를 초과하면 연결이 파괴되어 연결 풀에서 제거됨
* 'heartbeat_interval' => 50, // 심장 박동 검사 간격(초), 기본값 50초, 매 50초마다 연결이 정상인지 확인
* 'wait_timeout' => 10, // 연결을 가져오기 위한 대기 초과 시간(초), 기본값 10초, 10초를 초과하면 연결을 가져오지 못하고 예외 발생
* ]
*/
public function __construct(int $max_connections = 1, array $config = []);
/**
* 연결 하나 가져오기
*/
public function get(): mixed;
/**
* 연결 하나 반납하기
*/
public function put(object $connection): void;
/**
* 연결 하나 생성하기
*/
public function createConnection(): object;
/**
* 연결을 닫고 연결 풀에서 제거하기
*/
public function closeConnection(object $connection): void;
/**
* 연결 풀에서 현재 연결 수 가져오기(사용 중인 연결과 사용하지 않는 연결 포함)
*/
public function getConnectionCount(): int;
/**
* 연결 풀에서 연결 닫기(사용 중인 연결 제외)
*/
public function closeConnections(): void;
/**
* 연결 풀 생성 연결 방법 설정
*/
public function setConnectionCreator(callable $connectionCreateHandler): self;
/**
* 연결 풀 파괴 연결 방법 설정
*/
public function setConnectionCloser(callable $connectionDestroyHandler): self;
/**
* 심장 박동 검사 방법 설정
*/
public function setHeartbeatChecker(callable $connectionHeartbeatHandler): self;
}