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, // সংযোগের আয়_IDLE_TIMEOUT (সেকেন্ড), ডিফল্ট 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;

}