Pool Bağlantı Havuzu
Birden fazla koroutine aynı bağlantıyı paylaşırsa veri karışıklığı meydana gelebilir, bu nedenle veri tabanı, redis gibi bağlantı kaynaklarını yönetmek için bir bağlantı havuzu kullanmak gereklidir.
İpucu
Bu özellik workerman>=5.1.0 gerektirir.
Dikkat
- Alt yapı otomatik olarak Swoole/Swow/Fiber/Select/Event tabanlı destek sunar
- Eğer Fiber/Select/Event tabanlı kullanılıyorsa ve PDO redis gibi engelleyici uzantılar kullanılıyorsa, otomatik olarak yalnızca bir bağlantıya sahip bir bağlantı havuzuna düşer
Redis Bağlantı Havuzu
<?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);
// Bağlantı havuzunun bağlantı kurma yöntemini ayarlayın
$this->pool->setConnectionCreator(function () use ($host, $port) {
$redis = new \Redis();
$redis->connect($host, $port);
return $redis;
});
// Bağlantı havuzunun bağlantı kapatma yöntemini ayarlayın
$this->pool->setConnectionCloser(function ($redis) {
$redis->close();
});
// Kalp atışı kontrol yöntemini ayarlayın
$this->pool->setHeartbeatChecker(function ($redis) {
$redis->ping();
});
}
// Bağlantıyı al
public function get(): \Redis
{
return $this->pool->get();
}
// Bağlantıyı iade et
public function put($redis): void
{
$this->pool->put($redis);
}
}
// Http Sunucusu
$worker = new Worker('http://0.0.0.0:8001');
$worker->eventLoop = Swoole::class; // Veya Swow::class veya 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 Bağlantı Havuzu (otomatik alım ve iade desteği)
<?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();
}
// Koroutin bağlamından bağlantıyı al, aynı koroutine'nin aynı bağlantıyı kullanmasını sağla
$pdo = Context::get('pdo');
if (!$pdo) {
// Bağlantı havuzundan bağlantıyı al
$pdo = self::$pool->get();
Context::set('pdo', $pdo);
// Koroutine sona erdiğinde, bağlantıyı otomatik olarak geri ver
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 Sunucusu
$worker = new Worker('http://0.0.0.0:8001');
$worker->eventLoop = Swoole::class; // Veya Swow::class veya Fiber::class
$worker->onMessage = function (TcpConnection $connection, Request $request) {
$value = Db::query('SELECT NOW() as now')->fetchAll();
$connection->send(json_encode($value));
};
Worker::runAll();
Arayüz Tanımı
interface PoolInterface
{
/**
* Yapıcı fonksiyon
* @param int $max_connections Maksimum bağlantı sayısı, varsayılan 1
* @param array $config = [
* 'min_connections' => 1, // Minimum bağlantı sayısı, varsayılan 1
* 'idle_timeout' => 60, // Bağlantı boşta kalma süresi (saniye), varsayılan 60 saniye, 60 saniyeden uzun süre boşta kalan bağlantılar yok edilir ve bağlantı havuzundan çıkar
* 'heartbeat_interval => 50, // Kalp atışı kontrol aralığı (saniye), varsayılan 50 saniye, her 50 saniyede bir bağlantının durumunu kontrol eder
* 'wait_timeout' => 10, // Bağlantı alımında bekleme süresi (saniye), varsayılan 10 saniye, 10 saniyeden uzun süre bağlantı alınamazsa istisna fırlatılır
* ]
*/
public function __construct(int $max_connections = 1, array $config = []);
/**
* Bir bağlantı al
*/
public function get(): mixed;
/**
* Bir bağlantıyı iade et
*/
public function put(object $connection): void;
/**
* Bir bağlantı oluştur
*/
public function createConnection(): object;
/**
* Bağlantıyı kapat ve bağlantı havuzundan çıkar
*/
public function closeConnection(object $connection): void;
/**
* Bağlantı havuzundaki mevcut bağlantı sayısını al (kullanımda olan bağlantılar ve kullanılmayan bağlantılar dahil)
*/
public function getConnectionCount(): int;
/**
* Bağlantı havuzundaki bağlantıları kapat (kullanımda olan bağlantılar dahil değil)
*/
public function closeConnections(): void;
/**
* Bağlantı havuzunun bağlantı oluşturma yöntemini ayarlayın
*/
public function setConnectionCreator(callable $connectionCreateHandler): self;
/**
* Bağlantı havuzunun bağlantı kapatma yöntemini ayarlayın
*/
public function setConnectionCloser(callable $connectionDestroyHandler): self;
/**
* Kalp atışı kontrol yöntemini ayarlayın
*/
public function setHeartbeatChecker(callable $connectionHeartbeatHandler): self;
}